diff options
Diffstat (limited to 'src/CommonAPI')
61 files changed, 1790 insertions, 7828 deletions
diff --git a/src/CommonAPI/DBus/DBusAddress.cpp b/src/CommonAPI/DBus/DBusAddress.cpp new file mode 100644 index 0000000..f317e57 --- /dev/null +++ b/src/CommonAPI/DBus/DBusAddress.cpp @@ -0,0 +1,102 @@ +// Copyright (C) 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 <algorithm> + +#include <CommonAPI/DBus/DBusAddress.hpp> + +namespace CommonAPI { +namespace DBus { + +DBusAddress::DBusAddress(const std::string &_service, + 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_) { +} + +DBusAddress::~DBusAddress() { +} + +bool +DBusAddress::operator==(const DBusAddress &_other) const { + 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_); +} + +bool +DBusAddress::operator<(const DBusAddress &_other) const { + if (service_ < _other.service_) + return true; + + if (service_ == _other.service_) { + if (objectPath_ < _other.objectPath_) + return true; + + if (objectPath_ == _other.objectPath_) { + if (interface_ < _other.interface_) + return true; + } + } + + return false; +} + +const std::string & +DBusAddress::getService() const { + return service_; +} + +void +DBusAddress::setService(const std::string &_service) { + service_ = _service; +} + +const std::string & +DBusAddress::getObjectPath() const { + return objectPath_; +} + +void +DBusAddress::setObjectPath(const std::string &_objectPath) { + objectPath_ = _objectPath; +} + +const std::string & +DBusAddress::getInterface() const { + return interface_; +} + +void +DBusAddress::setInterface(const std::string &_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; +} + + +} // namespace DBus +} // namespace CommonAPI diff --git a/src/CommonAPI/DBus/DBusAddressTranslator.cpp b/src/CommonAPI/DBus/DBusAddressTranslator.cpp index 92f432c..5c5e3f1 100644 --- a/src/CommonAPI/DBus/DBusAddressTranslator.cpp +++ b/src/CommonAPI/DBus/DBusAddressTranslator.cpp @@ -1,149 +1,295 @@ -/* Copyright (C) 2013 BMW Group - * Author: Manfred Bathelt (manfred.bathelt@bmw.de) - * Author: Juergen Gehring (juergen.gehring@bmw.de) - * 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/. */ +// 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 <Windows.h> +#else +#include <unistd.h> +#endif -#include <CommonAPI/utils.h> +#include <sys/stat.h> -#include "DBusAddressTranslator.h" - -#include "DBusConnection.h" -#include "DBusFactory.h" - -#include "DBusConnection.h" -#include "DBusFactory.h" - -#include <unordered_set> -#include <string.h> -#include <iostream> -#include <fstream> -#include <cassert> -#include <sstream> +#include <algorithm> +#include <CommonAPI/IniFileReader.hpp> +#include <CommonAPI/Logger.hpp> +#include <CommonAPI/Runtime.hpp> +#include <CommonAPI/DBus/DBusAddressTranslator.hpp> namespace CommonAPI { namespace DBus { +const char *COMMONAPI_DBUS_DEFAULT_CONFIG_FILE = "commonapi-dbus.ini"; +const char *COMMONAPI_DBUS_DEFAULT_CONFIG_FOLDER = "/etc/"; + +const std::size_t DBUS_MAXIMUM_NAME_LENGTH = 255; -DBusAddressTranslator::DBusAddressTranslator() {} +static std::shared_ptr<DBusAddressTranslator> theTranslator = std::make_shared<DBusAddressTranslator>(); -void DBusAddressTranslator::init() { - commonApiAddressDetails_ = DBusConfiguration::getInstance().getCommonApiAddressDetails(); - for (auto& addressDetail: commonApiAddressDetails_) { - fillUndefinedValues(addressDetail.second, addressDetail.first); - DBusServiceAddress dbusServiceDefinition = std::get<0>(addressDetail.second); - dbusToCommonApiAddress_.insert( {dbusServiceDefinition, addressDetail.first}); - } +std::shared_ptr<DBusAddressTranslator> DBusAddressTranslator::get() { + return theTranslator; } -DBusAddressTranslator& DBusAddressTranslator::getInstance() { - static DBusAddressTranslator* dbusAddressTranslator; - if(!dbusAddressTranslator) { - dbusAddressTranslator = new DBusAddressTranslator(); - dbusAddressTranslator->init(); - } - return *dbusAddressTranslator; +DBusAddressTranslator::DBusAddressTranslator() + : defaultDomain_("local") { + init(); + + 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 DBusAddressTranslator::searchForDBusAddress(const std::string& domain, - const std::string& interf, - const std::string& instance, - std::string& interfaceName, - std::string& connectionName, - std::string& objectPath) { - std::stringstream ss; - ss << domain << ":" << interf << ":" << instance; - searchForDBusAddress(ss.str(), interfaceName, connectionName, objectPath); + (void)readConfiguration(); } -void DBusAddressTranslator::searchForDBusAddress(const std::string& commonApiAddress, - std::string& interfaceName, - std::string& connectionName, - std::string& objectPath) { - - const auto& foundAddressMapping = commonApiAddressDetails_.find(commonApiAddress); - - if (foundAddressMapping != commonApiAddressDetails_.end()) { - connectionName = std::get<0>(std::get<0>(foundAddressMapping->second)); - objectPath = std::get<1>(std::get<0>(foundAddressMapping->second)); - interfaceName = std::get<2>(std::get<0>(foundAddressMapping->second)); - } else { - findFallbackDBusAddress(commonApiAddress, interfaceName, connectionName, objectPath); - commonApiAddressDetails_.insert( {commonApiAddress, std::make_tuple(std::make_tuple(connectionName, objectPath, interfaceName), false) } ); - } +bool +DBusAddressTranslator::translate(const std::string &_key, DBusAddress &_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()); -void DBusAddressTranslator::fillUndefinedValues(CommonApiServiceDetails& serviceDetails, const std::string& commonApiAddress) const { - std::string connectionName; - std::string objectPath; - std::string interfaceName; + if (isValid(service, '.', false, false, true) + && isValid(objectPath, '/', true) + && isValid(interfaceName, '.')) { + _value.setInterface(interfaceName); + _value.setObjectPath(objectPath); + _value.setService(service); - findFallbackDBusAddress(commonApiAddress, interfaceName, connectionName, objectPath); + forwards_.insert({ _key, _value }); + backwards_.insert({ _value, _key }); + } + } else { + result = false; + } - std::get<0>(std::get<0>(serviceDetails)) = std::get<0>(std::get<0>(serviceDetails)) == "" ? connectionName : std::get<0>(std::get<0>(serviceDetails)); - std::get<1>(std::get<0>(serviceDetails)) = std::get<1>(std::get<0>(serviceDetails)) == "" ? objectPath : std::get<1>(std::get<0>(serviceDetails)); - std::get<2>(std::get<0>(serviceDetails)) = std::get<2>(std::get<0>(serviceDetails)) == "" ? interfaceName : std::get<2>(std::get<0>(serviceDetails)); + 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; +} -void DBusAddressTranslator::searchForCommonAddress(const std::string& interfaceName, - const std::string& connectionName, - const std::string& objectPath, - std::string& commonApiAddress) { +bool +DBusAddressTranslator::translate(const DBusAddress &_key, CommonAPI::Address &_value) { + bool result(true); + std::lock_guard<std::mutex> itsLock(mutex_); - DBusServiceAddress dbusAddress(connectionName, objectPath, interfaceName); + 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(), '/', '.'); - const auto& foundAddressMapping = dbusToCommonApiAddress_.find(dbusAddress); - if (foundAddressMapping != dbusToCommonApiAddress_.end()) { - commonApiAddress = foundAddressMapping->second; - } else { - findFallbackCommonAddress(commonApiAddress, interfaceName, connectionName, objectPath); - dbusToCommonApiAddress_.insert( {std::move(dbusAddress), commonApiAddress} ); - } -} + _value.setDomain(defaultDomain_); + _value.setInterface(interfaceName); + _value.setInstance(instance); -void DBusAddressTranslator::getPredefinedInstances(const std::string& connectionName, - std::vector<DBusServiceAddress>& instances) { - instances.clear(); - auto dbusAddress = commonApiAddressDetails_.begin(); - while (dbusAddress != commonApiAddressDetails_.end()) { - CommonApiServiceDetails serviceDetails = dbusAddress->second; - if (connectionName == std::get<0>(std::get<0>(serviceDetails)) - && true == std::get<1>(serviceDetails)) { - instances.push_back(std::get<0>(serviceDetails)); - } - dbusAddress++; - } + forwards_.insert({_value, _key}); + backwards_.insert({_key, _value}); + } else { + result = false; + } + } else { + result = false; + } + + return result; } -void DBusAddressTranslator::findFallbackDBusAddress(const std::string& commonApiAddress, - std::string& interfaceName, - std::string& connectionName, - std::string& objectPath) const { - std::vector<std::string> parts = split(commonApiAddress, ':'); - interfaceName = parts[1]; - connectionName = parts[2]; - objectPath = '/' + parts[2]; - std::replace(objectPath.begin(), objectPath.end(), '.', '/'); + +void +DBusAddressTranslator::insert( + const std::string &_address, + const std::string &_service, const std::string &_path, const std::string &_interface) { + + if (isValid(_service, '.', + (_service.length() > 0 && _service[0] == ':'), + (_service.length() > 0 && _service[0] == ':'), + true) + && isValid(_path, '/', true) + && 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); + } 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); + } + } } -void DBusAddressTranslator::findFallbackCommonAddress(std::string& commonApiAddress, - const std::string& interfaceName, - const std::string& connectionName, - const std::string& objectPath) const { - commonApiAddress = "local:" + interfaceName + ":" + transfromObjectPathToInstance(objectPath); +bool +DBusAddressTranslator::readConfiguration() { +#define MAX_PATH_LEN 255 + std::string config; + char currentDirectory[MAX_PATH_LEN]; +#ifdef WIN32 + if (GetCurrentDirectory(MAX_PATH_LEN, currentDirectory)) { +#else + 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()) { + 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; } -std::string DBusAddressTranslator::transfromObjectPathToInstance(const std::string& path) const { - std::string out = path.substr(1, std::string::npos); - std::replace(out.begin(), out.end(), '/', '.'); - return out; +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) + 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; } -}// namespace DBus +} // namespace DBus } // namespace CommonAPI diff --git a/src/CommonAPI/DBus/DBusAddressTranslator.h b/src/CommonAPI/DBus/DBusAddressTranslator.h deleted file mode 100644 index c1b29df..0000000 --- a/src/CommonAPI/DBus/DBusAddressTranslator.h +++ /dev/null @@ -1,84 +0,0 @@ -/* Copyright (C) 2013 BMW Group - * Author: Manfred Bathelt (manfred.bathelt@bmw.de) - * Author: Juergen Gehring (juergen.gehring@bmw.de) - * 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/. */ - -#if !defined (COMMONAPI_INTERNAL_COMPILATION) -#error "Only <CommonAPI/CommonAPI.h> can be included directly, this file may disappear or change contents." -#endif - -#ifndef COMMONAPI_DBUS_DBUS_ADDRESS_TRANSLATOR_H_ -#define COMMONAPI_DBUS_DBUS_ADDRESS_TRANSLATOR_H_ - -#include <CommonAPI/types.h> - -#include "DBusConnectionBusType.h" -#include "DBusFunctionalHash.h" -#include "DBusConfiguration.h" - -#include <algorithm> -#include <unordered_map> - - -namespace CommonAPI { -namespace DBus { - - -class DBusAddressTranslator { -public: - ~DBusAddressTranslator(); - - static DBusAddressTranslator& getInstance(); - - void searchForDBusAddress(const std::string& domain, - const std::string& interf, - const std::string& instance, - std::string& interfaceName, - std::string& connectionName, - std::string& objectPath); - - void searchForDBusAddress(const std::string& commonApiAddress, - std::string& interfaceName, - std::string& connectionName, - std::string& objectPath); - - void searchForCommonAddress(const std::string& interfaceName, - const std::string& connectionName, - const std::string& objectPath, - std::string& commonApiAddress); - - void getPredefinedInstances(const std::string& connectionName, - std::vector<DBusServiceAddress>& instances); - -private: - DBusAddressTranslator(); - DBusAddressTranslator(const DBusAddressTranslator&) = delete; - DBusAddressTranslator& operator=(const DBusAddressTranslator&) = delete; - - void init(); - - void findFallbackDBusAddress(const std::string& instanceId, - std::string& interfaceName, - std::string& connectionName, - std::string& objectPath) const; - - void findFallbackCommonAddress(std::string& instanceId, - const std::string& interfaceName, - const std::string& connectionName, - const std::string& objectPath) const; - - void fillUndefinedValues(CommonApiServiceDetails& serviceDetails, const std::string& commonApiAddress) const; - - std::string transfromObjectPathToInstance(const std::string& path) const; - - std::unordered_map<std::string, CommonApiServiceDetails> commonApiAddressDetails_; - std::unordered_map<DBusServiceAddress, std::string> dbusToCommonApiAddress_; -}; - - -}// namespace DBus -}// namespace CommonAPI - -#endif /* COMMONAPI_DBUS_DBUS_ADDRESS_TRANSLATOR_H_ */ diff --git a/src/CommonAPI/DBus/DBusAttribute.h b/src/CommonAPI/DBus/DBusAttribute.h deleted file mode 100644 index 146a190..0000000 --- a/src/CommonAPI/DBus/DBusAttribute.h +++ /dev/null @@ -1,549 +0,0 @@ -/* Copyright (C) 2013 BMW Group - * Author: Manfred Bathelt (manfred.bathelt@bmw.de) - * Author: Juergen Gehring (juergen.gehring@bmw.de) - * 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/. */ - -#if !defined (COMMONAPI_INTERNAL_COMPILATION) -#error "Only <CommonAPI/CommonAPI.h> can be included directly, this file may disappear or change contents." -#endif - -#ifndef COMMONAPI_DBUS_DBUS_ATTRIBUTE_H_ -#define COMMONAPI_DBUS_DBUS_ATTRIBUTE_H_ - -#include "DBusProxyHelper.h" -#include "DBusEvent.h" -#include <stdint.h> -#include "DBusLegacyVariant.h" - -#include <cassert> - -namespace CommonAPI { -namespace DBus { - - -class DBusProxy; - - -template <typename _AttributeType, typename _DBusProxyType = DBusProxy> -class DBusReadonlyAttribute: public _AttributeType { - public: - typedef typename _AttributeType::ValueType ValueType; - typedef typename _AttributeType::AttributeAsyncCallback AttributeAsyncCallback; - - DBusReadonlyAttribute(_DBusProxyType& dbusProxy, const char* setMethodSignature, const char* getMethodName): - dbusProxy_(dbusProxy), - getMethodName_(getMethodName), - setMethodSignature_(setMethodSignature) { - assert(getMethodName); - } - - void getValue(CallStatus& callStatus, ValueType& value) const { - - DBusProxyHelper<DBusSerializableArguments<>, - DBusSerializableArguments<ValueType> >::callMethodWithReply(dbusProxy_, getMethodName_, "", callStatus, value); - } - - std::future<CallStatus> getValueAsync(AttributeAsyncCallback attributeAsyncCallback) { - return DBusProxyHelper<DBusSerializableArguments<>, - DBusSerializableArguments<ValueType> >::callMethodAsync(dbusProxy_, getMethodName_, "", std::move(attributeAsyncCallback)); - } - - protected: - _DBusProxyType& dbusProxy_; - const char* getMethodName_; - const char* setMethodSignature_; -}; - -template <typename _AttributeType, typename _DBusProxyType = DBusProxy> -class DBusFreedesktopReadonlyAttribute: public _AttributeType { - public: - typedef typename _AttributeType::ValueType ValueType; - typedef typename _AttributeType::AttributeAsyncCallback AttributeAsyncCallback; - - DBusFreedesktopReadonlyAttribute(_DBusProxyType& dbusProxy, const char* interfaceName, const char* propertyName): - dbusProxy_(dbusProxy), - interfaceName_(interfaceName), - propertyName_(propertyName) - { - assert(interfaceName); - assert(propertyName); - } - - void getValue(CallStatus& callStatus, ValueType& value) const { - DBusLegacyVariantWrapper<Variant<ValueType> > variantVal; - DBusProxyHelper<DBusSerializableArguments<std::string, std::string>, - DBusSerializableArguments<DBusLegacyVariantWrapper<Variant<ValueType> > > >::callMethodWithReply( - dbusProxy_, - dbusProxy_.getDBusBusName().c_str(), - dbusProxy_.getDBusObjectPath().c_str(), - "org.freedesktop.DBus.Properties", - "Get", - "ss", - interfaceName_, - propertyName_, - callStatus, - variantVal); - value = variantVal.contained_.template get<ValueType>(); - - } - - std::future<CallStatus> getValueAsync(AttributeAsyncCallback attributeAsyncCallback) { - return DBusProxyHelper<DBusSerializableArguments<std::string, std::string>, - DBusSerializableArguments<DBusLegacyVariantWrapper<Variant<ValueType> > > >::callMethodAsync( - dbusProxy_, - dbusProxy_.getDBusBusName().c_str(), - dbusProxy_.getDBusObjectPath().c_str(), - "org.freedesktop.DBus.Properties", - "Get", - "ss", - interfaceName_, - propertyName_, - std::bind( - &CommonAPI::DBus::DBusFreedesktopReadonlyAttribute<_AttributeType>::AsyncVariantStripper, - this, - std::placeholders::_1, - std::placeholders::_2, - std::move(attributeAsyncCallback))); - } - - void AsyncVariantStripper(const CommonAPI::CallStatus& status, - const DBusLegacyVariantWrapper<Variant<ValueType> >& value, - AttributeAsyncCallback attributeAsyncCallback) { - attributeAsyncCallback(status, value.contained_.template get<ValueType>()); - } - - protected: - _DBusProxyType& dbusProxy_; - const std::string interfaceName_; - const std::string propertyName_; -}; - -template <typename _AttributeType, typename _DBusProxyType = DBusProxy> -class DBusFreedesktopUnionReadonlyAttribute: public _AttributeType { - public: - typedef typename _AttributeType::ValueType ValueType; - typedef typename _AttributeType::AttributeAsyncCallback AttributeAsyncCallback; - - DBusFreedesktopUnionReadonlyAttribute(_DBusProxyType& dbusProxy, const char* interfaceName, const char* propertyName): - dbusProxy_(dbusProxy), - interfaceName_(interfaceName), - propertyName_(propertyName) - { - assert(interfaceName); - assert(propertyName); - } - - void getValue(CallStatus& callStatus, ValueType& value) const { - DBusLegacyVariantWrapper<ValueType> variantVal(value); - DBusProxyHelper<DBusSerializableArguments<std::string, std::string>, - DBusSerializableArguments<DBusLegacyVariantWrapper<ValueType> > >::callMethodWithReply( - dbusProxy_, - dbusProxy_.getDBusBusName().c_str(), - dbusProxy_.getDBusObjectPath().c_str(), - "org.freedesktop.DBus.Properties", - "Get", - "ss", - interfaceName_, - propertyName_, - callStatus, - variantVal); - value = variantVal.contained_; - } - - std::future<CallStatus> getValueAsync(AttributeAsyncCallback attributeAsyncCallback) { - return DBusProxyHelper<DBusSerializableArguments<std::string, std::string>, - DBusSerializableArguments<DBusLegacyVariantWrapper<ValueType> > >::callMethodAsync( - dbusProxy_, - dbusProxy_.getDBusBusName().c_str(), - dbusProxy_.getDBusObjectPath().c_str(), - "org.freedesktop.DBus.Properties", - "Get", - "ss", - interfaceName_, - propertyName_, - std::bind( - &CommonAPI::DBus::DBusFreedesktopUnionReadonlyAttribute<_AttributeType>::AsyncVariantStripper, - this, - std::placeholders::_1, - std::placeholders::_2, - std::move(attributeAsyncCallback))); - } - - void AsyncVariantStripper(const CommonAPI::CallStatus& status, - const DBusLegacyVariantWrapper<ValueType>& value, - AttributeAsyncCallback attributeAsyncCallback) { - attributeAsyncCallback(status, value.contained_); - } - - protected: - _DBusProxyType& dbusProxy_; - const std::string interfaceName_; - const std::string propertyName_; -}; - -template <typename _AttributeType, typename _DBusProxyType = DBusProxy> -class DBusAttribute: public DBusReadonlyAttribute<_AttributeType> { - public: - typedef typename _AttributeType::ValueType ValueType; - typedef typename _AttributeType::AttributeAsyncCallback AttributeAsyncCallback; - - DBusAttribute(_DBusProxyType& dbusProxy, const char* setMethodName, const char* setMethodSignature, const char* getMethodName): - DBusReadonlyAttribute<_AttributeType>(dbusProxy, setMethodSignature, getMethodName), - setMethodName_(setMethodName), - setMethodSignature_(setMethodSignature) { - assert(setMethodName); - assert(setMethodSignature); - } - - void setValue(const ValueType& requestValue, CallStatus& callStatus, ValueType& responseValue) { - DBusProxyHelper<DBusSerializableArguments<ValueType>, - DBusSerializableArguments<ValueType> >::callMethodWithReply( - this->dbusProxy_, - setMethodName_, - setMethodSignature_, - requestValue, - callStatus, - responseValue); - } - - - std::future<CallStatus> setValueAsync(const ValueType& requestValue, AttributeAsyncCallback attributeAsyncCallback) { - return DBusProxyHelper<DBusSerializableArguments<ValueType>, - DBusSerializableArguments<ValueType> >::callMethodAsync( - this->dbusProxy_, - setMethodName_, - setMethodSignature_, - requestValue, - attributeAsyncCallback); - } - - protected: - const char* setMethodName_; - const char* setMethodSignature_; -}; - -template <typename _AttributeType, typename _DBusProxyType = DBusProxy> -class DBusFreedesktopAttribute: public DBusFreedesktopReadonlyAttribute<_AttributeType, _DBusProxyType> { - public: - typedef typename _AttributeType::ValueType ValueType; - typedef typename _AttributeType::AttributeAsyncCallback AttributeAsyncCallback; - - DBusFreedesktopAttribute(_DBusProxyType& dbusProxy, - const char* interfaceName, - const char* propertyName) : - DBusFreedesktopReadonlyAttribute<_AttributeType>(dbusProxy, interfaceName, propertyName) - { - assert(interfaceName); - assert(propertyName); - } - - - void setValue(const ValueType& requestValue, CallStatus& callStatus, ValueType& responseValue) { - DBusLegacyVariantWrapper<Variant<ValueType> > variantVal; - variantVal.contained_ = Variant<ValueType>(requestValue); - DBusProxyHelper<DBusSerializableArguments<std::string, std::string, DBusLegacyVariantWrapper<Variant<ValueType> > >, - DBusSerializableArguments<> >::callMethodWithReply( - DBusFreedesktopReadonlyAttribute<_AttributeType>::dbusProxy_, - DBusFreedesktopReadonlyAttribute<_AttributeType>::dbusProxy_.getDBusBusName().c_str(), - DBusFreedesktopReadonlyAttribute<_AttributeType>::dbusProxy_.getDBusObjectPath().c_str(), - "org.freedesktop.DBus.Properties", - "Set", - "ssv", - DBusFreedesktopReadonlyAttribute<_AttributeType>::interfaceName_, - DBusFreedesktopReadonlyAttribute<_AttributeType>::propertyName_, - variantVal, - callStatus); - responseValue = requestValue; - } - - std::future<CallStatus> setValueAsync(const ValueType& requestValue, AttributeAsyncCallback attributeAsyncCallback) { - DBusLegacyVariantWrapper<Variant<ValueType> > variantVal; - variantVal.contained_ = Variant<ValueType>(requestValue); - return DBusProxyHelper<DBusSerializableArguments<std::string, std::string, DBusLegacyVariantWrapper<Variant<ValueType> > >, - DBusSerializableArguments<> >::callMethodAsync( - DBusFreedesktopReadonlyAttribute<_AttributeType>::dbusProxy_, - DBusFreedesktopReadonlyAttribute<_AttributeType>::dbusProxy_.getDBusBusName().c_str(), - DBusFreedesktopReadonlyAttribute<_AttributeType>::dbusProxy_.getDBusObjectPath().c_str(), - "org.freedesktop.DBus.Properties", - "Set", - "ssv", - DBusFreedesktopReadonlyAttribute<_AttributeType>::interfaceName_, - DBusFreedesktopReadonlyAttribute<_AttributeType>::propertyName_, - variantVal, - std::bind( - &CommonAPI::DBus::DBusFreedesktopAttribute<_AttributeType>::AsyncVariantStripper, - this, - std::placeholders::_1, - variantVal, - std::move(attributeAsyncCallback))); - } - - void AsyncVariantStripper(const CommonAPI::CallStatus& status, - const DBusLegacyVariantWrapper<Variant<ValueType> >& value, - AttributeAsyncCallback attributeAsyncCallback) { - attributeAsyncCallback(status, value.contained_.template get<ValueType>()); - } -}; - -template <typename _AttributeType, typename _DBusProxyType = DBusProxy> -class DBusFreedesktopUnionAttribute: public DBusFreedesktopUnionReadonlyAttribute<_AttributeType, _DBusProxyType> { - public: - typedef typename _AttributeType::ValueType ValueType; - typedef typename _AttributeType::AttributeAsyncCallback AttributeAsyncCallback; - - DBusFreedesktopUnionAttribute(_DBusProxyType& dbusProxy, - const char* interfaceName, - const char* propertyName) : - DBusFreedesktopUnionReadonlyAttribute<_AttributeType>(dbusProxy, interfaceName, propertyName) - { - assert(interfaceName); - assert(propertyName); - } - - - void setValue(const ValueType& requestValue, CallStatus& callStatus, ValueType& responseValue) { - DBusLegacyVariantWrapper<ValueType> variantVal; - variantVal.contained_ = requestValue; - DBusProxyHelper<DBusSerializableArguments<std::string, std::string, DBusLegacyVariantWrapper<ValueType> >, - DBusSerializableArguments<> >::callMethodWithReply( - DBusFreedesktopUnionAttribute<_AttributeType>::dbusProxy_, - DBusFreedesktopUnionAttribute<_AttributeType>::dbusProxy_.getDBusBusName().c_str(), - DBusFreedesktopUnionAttribute<_AttributeType>::dbusProxy_.getDBusObjectPath().c_str(), - "org.freedesktop.DBus.Properties", - "Set", - "ssv", - DBusFreedesktopUnionReadonlyAttribute<_AttributeType>::interfaceName_, - DBusFreedesktopUnionReadonlyAttribute<_AttributeType>::propertyName_, - variantVal, - callStatus); - responseValue = requestValue; - } - - std::future<CallStatus> setValueAsync(const ValueType& requestValue, AttributeAsyncCallback attributeAsyncCallback) { - DBusLegacyVariantWrapper<ValueType> variantVal; - variantVal.contained_ = requestValue; - return DBusProxyHelper<DBusSerializableArguments<std::string, std::string, DBusLegacyVariantWrapper<ValueType> >, - DBusSerializableArguments<> >::callMethodAsync( - DBusFreedesktopUnionAttribute<_AttributeType>::dbusProxy_, - DBusFreedesktopUnionAttribute<_AttributeType>::dbusProxy_.getDBusBusName().c_str(), - DBusFreedesktopUnionAttribute<_AttributeType>::dbusProxy_.getDBusObjectPath().c_str(), - "org.freedesktop.DBus.Properties", - "Set", - "ssv", - DBusFreedesktopUnionReadonlyAttribute<_AttributeType>::interfaceName_, - DBusFreedesktopUnionReadonlyAttribute<_AttributeType>::propertyName_, - variantVal, - std::bind( - &CommonAPI::DBus::DBusFreedesktopUnionAttribute<_AttributeType>::AsyncVariantStripper, - this, - std::placeholders::_1, - variantVal, - std::move(attributeAsyncCallback))); - } - - void AsyncVariantStripper(const CommonAPI::CallStatus& status, - const DBusLegacyVariantWrapper<ValueType>& value, - AttributeAsyncCallback attributeAsyncCallback) { - attributeAsyncCallback(status, value.contained_); - } -}; - -template <typename _AttributeType, typename _DBusProxyType = DBusProxy> -class DBusObservableAttribute: public _AttributeType { - public: - typedef typename _AttributeType::ValueType ValueType; - typedef typename _AttributeType::AttributeAsyncCallback AttributeAsyncCallback; - typedef typename _AttributeType::ChangedEvent ChangedEvent; - - template <typename... _AttributeTypeArguments> - DBusObservableAttribute(_DBusProxyType& dbusProxy, const char* changedEventName, _AttributeTypeArguments... arguments): - _AttributeType(dbusProxy, arguments...), - changedEvent_(dbusProxy, changedEventName, this->setMethodSignature_) { - } - - ChangedEvent& getChangedEvent() { - return changedEvent_; - } - - protected: - DBusEvent<ChangedEvent> changedEvent_; -}; - -template< class, class > -class LegacyEvent; - -template <template <class...> class _Type, class _Types, typename _DBusProxy> -class LegacyEvent<_Type<_Types>, _DBusProxy> : public _Type<_Types> { -public: - typedef _Types ValueType; - typedef _Type<ValueType> CommonAPIEvent; - typedef typename CommonAPIEvent::CancellableListener CancellableListener; - - LegacyEvent(_DBusProxy& dbusProxy, const char* interfaceName, const char* propName) : - interfaceName_(interfaceName), - propertyName_(propName), - subSet_(false), - internalEvent_(dbusProxy, "PropertiesChanged", "sa{sv}as", dbusProxy.getDBusObjectPath().c_str(), "org.freedesktop.DBus.Properties") { - } - -protected: - void onInternalEvent(const std::string& interfaceName, - const std::unordered_map<std::string, DBusLegacyVariantWrapper<Variant<_Types> > >& props, - const std::vector<std::string>& invalid) { - if (interfaceName_ == interfaceName) { - auto mapIter = props.find(propertyName_); - if (mapIter != props.end()) { - notifyListeners(mapIter->second.contained_.template get<ValueType>()); - } - } - } - - void onFirstListenerAdded(const CancellableListener& listener) { - sub = internalEvent_.subscribe( - std::bind( - &LegacyEvent<_Type<_Types>, _DBusProxy>::onInternalEvent, - this, - std::placeholders::_1, - std::placeholders::_2, - std::placeholders::_3)); - subSet_ = true; - } - - void onLastListenerRemoved(const CancellableListener& listener) { - if (subSet_) { - internalEvent_.unsubscribe(sub); - subSet_ = false; - } - } - - typedef DBusLegacyVariantWrapper<Variant<_Types> > ContainedVariant; - typedef std::unordered_map<std::string, ContainedVariant> PropertyMap; - typedef std::vector<std::string> InvalidArray; - typedef Event<std::string, PropertyMap, InvalidArray> SignalEvent; - - - typename DBusEvent<SignalEvent>::Subscription sub; - - const std::string interfaceName_; - const std::string propertyName_; - bool subSet_; - DBusEvent<SignalEvent> internalEvent_; -}; - -template <typename _AttributeType, typename _DBusProxyType = DBusProxy> -class DBusFreedesktopObservableAttribute: public _AttributeType { - public: - typedef typename _AttributeType::ValueType ValueType; - typedef typename _AttributeType::AttributeAsyncCallback AttributeAsyncCallback; - typedef typename _AttributeType::ChangedEvent ChangedEvent; - - template <typename... _AttributeTypeArguments> - DBusFreedesktopObservableAttribute(_DBusProxyType& dbusProxy, - const char* interfaceName, - const char* propertyName, - _AttributeTypeArguments... arguments): - _AttributeType(dbusProxy, interfaceName, propertyName, arguments...), - externalChangedEvent_(dbusProxy, interfaceName, propertyName) { - } - - ChangedEvent& getChangedEvent() { - return externalChangedEvent_; - } - - protected: - LegacyEvent<ChangedEvent, _DBusProxyType> externalChangedEvent_; -}; - -template< class, class > -class LegacyUnionEvent; - -template <template <class...> class _Type, class _Types, typename _DBusProxy> -class LegacyUnionEvent<_Type<_Types>, _DBusProxy> : public _Type<_Types> { -public: - typedef _Types ValueType; - typedef _Type<ValueType> CommonAPIEvent; - typedef typename CommonAPIEvent::CancellableListener CancellableListener; - - LegacyUnionEvent(_DBusProxy& dbusProxy, const char* interfaceName, const char* propName) : - interfaceName_(interfaceName), - propertyName_(propName), - subSet_(false), - internalEvent_(dbusProxy, "PropertiesChanged", "sa{sv}as", dbusProxy.getDBusObjectPath().c_str(), "org.freedesktop.DBus.Properties") { - } - -protected: - void onInternalEvent(const std::string& interfaceName, - const std::unordered_map<std::string, DBusLegacyVariantWrapper<ValueType> >& props, - const std::vector<std::string>& invalid) { - if (interfaceName_ == interfaceName) { - auto mapIter = props.find(propertyName_); - if (mapIter != props.end()) { - notifyListeners(mapIter->second.contained_); - } - } - } - - void onFirstListenerAdded(const CancellableListener& listener) { - sub = internalEvent_.subscribe( - std::bind( - &LegacyUnionEvent<_Type<_Types>, _DBusProxy>::onInternalEvent, - this, - std::placeholders::_1, - std::placeholders::_2, - std::placeholders::_3)); - subSet_ = true; - } - - void onLastListenerRemoved(const CancellableListener& listener) { - if (subSet_) { - internalEvent_.unsubscribe(sub); - subSet_ = false; - } - } - - typedef DBusLegacyVariantWrapper<ValueType> ContainedVariant; - typedef std::unordered_map<std::string, ContainedVariant> PropertyMap; - typedef std::vector<std::string> InvalidArray; - typedef Event<std::string, PropertyMap, InvalidArray> SignalEvent; - - DBusEvent<SignalEvent> internalEvent_; - - typename DBusEvent<SignalEvent>::Subscription sub; - - const std::string interfaceName_; - const std::string propertyName_; - - bool subSet_; - -}; - -template <typename _AttributeType, typename _DBusProxyType = DBusProxy> -class DBusFreedesktopUnionObservableAttribute: public _AttributeType { - public: - typedef typename _AttributeType::ValueType ValueType; - typedef typename _AttributeType::AttributeAsyncCallback AttributeAsyncCallback; - typedef typename _AttributeType::ChangedEvent ChangedEvent; - - template <typename... _AttributeTypeArguments> - DBusFreedesktopUnionObservableAttribute(_DBusProxyType& dbusProxy, - const char* interfaceName, - const char* propertyName, - _AttributeTypeArguments... arguments): - _AttributeType(dbusProxy, interfaceName, propertyName, arguments...), - externalChangedEvent_(dbusProxy, interfaceName, propertyName) { - } - - ChangedEvent& getChangedEvent() { - return externalChangedEvent_; - } - - protected: - LegacyUnionEvent<ChangedEvent, _DBusProxyType> externalChangedEvent_; -}; - -} // namespace DBus -} // namespace CommonAPI - -#endif // COMMONAPI_DBUS_DBUS_ATTRIBUTE_H_ diff --git a/src/CommonAPI/DBus/DBusClientId.cpp b/src/CommonAPI/DBus/DBusClientId.cpp index b68b7fa..7c9f195 100644 --- a/src/CommonAPI/DBus/DBusClientId.cpp +++ b/src/CommonAPI/DBus/DBusClientId.cpp @@ -1,14 +1,13 @@ -/* Copyright (C) 2013 BMW Group - * Author: Manfred Bathelt (manfred.bathelt@bmw.de) - * Author: Juergen Gehring (juergen.gehring@bmw.de) - * 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/. */ +// 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/. -#include "DBusClientId.h" -#include "DBusMessage.h" #include <typeinfo> +#include <CommonAPI/DBus/DBusClientId.hpp> +#include <CommonAPI/DBus/DBusMessage.hpp> + namespace std { template<> @@ -33,7 +32,7 @@ bool DBusClientId::operator==(CommonAPI::ClientId& clientIdToCompare) { DBusClientId clientIdToCompareDBus = DBusClientId(dynamic_cast<DBusClientId&>(clientIdToCompare)); return (clientIdToCompareDBus == *this); } - catch (const std::bad_cast& e) { + catch (...) { return false; } } @@ -59,7 +58,5 @@ DBusMessage DBusClientId::createMessage(const std::string objectPath, const std: return(returnMessage); } -} /* namespace DBus */ -} /* namespace CommonAPI */ - - +} // namespace DBus +} // namespace CommonAPI diff --git a/src/CommonAPI/DBus/DBusClientId.h b/src/CommonAPI/DBus/DBusClientId.h deleted file mode 100644 index a252de6..0000000 --- a/src/CommonAPI/DBus/DBusClientId.h +++ /dev/null @@ -1,48 +0,0 @@ -/* Copyright (C) 2013 BMW Group - * Author: Manfred Bathelt (manfred.bathelt@bmw.de) - * Author: Juergen Gehring (juergen.gehring@bmw.de) - * 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/. */ - -#if !defined (COMMONAPI_INTERNAL_COMPILATION) -#error "Only <CommonAPI/CommonAPI.h> can be included directly, this file may disappear or change contents." -#endif - -#ifndef DBUSCLIENTID_H_ -#define DBUSCLIENTID_H_ - -#include <CommonAPI/types.h> -#include <string> - -namespace CommonAPI { -namespace DBus { - -class DBusMessage; - -/** - * \brief Implementation of CommonAPI::ClientId for DBus - * - * This class represents the DBus specific implementation of CommonAPI::ClientId. - * It internally uses a string to identify clients. This string is the unique sender id used by dbus. - */ -class DBusClientId: public CommonAPI::ClientId { - friend class std::hash<DBusClientId>; - -public: - DBusClientId(std::string dbusId); - - bool operator==(CommonAPI::ClientId& clientIdToCompare); - bool operator==(DBusClientId& clientIdToCompare); - size_t hashCode(); - - const char * getDBusId(); - - DBusMessage createMessage(const std::string objectPath, const std::string interfaceName, const std::string signalName) const; -protected: - std::string dbusId_; -}; - -} /* namespace DBus */ -} /* namespace CommonAPI */ -#endif /* DBUSCLIENTID_H_ */ diff --git a/src/CommonAPI/DBus/DBusConfiguration.cpp b/src/CommonAPI/DBus/DBusConfiguration.cpp deleted file mode 100644 index 9b23a9c..0000000 --- a/src/CommonAPI/DBus/DBusConfiguration.cpp +++ /dev/null @@ -1,264 +0,0 @@ -/* Copyright (C) 2013 BMW Group - * Author: Manfred Bathelt (manfred.bathelt@bmw.de) - * Author: Juergen Gehring (juergen.gehring@bmw.de) - * 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 <fstream> - -#include <CommonAPI/utils.h> - -#include "DBusConfiguration.h" - - -namespace CommonAPI { -namespace DBus { - - -enum class TypeEnum { - DBUS_CONNECTION, DBUS_OBJECT, DBUS_INTERFACE, DBUS_PREDEFINED -}; - -enum class TypeEnumFactory { - DBUS_BUSTYPE -}; - -enum class FileParsingState { - UNDEFINED, - PARSING_ADDRESS, - PARSING_FACTORY -}; - - -static const std::unordered_map<std::string, TypeEnum> allowedValueTypes = { - {"dbus_connection", TypeEnum::DBUS_CONNECTION}, - {"dbus_object", TypeEnum::DBUS_OBJECT}, - {"dbus_interface", TypeEnum::DBUS_INTERFACE}, - {"dbus_predefined", TypeEnum::DBUS_PREDEFINED} -}; - -static const std::unordered_map<std::string, TypeEnumFactory> allowedValueTypesFactory = { - {"dbus_bustype", TypeEnumFactory::DBUS_BUSTYPE} -}; - - -const DBusConfiguration& DBusConfiguration::getInstance() { - static DBusConfiguration* instance = NULL; - if (!instance) { - instance = new DBusConfiguration(); - instance->retrieveCommonApiDBusConfiguration(); - } - return *instance; -} - -void DBusConfiguration::retrieveCommonApiDBusConfiguration() { - std::string fqnOfConfigFile = getCurrentBinaryFileFQN(); - std::ifstream addressConfigFile; - - fqnOfConfigFile += DBUS_CONFIG_SUFFIX; - - addressConfigFile.open(fqnOfConfigFile.c_str()); - - if (addressConfigFile.is_open()) { - readConfigFile(addressConfigFile); - addressConfigFile.close(); - } - - addressConfigFile.clear(); - std::vector<std::string> splittedConfigFQN = split(fqnOfConfigFile, '/'); - std::string globalConfigFQN = DBUS_GLOBAL_CONFIG_ROOT + splittedConfigFQN.at(splittedConfigFQN.size() - 1); - addressConfigFile.open(globalConfigFQN); - if (addressConfigFile.is_open()) { - readConfigFile(addressConfigFile); - addressConfigFile.close(); - } - addressConfigFile.clear(); - - addressConfigFile.open(DBUS_GLOBAL_CONFIG_FQN); - if(addressConfigFile.is_open()) { - readConfigFile(addressConfigFile); - addressConfigFile.close(); - } -} - -const std::unordered_map<std::string, CommonApiServiceDetails>& DBusConfiguration::getCommonApiAddressDetails() const { - return std::move(commonApiAddressDetails_); -} - -const DBusFactoryConfig* DBusConfiguration::getFactoryConfiguration(const std::string& factoryName) const { - const auto foundConfig = factoryConfigurations_.find(factoryName); - - if (foundConfig != factoryConfigurations_.end()) { - return &foundConfig->second; - } - return NULL; -} - -void reset(DBusServiceAddress& dbusServiceAddress) { - std::get<0>(dbusServiceAddress) = ""; - std::get<1>(dbusServiceAddress) = ""; - std::get<2>(dbusServiceAddress) = ""; -} - -void reset(CommonApiServiceDetails& serviceDetails) { - reset(std::get<0>(serviceDetails)); - std::get<1>(serviceDetails) = false; -} - - -void reset(DBusFactoryConfig& dbusFactoryconfiguration) { - dbusFactoryconfiguration.factoryName_ = ""; - dbusFactoryconfiguration.busType_ = BusType::SESSION; -} - -void DBusConfiguration::readValue(std::string& readLine, DBusFactoryConfig& factoryConfig) { - std::stringstream readStream(readLine); - std::string paramName; - std::string paramValue; - - getline(readStream, paramName, '='); - - auto typeEntry = allowedValueTypesFactory.find(paramName); - if (typeEntry != allowedValueTypesFactory.end()) { - getline(readStream, paramValue); - switch (typeEntry->second) { - case TypeEnumFactory::DBUS_BUSTYPE: - if (paramValue == "system") { - factoryConfig.busType_ = DBus::BusType::SYSTEM; - } - break; - } - } -} - -void DBusConfiguration::readValue(std::string& readLine, CommonApiServiceDetails& serviceDetails) { - std::stringstream readStream(readLine); - - std::string paramName; - std::string paramValue; - - getline(readStream, paramName, '='); - - auto typeEntry = allowedValueTypes.find(paramName); - if (typeEntry != allowedValueTypes.end()) { - getline(readStream, paramValue); - switch (typeEntry->second) { - case TypeEnum::DBUS_CONNECTION: - std::get<0>(std::get<0>(serviceDetails)) = paramValue; - break; - case TypeEnum::DBUS_OBJECT: - std::get<1>(std::get<0>(serviceDetails)) = paramValue; - break; - case TypeEnum::DBUS_INTERFACE: - std::get<2>(std::get<0>(serviceDetails)) = paramValue; - break; - case TypeEnum::DBUS_PREDEFINED: - std::get<1>(serviceDetails) = paramValue == "true" ? true : false; - break; - } - } -} - - -const FileParsingState isValidSection(const std::string& sectionIdentifier, std::string& newSectionName) { - const size_t sectionIdentifierLength = sectionIdentifier.length(); - - if (sectionIdentifier[0] == '[' && sectionIdentifier[sectionIdentifier.length() - 1] == ']') { - std::string sectionName = sectionIdentifier.substr(1, sectionIdentifierLength - 2); - std::vector<std::string> addressParts = split(sectionName, '$'); - - if (addressParts.size() == 2 && addressParts[0] == "factory") { - newSectionName = addressParts[1]; - return FileParsingState::PARSING_FACTORY; - } else if (isValidCommonApiAddress(sectionName)) { - newSectionName = sectionName; - return FileParsingState::PARSING_ADDRESS; - } - } - return FileParsingState::UNDEFINED; -} - - -void DBusConfiguration::readConfigFile(std::ifstream& addressConfigFile) { - std::string currentlyParsedCommonApiAddress; - DBusFactoryConfig currentlyParsedFactoryConfig; - CommonApiServiceDetails serviceDetails; - reset(serviceDetails); - - bool newAddressFound = false; - bool newFactoryFound = false; - - FileParsingState currentParsingState = FileParsingState::UNDEFINED; - - while (addressConfigFile.good()) { - std::string readLine; - std::string sectionName; - getline(addressConfigFile, readLine); - - FileParsingState newState = isValidSection(readLine, sectionName); - - //Finish currently read sections if necessary - if (newState != FileParsingState::UNDEFINED) { - switch (currentParsingState) { - case FileParsingState::PARSING_ADDRESS: - if (newAddressFound) { - commonApiAddressDetails_.insert( {currentlyParsedCommonApiAddress, serviceDetails}); - } - newAddressFound = false; - break; - case FileParsingState::PARSING_FACTORY: - if (newFactoryFound) { - factoryConfigurations_.insert( {currentlyParsedFactoryConfig.factoryName_, currentlyParsedFactoryConfig} ); - } - newFactoryFound = false; - break; - case FileParsingState::UNDEFINED: - break; - } - } - - //See what comes next - switch (newState) { - case FileParsingState::PARSING_ADDRESS: - reset(serviceDetails); - currentlyParsedCommonApiAddress = sectionName; - newAddressFound = commonApiAddressDetails_.find(currentlyParsedCommonApiAddress) == commonApiAddressDetails_.end(); - currentParsingState = FileParsingState::PARSING_ADDRESS; - break; - - case FileParsingState::PARSING_FACTORY: - reset(currentlyParsedFactoryConfig); - currentlyParsedFactoryConfig.factoryName_ = sectionName; - newFactoryFound = factoryConfigurations_.find(sectionName) == factoryConfigurations_.end(); - currentParsingState = FileParsingState::PARSING_FACTORY; - break; - - //nothing new, so this lines should contain additional information for the current state - case FileParsingState::UNDEFINED: - switch (currentParsingState) { - case FileParsingState::PARSING_FACTORY: - readValue(readLine, currentlyParsedFactoryConfig); - break; - case FileParsingState::PARSING_ADDRESS: - readValue(readLine, serviceDetails); - break; - case FileParsingState::UNDEFINED: - break; - } - break; - } - } - - //End of file, finish last section - if (newAddressFound) { - commonApiAddressDetails_.insert( {currentlyParsedCommonApiAddress, serviceDetails}); - } - if (newFactoryFound) { - factoryConfigurations_.insert( {currentlyParsedFactoryConfig.factoryName_, currentlyParsedFactoryConfig}); - } -} - - -}// namespace DBus -} // namespace CommonAPI diff --git a/src/CommonAPI/DBus/DBusConfiguration.h b/src/CommonAPI/DBus/DBusConfiguration.h deleted file mode 100644 index 6ded2b6..0000000 --- a/src/CommonAPI/DBus/DBusConfiguration.h +++ /dev/null @@ -1,74 +0,0 @@ -/* Copyright (C) 2013 BMW Group - * Author: Manfred Bathelt (manfred.bathelt@bmw.de) - * Author: Juergen Gehring (juergen.gehring@bmw.de) - * 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/. */ - -#if !defined (COMMONAPI_INTERNAL_COMPILATION) -#error "Only <CommonAPI/CommonAPI.h> can be included directly, this file may disappear or change contents." -#endif - -#ifndef COMMONAPI_DBUS_DBUS_CONFIGURATION_H_ -#define COMMONAPI_DBUS_DBUS_CONFIGURATION_H_ - - -#include <unordered_map> - -#include "DBusConnectionBusType.h" -#include "DBusFunctionalHash.h" - - -namespace CommonAPI { -namespace DBus { - -static const char DBUS_CONFIG_SUFFIX[] = "_dbus.conf"; -static const char DBUS_GLOBAL_CONFIG_FQN[] = "/etc/CommonApiDBus/dbusAddresses.conf"; -static const char DBUS_GLOBAL_CONFIG_ROOT[] = "/etc/CommonApiDBus/"; - -//connectionName, objectPath, interfaceName -typedef std::tuple<std::string, std::string, std::string> DBusServiceAddress; - -//Details for a common api address key: DBusAddress, predefined service -typedef std::tuple<DBusServiceAddress, bool> CommonApiServiceDetails; - - -struct DBusFactoryConfig { - DBusFactoryConfig(): factoryName_(""), busType_(BusType::SESSION) {} - - std::string factoryName_; - BusType busType_; -}; - - -class DBusConfiguration { - public: - static const DBusConfiguration& getInstance(); - - DBusConfiguration(const DBusConfiguration&) = delete; - DBusConfiguration& operator=(const DBusConfiguration&) = delete; - DBusConfiguration(DBusConfiguration&&) = delete; - DBusConfiguration& operator=(DBusConfiguration&&) = delete; - - const std::unordered_map<std::string, CommonApiServiceDetails>& getCommonApiAddressDetails() const; - - const DBusFactoryConfig* getFactoryConfiguration(const std::string& factoryName) const; - - private: - DBusConfiguration() = default; - - void readConfigFile(std::ifstream& addressConfigFile); - void retrieveCommonApiDBusConfiguration(); - - void readValue(std::string& readLine, DBusFactoryConfig& factoryConfig); - void readValue(std::string& readLine, CommonApiServiceDetails& serviceDetails); - - std::unordered_map<std::string, CommonApiServiceDetails> commonApiAddressDetails_; - std::unordered_map<std::string, DBusFactoryConfig> factoryConfigurations_; -}; - - -}// namespace DBus -}// namespace CommonAPI - -#endif /* COMMONAPI_DBUS_DBUS_CONFIGURATION_H_ */ diff --git a/src/CommonAPI/DBus/DBusConnection.cpp b/src/CommonAPI/DBus/DBusConnection.cpp index 1d8fd38..07e7da5 100644 --- a/src/CommonAPI/DBus/DBusConnection.cpp +++ b/src/CommonAPI/DBus/DBusConnection.cpp @@ -1,26 +1,20 @@ -/* Copyright (C) 2013 BMW Group - * Author: Manfred Bathelt (manfred.bathelt@bmw.de) - * Author: Juergen Gehring (juergen.gehring@bmw.de) - * 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/. */ - -// Workaround for libstdc++ bug -#ifndef _GLIBCXX_USE_NANOSLEEP -#define _GLIBCXX_USE_NANOSLEEP -#endif - -#include "DBusConnection.h" -#include "DBusInputStream.h" -#include "DBusProxy.h" +// 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/. #include <algorithm> -#include <sstream> #include <cassert> -#include <future> #include <chrono> +#include <future> +#include <sstream> #include <thread> +#include <CommonAPI/Logger.hpp> +#include <CommonAPI/DBus/DBusConnection.hpp> +#include <CommonAPI/DBus/DBusInputStream.hpp> +#include <CommonAPI/DBus/DBusProxy.hpp> + namespace CommonAPI { namespace DBus { @@ -28,7 +22,7 @@ DBusConnectionStatusEvent::DBusConnectionStatusEvent(DBusConnection* dbusConnect dbusConnection_(dbusConnection) { } -void DBusConnectionStatusEvent::onListenerAdded(const CancellableListener& listener) { +void DBusConnectionStatusEvent::onListenerAdded(const Listener& listener) { if (dbusConnection_->isConnected()) listener(AvailabilityStatus::AVAILABLE); } @@ -42,12 +36,10 @@ const DBusObjectPathVTable* DBusConnection::getDBusObjectPathVTable() { return &libdbusObjectPathVTable; } - - //std::bind used to start the dispatch thread holds one reference, and the selfReference //created within the thread is the second. If only those two remain, no one but the //dispatch thread references the connection, which therefore can be finished. -const uint32_t ownUseCount = 2; +const int32_t ownUseCount = 2; void DBusConnection::dispatch() { std::shared_ptr<DBusConnection> selfReference = this->shared_from_this(); @@ -59,11 +51,9 @@ void DBusConnection::dispatch() { } } -bool DBusConnection::readWriteDispatch(int timeoutMilliseconds) { +bool DBusConnection::readWriteDispatch(int _timeout) { if(isConnected()) { - const dbus_bool_t libdbusSuccess = dbus_connection_read_write_dispatch(libdbusConnection_, - timeoutMilliseconds); - return libdbusSuccess; + return 0 != dbus_connection_read_write_dispatch(connection_, _timeout); } return false; } @@ -78,39 +68,39 @@ void DBusConnection::resumeDispatching() const { dispatchSuspendLock_.unlock(); } -DBusConnection::DBusConnection(BusType busType) : +DBusConnection::DBusConnection(DBusType_t busType) : dispatchThread_(NULL), stopDispatching_(false), - mainLoopContext_(std::shared_ptr<MainLoopContext>(NULL)), dispatchSource_(), watchContext_(NULL), pauseDispatching_(false), - libdbusConnection_(NULL), + connection_(NULL), busType_(busType), dbusConnectionStatusEvent_(this), libdbusSignalMatchRulesCount_(0), dbusObjectMessageHandler_(), connectionNameCount_(), - enforcerThread_(NULL) - { + enforcerThread_(NULL), + enforcerThreadCancelled_(false) { dbus_threads_init_default(); } -DBusConnection::DBusConnection(::DBusConnection* libDbusConnection) : +DBusConnection::DBusConnection(::DBusConnection *_connection) : dispatchThread_(NULL), stopDispatching_(false), - mainLoopContext_(std::shared_ptr<MainLoopContext>(NULL)), dispatchSource_(), watchContext_(NULL), pauseDispatching_(false), - libdbusConnection_(libDbusConnection), - busType_(WRAPPED), + connection_(_connection), + busType_(DBusType_t::WRAPPED), dbusConnectionStatusEvent_(this), libdbusSignalMatchRulesCount_(0), dbusObjectMessageHandler_(), connectionNameCount_(), - enforcerThread_(NULL) { + enforcerThread_(NULL), + enforcerThreadCancelled_(false) { + dbus_threads_init_default(); } @@ -124,38 +114,36 @@ bool DBusConnection::isObjectPathMessageHandlerSet() { DBusConnection::~DBusConnection() { if (auto lockedContext = mainLoopContext_.lock()) { - dbus_connection_set_watch_functions(libdbusConnection_, NULL, NULL, NULL, NULL, NULL); - dbus_connection_set_timeout_functions(libdbusConnection_, NULL, NULL, NULL, NULL, NULL); + 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_; delete dispatchSource_; } - disconnect(); + // ensure, the registry survives until disconnecting is done... + //std::shared_ptr<DBusServiceRegistry> itsRegistry = DBusServiceRegistry::get(shared_from_this()); + 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. - if (enforcerThread_) { - enforceTimeoutMutex_.lock(); - - auto it = timeoutMap_.begin(); - while (it != timeoutMap_.end()) { - 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); - asyncHandler->onDBusMessageReply(CallStatus::REMOTE_ERROR, dbusMessageCall.createMethodError(DBUS_ERROR_TIMEOUT)); - delete asyncHandler; - } - it = timeoutMap_.erase(it); - dbus_pending_call_unref(libdbusPendingCall); - } - - enforceTimeoutMutex_.unlock(); - } + auto it = timeoutMap_.begin(); + while (it != timeoutMap_.end()) { + 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); + + asyncHandler->onDBusMessageReply(CallStatus::REMOTE_ERROR, dbusMessageCall.createMethodError(DBUS_ERROR_TIMEOUT)); + delete asyncHandler; + + } + it = timeoutMap_.erase(it); + dbus_pending_call_unref(libdbusPendingCall); + } } @@ -168,13 +156,13 @@ bool DBusConnection::attachMainLoopContext(std::weak_ptr<MainLoopContext> mainLo lockedContext->registerDispatchSource(dispatchSource_); dbus_connection_set_wakeup_main_function( - libdbusConnection_, + connection_, &DBusConnection::onWakeupMainContext, &mainLoopContext_, NULL); - bool success = dbus_connection_set_watch_functions( - libdbusConnection_, + bool success = 0 != dbus_connection_set_watch_functions( + connection_, &DBusConnection::onAddWatch, &DBusConnection::onRemoveWatch, &DBusConnection::onToggleWatch, @@ -185,8 +173,8 @@ bool DBusConnection::attachMainLoopContext(std::weak_ptr<MainLoopContext> mainLo return false; } - success = dbus_connection_set_timeout_functions( - libdbusConnection_, + success = 0 != dbus_connection_set_timeout_functions( + connection_, &DBusConnection::onAddTimeout, &DBusConnection::onRemoveTimeout, &DBusConnection::onToggleTimeout, @@ -194,7 +182,7 @@ bool DBusConnection::attachMainLoopContext(std::weak_ptr<MainLoopContext> mainLo NULL); if (!success) { - dbus_connection_set_watch_functions(libdbusConnection_, NULL, NULL, NULL, NULL, NULL); + dbus_connection_set_watch_functions(connection_, NULL, NULL, NULL, NULL, NULL); return false; } @@ -212,7 +200,6 @@ void DBusConnection::onWakeupMainContext(void* data) { } } - dbus_bool_t DBusConnection::onAddWatch(::DBusWatch* libdbusWatch, void* data) { WatchContext* watchContext = static_cast<WatchContext*>(data); assert(watchContext); @@ -279,7 +266,6 @@ void DBusConnection::onToggleTimeout(::DBusTimeout* dbustimeout, void* data) { assert(static_cast<std::weak_ptr<MainLoopContext>*>(data)); DBusTimeout* timeout = static_cast<DBusTimeout*>(dbus_timeout_get_data(dbustimeout)); - if (timeout->isReadyToBeMonitored()) { timeout->startMonitoring(); } else { @@ -287,37 +273,38 @@ void DBusConnection::onToggleTimeout(::DBusTimeout* dbustimeout, void* data) { } } - bool DBusConnection::connect(bool startDispatchThread) { DBusError dbusError; return connect(dbusError, startDispatchThread); } -bool DBusConnection::connect(DBusError& dbusError, bool startDispatchThread) { +bool DBusConnection::connect(DBusError &dbusError, bool startDispatchThread) { assert(!dbusError); - if (isConnected()) { return true; } const ::DBusBusType libdbusType = static_cast<DBusBusType>(busType_); - libdbusConnection_ = dbus_bus_get_private(libdbusType, &dbusError.libdbusError_); + connection_ = dbus_bus_get_private(libdbusType, &dbusError.libdbusError_); if (dbusError) { return false; } - assert(libdbusConnection_); - dbus_connection_set_exit_on_disconnect(libdbusConnection_, false); + assert(connection_); + dbus_connection_set_exit_on_disconnect(connection_, false); initLibdbusObjectPathHandlerAfterConnect(); initLibdbusSignalFilterAfterConnect(); + stopDispatching_ = !startDispatchThread; if (startDispatchThread) { dispatchThread_ = new std::thread(std::bind(&DBusConnection::dispatch, this->shared_from_this())); } - stopDispatching_ = !startDispatchThread; + + enforcerThread_ = std::make_shared<std::thread>( + std::bind(&DBusConnection::enforceAsynchronousTimeouts, shared_from_this())); dbusConnectionStatusEvent_.notifyListeners(AvailabilityStatus::AVAILABLE); @@ -325,12 +312,12 @@ bool DBusConnection::connect(DBusError& dbusError, bool startDispatchThread) { } void DBusConnection::disconnect() { - std::lock_guard<std::mutex> dbusConnectionLock(libdbusConnectionGuard_); + std::lock_guard<std::mutex> dbusConnectionLock(connectionGuard_); if (isConnected()) { dbusConnectionStatusEvent_.notifyListeners(AvailabilityStatus::NOT_AVAILABLE); if (libdbusSignalMatchRulesCount_ > 0) { - dbus_connection_remove_filter(libdbusConnection_, &onLibdbusSignalFilterThunk, this); + dbus_connection_remove_filter(connection_, &onLibdbusSignalFilterThunk, this); libdbusSignalMatchRulesCount_ = 0; } @@ -338,7 +325,7 @@ void DBusConnection::disconnect() { stopDispatching_ = true; - dbus_connection_close(libdbusConnection_); + dbus_connection_close(connection_); if(dispatchThread_) { //It is possible for the disconnect to be called from within a callback, i.e. from within the dispatch @@ -352,34 +339,26 @@ void DBusConnection::disconnect() { dispatchThread_ = NULL; } - dbus_connection_unref(libdbusConnection_); - libdbusConnection_ = NULL; + enforcerThreadCancelled_ = true; + enforceTimeoutCondition_.notify_one(); + if (enforcerThread_->joinable()) { + enforcerThread_->join(); + } + enforcerThreadCancelled_ = false; + + dbus_connection_unref(connection_); + connection_ = nullptr; } } bool DBusConnection::isConnected() const { - return (libdbusConnection_ != NULL); + return (connection_ != NULL); } DBusProxyConnection::ConnectionStatusEvent& DBusConnection::getConnectionStatusEvent() { return dbusConnectionStatusEvent_; } -const std::shared_ptr<DBusServiceRegistry> DBusConnection::getDBusServiceRegistry() { - std::shared_ptr<DBusServiceRegistry> serviceRegistry = dbusServiceRegistry_.lock(); - if (!serviceRegistry || dbusServiceRegistry_.expired()) { - serviceRegistryGuard_.lock(); - if (!serviceRegistry || dbusServiceRegistry_.expired()) { - serviceRegistry = std::make_shared<DBusServiceRegistry>(shared_from_this()); - serviceRegistry->init(); - dbusServiceRegistry_ = serviceRegistry; - } - serviceRegistryGuard_.unlock(); - } - - return serviceRegistry; -} - //Does this need to be a weak pointer? const std::shared_ptr<DBusObjectManager> DBusConnection::getDBusObjectManager() { if (!dbusObjectManager_) { @@ -389,19 +368,19 @@ const std::shared_ptr<DBusObjectManager> DBusConnection::getDBusObjectManager() } objectManagerGuard_.unlock(); } - return dbusObjectManager_; } bool DBusConnection::requestServiceNameAndBlock(const std::string& serviceName) const { DBusError dbusError; bool isServiceNameAcquired = false; - std::lock_guard<std::mutex> dbusConnectionLock(libdbusConnectionGuard_); + + std::lock_guard<std::mutex> dbusConnectionLock(connectionGuard_); auto conIter = connectionNameCount_.find(serviceName); if (conIter == connectionNameCount_.end()) { suspendDispatching(); - const int libdbusStatus = dbus_bus_request_name(libdbusConnection_, + const int libdbusStatus = dbus_bus_request_name(connection_, serviceName.c_str(), DBUS_NAME_FLAG_DO_NOT_QUEUE, &dbusError.libdbusError_); @@ -410,7 +389,7 @@ bool DBusConnection::requestServiceNameAndBlock(const std::string& serviceName) isServiceNameAcquired = (libdbusStatus == DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER); if (isServiceNameAcquired) { - connectionNameCount_.insert({serviceName, (uint16_t)1}); + connectionNameCount_.insert( { serviceName, (uint16_t)1 } ); } } else { conIter->second = conIter->second + 1; @@ -423,12 +402,12 @@ bool DBusConnection::requestServiceNameAndBlock(const std::string& serviceName) bool DBusConnection::releaseServiceName(const std::string& serviceName) const { DBusError dbusError; bool isServiceNameReleased = false; - std::lock_guard<std::mutex> dbusConnectionLock(libdbusConnectionGuard_); + std::lock_guard<std::mutex> dbusConnectionLock(connectionGuard_); auto conIter = connectionNameCount_.find(serviceName); if (conIter != connectionNameCount_.end()) { if (conIter->second == 1) { suspendDispatching(); - const int libdbusStatus = dbus_bus_release_name(libdbusConnection_, + const int libdbusStatus = dbus_bus_release_name(connection_, serviceName.c_str(), &dbusError.libdbusError_); resumeDispatching(); @@ -444,13 +423,12 @@ bool DBusConnection::releaseServiceName(const std::string& serviceName) const { return isServiceNameReleased; } -bool DBusConnection::sendDBusMessage(const DBusMessage& dbusMessage, uint32_t* allocatedSerial) const { - assert(dbusMessage); +bool DBusConnection::sendDBusMessage(const DBusMessage &_message) const { + assert(_message); assert(isConnected()); - dbus_uint32_t* libdbusSerial = static_cast<dbus_uint32_t*>(allocatedSerial); - const bool result = dbus_connection_send(libdbusConnection_, dbusMessage.libdbusMessage_, libdbusSerial); - + dbus_uint32_t dbusSerial; + bool result = 0 != dbus_connection_send(connection_, _message.message_, &dbusSerial); return result; } @@ -471,7 +449,7 @@ void DBusConnection::onLibdbusPendingCallNotifyThunk(::DBusPendingCall* libdbusP dbusMessageReplyAsyncHandler->onDBusMessageReply(callStatus, dbusMessage); - // libdbus calls the Cleanup method below + // libdbus calls the cleanup method below dbus_pending_call_unref(libdbusPendingCall); } @@ -483,71 +461,74 @@ void DBusConnection::onLibdbusDataCleanup(void* userData) { //Would not be needed if libdbus would actually handle its timeouts for pending calls. void DBusConnection::enforceAsynchronousTimeouts() const { - enforceTimeoutMutex_.lock(); - - //Assert that we DO have a reference to the executing thread, even if the DBusConnection is destroyed. - //We need it to assess whether we still may access the members of the DBusConnection. - std::shared_ptr<std::thread> threadPtr = enforcerThread_; - - while (!timeoutMap_.empty()) { - auto minTimeoutElement = std::min_element(timeoutMap_.begin(), timeoutMap_.end(), - [] (const TimeoutMapElement& lhs, const TimeoutMapElement& rhs) { - return std::get<0>(lhs.second) < std::get<0>(rhs.second); - }); + std::unique_lock<std::mutex> itsLock(enforcerThreadMutex_); - int minTimeout = std::get<0>(minTimeoutElement->second); + while (!enforcerThreadCancelled_) { + enforceTimeoutMutex_.lock(); - enforceTimeoutMutex_.unlock(); + int minTimeout = std::numeric_limits<int>::max(); // not really, but nearly "forever" + if (timeoutMap_.size() > 0) { + auto minTimeoutElement = std::min_element(timeoutMap_.begin(), timeoutMap_.end(), + [] (const TimeoutMapElement& lhs, const TimeoutMapElement& rhs) { + return std::get<0>(lhs.second) < std::get<0>(rhs.second); + }); - std::this_thread::sleep_for(std::chrono::milliseconds(minTimeout)); - - //Do not access members if the DBusConnection was destroyed during the unlocked phase. - if (!threadPtr.unique()) { - enforceTimeoutMutex_.lock(); - auto it = timeoutMap_.begin(); - while (!threadPtr.unique() && it != timeoutMap_.end()) { - int& currentTimeout = std::get<0>(it->second); - currentTimeout -= minTimeout; - if (currentTimeout <= 0) { - 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); - 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; - - } - 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 { - ++it; - } - } + minTimeout = std::get<0>(minTimeoutElement->second); } - } - //Normally there is at least the member of DBusConnection plus the local copy of this pointer. - //If the local copy is the only one remaining, we have to assume that the DBusConnection was - //destroyed and therefore we must no longer access its members. - if (!threadPtr.unique()) { - enforcerThread_.reset(); enforceTimeoutMutex_.unlock(); - } - threadPtr->detach(); + auto startTime = std::chrono::high_resolution_clock::now(); + if (std::cv_status::timeout == + enforceTimeoutCondition_.wait_for(itsLock, std::chrono::milliseconds(minTimeout))) { + + //Do not access members if the DBusConnection was destroyed during the unlocked phase. + enforceTimeoutMutex_.lock(); + auto it = timeoutMap_.begin(); + while (it != timeoutMap_.end()) { + int& currentTimeout = std::get<0>(it->second); + + currentTimeout -= minTimeout; + if (currentTimeout <= 0) { + 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_pair(asyncHandler, dbusMessageCall)); + } 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; + } + } + 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 { + ++it; + } + } + enforceTimeoutMutex_.unlock(); + } else { + auto notifyTime = std::chrono::high_resolution_clock::now(); + int elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(notifyTime - startTime).count(); + for (auto &i : timeoutMap_) + std::get<0>(i.second) -= elapsed; + } + } } std::future<CallStatus> DBusConnection::sendDBusMessageWithReplyAsync( const DBusMessage& dbusMessage, std::unique_ptr<DBusMessageReplyAsyncHandler> dbusMessageReplyAsyncHandler, - int timeoutMilliseconds) const { + const CommonAPI::CallInfo *_info) const { assert(dbusMessage); assert(isConnected()); @@ -556,10 +537,14 @@ std::future<CallStatus> DBusConnection::sendDBusMessageWithReplyAsync( dbus_bool_t libdbusSuccess; suspendDispatching(); - libdbusSuccess = dbus_connection_send_with_reply(libdbusConnection_, - dbusMessage.libdbusMessage_, + libdbusSuccess = dbus_connection_send_with_reply(connection_, + dbusMessage.message_, &libdbusPendingCall, - timeoutMilliseconds); + _info->timeout_); + + if (_info->sender_ != 0) { + COMMONAPI_DEBUG("Message sent: SenderID: ", _info->sender_, " - Serial number: ", dbusMessage.getSerial()); + } if (!libdbusSuccess || !libdbusPendingCall) { dbusMessageReplyAsyncHandler->onDBusMessageReply(CallStatus::CONNECTION_FAILED, dbusMessage.createMethodError(DBUS_ERROR_DISCONNECTED)); @@ -567,32 +552,39 @@ std::future<CallStatus> DBusConnection::sendDBusMessageWithReplyAsync( return dbusMessageReplyAsyncHandler->getFuture(); } - libdbusSuccess = dbus_pending_call_set_notify( - libdbusPendingCall, - onLibdbusPendingCallNotifyThunk, - dbusMessageReplyAsyncHandler.get(), - onLibdbusDataCleanup); - - if (!libdbusSuccess) { - dbusMessageReplyAsyncHandler->onDBusMessageReply(CallStatus::OUT_OF_MEMORY, dbusMessage); - dbus_pending_call_unref(libdbusPendingCall); - resumeDispatching(); - return dbusMessageReplyAsyncHandler->getFuture(); - } + sendLock_.lock(); + if (dbus_pending_call_get_completed (libdbusPendingCall)) { + onLibdbusPendingCallNotifyThunk(libdbusPendingCall, dbusMessageReplyAsyncHandler.get()); + onLibdbusDataCleanup(dbusMessageReplyAsyncHandler.get()); + + } else { + libdbusSuccess = dbus_pending_call_set_notify( + libdbusPendingCall, + onLibdbusPendingCallNotifyThunk, + dbusMessageReplyAsyncHandler.get(), + onLibdbusDataCleanup); + + if (!libdbusSuccess) { + dbusMessageReplyAsyncHandler->onDBusMessageReply(CallStatus::OUT_OF_MEMORY, dbusMessage); + dbus_pending_call_unref(libdbusPendingCall); + resumeDispatching(); + sendLock_.unlock(); + return dbusMessageReplyAsyncHandler->getFuture(); + } + } + sendLock_.unlock(); DBusMessageReplyAsyncHandler* replyAsyncHandler = dbusMessageReplyAsyncHandler.release(); - const bool mainloopContextIsPresent = (bool) mainLoopContext_.lock(); - if (!mainloopContextIsPresent && timeoutMilliseconds != DBUS_TIMEOUT_INFINITE) { + if (_info->timeout_ != DBUS_TIMEOUT_INFINITE) { dbus_pending_call_ref(libdbusPendingCall); - std::tuple<int, DBusMessageReplyAsyncHandler*, DBusMessage> toInsert {timeoutMilliseconds, replyAsyncHandler, dbusMessage}; + std::tuple<int, DBusMessageReplyAsyncHandler*, DBusMessage> toInsert { _info->timeout_, replyAsyncHandler, dbusMessage }; enforceTimeoutMutex_.lock(); - timeoutMap_.insert( {libdbusPendingCall, toInsert } ); - if (!enforcerThread_) { - enforcerThread_ = std::make_shared<std::thread>(std::bind(&DBusConnection::enforceAsynchronousTimeouts, this->shared_from_this())); - } + timeoutMap_.insert( { libdbusPendingCall, toInsert } ); enforceTimeoutMutex_.unlock(); + + enforceTimeoutCondition_.notify_all(); } std::future<CallStatus> result = replyAsyncHandler->getFuture(); @@ -602,21 +594,24 @@ std::future<CallStatus> DBusConnection::sendDBusMessageWithReplyAsync( return result; } - DBusMessage DBusConnection::sendDBusMessageWithReplyAndBlock(const DBusMessage& dbusMessage, DBusError& dbusError, - int timeoutMilliseconds) const { + const CommonAPI::CallInfo *_info) const { assert(dbusMessage); assert(!dbusError); assert(isConnected()); suspendDispatching(); - ::DBusMessage* libdbusMessageReply = dbus_connection_send_with_reply_and_block(libdbusConnection_, - dbusMessage.libdbusMessage_, - timeoutMilliseconds, + ::DBusMessage* libdbusMessageReply = dbus_connection_send_with_reply_and_block(connection_, + dbusMessage.message_, + _info->timeout_, &dbusError.libdbusError_); + if (_info->sender_ != 0) { + COMMONAPI_DEBUG("Message sent: SenderID: ", _info->sender_, " - Serial number: ", dbusMessage.getSerial()); + } + resumeDispatching(); if (dbusError) { @@ -629,11 +624,18 @@ DBusMessage DBusConnection::sendDBusMessageWithReplyAndBlock(const DBusMessage& bool DBusConnection::singleDispatch() { - return (dbus_connection_dispatch(libdbusConnection_) == DBUS_DISPATCH_DATA_REMAINS); + for (auto t : mainloopTimeouts_) { + t.first->onDBusMessageReply(CallStatus::REMOTE_ERROR, t.second.createMethodError(DBUS_ERROR_TIMEOUT)); + delete t.first; + } + mainloopTimeouts_.clear(); + + return (dbus_connection_dispatch(connection_) == DBUS_DISPATCH_DATA_REMAINS); } bool DBusConnection::isDispatchReady() { - return (dbus_connection_get_dispatch_status(libdbusConnection_) == DBUS_DISPATCH_DATA_REMAINS); + return (dbus_connection_get_dispatch_status(connection_) == DBUS_DISPATCH_DATA_REMAINS || + !mainloopTimeouts_.empty()); } DBusProxyConnection::DBusSignalHandlerToken DBusConnection::subscribeForSelectiveBroadcast( @@ -648,22 +650,22 @@ DBusProxyConnection::DBusSignalHandlerToken DBusConnection::subscribeForSelectiv std::string methodName = "subscribeFor" + interfaceMemberName + "Selective"; subscriptionAccepted = false; + CommonAPI::CallStatus callStatus; DBusProxyHelper<CommonAPI::DBus::DBusSerializableArguments<>, CommonAPI::DBus::DBusSerializableArguments<bool>>::callMethodWithReply( - *callingProxy, methodName.c_str(), "", callStatus, subscriptionAccepted); + *callingProxy, methodName.c_str(), "", &CommonAPI::DBus::defaultCallInfo, callStatus, subscriptionAccepted); DBusProxyConnection::DBusSignalHandlerToken subscriptionToken; - if (callStatus == CommonAPI::CallStatus::SUCCESS && subscriptionAccepted) { subscriptionToken = addSignalMemberHandler( - objectPath, - interfaceName, - interfaceMemberName, - interfaceMemberSignature, - dbusSignalHandler, - true); - + objectPath, + interfaceName, + interfaceMemberName, + interfaceMemberSignature, + dbusSignalHandler, + true + ); subscriptionAccepted = true; } @@ -682,7 +684,7 @@ void DBusConnection::unsubscribeFromSelectiveBroadcast(const std::string& eventN CommonAPI::CallStatus callStatus; DBusProxyHelper<CommonAPI::DBus::DBusSerializableArguments<>, CommonAPI::DBus::DBusSerializableArguments<>>::callMethodWithReply( - *callingProxy, methodName.c_str(), "", callStatus); + *callingProxy, methodName.c_str(), "", &CommonAPI::DBus::defaultCallInfo, callStatus); } } @@ -698,56 +700,43 @@ DBusProxyConnection::DBusSignalHandlerToken DBusConnection::addSignalMemberHandl interfaceMemberName, interfaceMemberSignature); std::lock_guard < std::mutex > dbusSignalLock(signalGuard_); - const bool isFirstSignalMemberHandler = dbusSignalHandlerTable_.find(dbusSignalHandlerPath) - == dbusSignalHandlerTable_.end(); - dbusSignalHandlerTable_.insert(DBusSignalHandlerTable::value_type(dbusSignalHandlerPath, dbusSignalHandler)); + auto signalEntry = dbusSignalHandlerTable_.find(dbusSignalHandlerPath); + const bool isFirstSignalMemberHandler = (signalEntry == dbusSignalHandlerTable_.end()); if (isFirstSignalMemberHandler) { addLibdbusSignalMatchRule(objectPath, interfaceName, interfaceMemberName, justAddFilter); + std::set<DBusSignalHandler*> handlerList; + handlerList.insert(dbusSignalHandler); + + dbusSignalHandlerTable_.insert( { + dbusSignalHandlerPath, + std::make_pair(std::make_shared<std::recursive_mutex>(), std::move(handlerList)) + } ); + } else { + signalEntry->second.first->lock(); + signalEntry->second.second.insert(dbusSignalHandler); + signalEntry->second.first->unlock(); } return dbusSignalHandlerPath; } -bool DBusConnection::removeSignalMemberHandler(const DBusSignalHandlerToken& dbusSignalHandlerToken, - const DBusSignalHandler* dbusSignalHandler) { +bool DBusConnection::removeSignalMemberHandler(const DBusSignalHandlerToken &dbusSignalHandlerToken, + const DBusSignalHandler *dbusSignalHandler) { bool lastHandlerRemoved = false; + std::lock_guard < std::mutex > dbusSignalLock(signalGuard_); - std::lock_guard<std::mutex> dbusSignalLock(signalGuard_); - auto equalRangeIteratorPair = dbusSignalHandlerTable_.equal_range(dbusSignalHandlerToken); - if (equalRangeIteratorPair.first != equalRangeIteratorPair.second) { - // advance to the next element - auto iteratorToNextElement = equalRangeIteratorPair.first; - iteratorToNextElement++; - - // check if the first element was the only element - const bool isLastSignalMemberHandler = iteratorToNextElement == equalRangeIteratorPair.second; - - if (isLastSignalMemberHandler) { - const std::string& objectPath = std::get<0>(dbusSignalHandlerToken); - const std::string& interfaceName = std::get<1>(dbusSignalHandlerToken); - const std::string& interfaceMemberName = std::get<2>(dbusSignalHandlerToken); + auto signalEntry = dbusSignalHandlerTable_.find(dbusSignalHandlerToken); + if (signalEntry != dbusSignalHandlerTable_.end()) { - removeLibdbusSignalMatchRule(objectPath, interfaceName, interfaceMemberName); - lastHandlerRemoved = true; - } - - if(dbusSignalHandler == NULL) { - // remove all handlers - dbusSignalHandlerTable_.erase(dbusSignalHandlerToken); - } else { - // just remove specific handler - while(equalRangeIteratorPair.first != equalRangeIteratorPair.second) { - if(equalRangeIteratorPair.first->second == dbusSignalHandler) { - equalRangeIteratorPair.first = dbusSignalHandlerTable_.erase(equalRangeIteratorPair.first); - } - else { - equalRangeIteratorPair.first++; - } - } + signalEntry->second.first->lock(); + auto selectedHandler = signalEntry->second.second.find(const_cast<DBusSignalHandler*>(dbusSignalHandler)); + if (selectedHandler != signalEntry->second.second.end()) { + signalEntry->second.second.erase(selectedHandler); + lastHandlerRemoved = (signalEntry->second.second.empty()); } + signalEntry->second.first->unlock(); } - return lastHandlerRemoved; } @@ -758,6 +747,7 @@ bool DBusConnection::addObjectManagerSignalMemberHandler(const std::string& dbus } std::lock_guard<std::mutex> dbusSignalLock(dbusObjectManagerSignalGuard_); + auto dbusSignalMatchRuleIterator = dbusObjectManagerSignalMatchRulesMap_.find(dbusBusName); const bool isDBusSignalMatchRuleFound = (dbusSignalMatchRuleIterator != dbusObjectManagerSignalMatchRulesMap_.end()); @@ -774,17 +764,15 @@ bool DBusConnection::addObjectManagerSignalMemberHandler(const std::string& dbus const bool isRemoveSignalMatchRuleSuccessful = removeObjectManagerSignalMatchRule(dbusBusName); assert(isRemoveSignalMatchRuleSuccessful); } - return false; } dbusSignalMatchRuleIterator = insertResult.first; } - size_t& dbusSignalMatchRuleRefernceCount = dbusSignalMatchRuleIterator->second; - dbusSignalMatchRuleRefernceCount++; - - dbusObjectManagerSignalHandlerTable_.insert({ dbusBusName, dbusSignalHandler }); + size_t &dbusSignalMatchRuleReferenceCount = dbusSignalMatchRuleIterator->second; + dbusSignalMatchRuleReferenceCount++; + dbusObjectManagerSignalHandlerTable_.insert( { dbusBusName, dbusSignalHandler } ); return true; } @@ -794,6 +782,7 @@ bool DBusConnection::removeObjectManagerSignalMemberHandler(const std::string& d assert(!dbusBusName.empty()); std::lock_guard<std::mutex> dbusSignalLock(dbusObjectManagerSignalGuard_); + auto dbusSignalMatchRuleIterator = dbusObjectManagerSignalMatchRulesMap_.find(dbusBusName); const bool isDBusSignalMatchRuleFound = (dbusSignalMatchRuleIterator != dbusObjectManagerSignalMatchRulesMap_.end()); @@ -807,7 +796,6 @@ bool DBusConnection::removeObjectManagerSignalMemberHandler(const std::string& d dbusObjectManagerSignalHandlerRange.second, [&](decltype(*dbusObjectManagerSignalHandlerRange.first)& it) { return it.second == dbusSignalHandler; }); const bool isDBusSignalHandlerFound = (dbusObjectManagerSignalHandlerIterator != dbusObjectManagerSignalHandlerRange.second); - if (!isDBusSignalHandlerFound) { return false; } @@ -833,21 +821,17 @@ bool DBusConnection::removeObjectManagerSignalMemberHandler(const std::string& d bool DBusConnection::addObjectManagerSignalMatchRule(const std::string& dbusBusName) { std::ostringstream dbusMatchRuleStringStream; - dbusMatchRuleStringStream << "type='signal'" << ",sender='" << dbusBusName << "'" << ",interface='org.freedesktop.DBus.ObjectManager'"; - return addLibdbusSignalMatchRule(dbusMatchRuleStringStream.str()); } bool DBusConnection::removeObjectManagerSignalMatchRule(const std::string& dbusBusName) { std::ostringstream dbusMatchRuleStringStream; - dbusMatchRuleStringStream << "type='signal'" << ",sender='" << dbusBusName << "'" << ",interface='org.freedesktop.DBus.ObjectManager'"; - return removeLibdbusSignalMatchRule(dbusMatchRuleStringStream.str()); } @@ -864,17 +848,18 @@ bool DBusConnection::addLibdbusSignalMatchRule(const std::string& dbusMatchRule) // add the libdbus message signal filter if (!libdbusSignalMatchRulesCount_) { - libdbusSuccess = (bool) dbus_connection_add_filter( - libdbusConnection_, + libdbusSuccess = 0 != dbus_connection_add_filter( + connection_, &onLibdbusSignalFilterThunk, this, - NULL); + NULL + ); } // finally add the match rule if (libdbusSuccess) { DBusError dbusError; - dbus_bus_add_match(libdbusConnection_, dbusMatchRule.c_str(), &dbusError.libdbusError_); + dbus_bus_add_match(connection_, dbusMatchRule.c_str(), &dbusError.libdbusError_); libdbusSuccess = !dbusError; } @@ -894,21 +879,17 @@ bool DBusConnection::addLibdbusSignalMatchRule(const std::string& dbusMatchRule) * @return */ bool DBusConnection::removeLibdbusSignalMatchRule(const std::string& dbusMatchRule) { - //assert(libdbusSignalMatchRulesCount_ > 0); if(libdbusSignalMatchRulesCount_ == 0) return true; suspendDispatching(); - DBusError dbusError; - dbus_bus_remove_match(libdbusConnection_, dbusMatchRule.c_str(), &dbusError.libdbusError_); + dbus_bus_remove_match(connection_, dbusMatchRule.c_str(), NULL); - if (!dbusError) { - libdbusSignalMatchRulesCount_--; - if (libdbusSignalMatchRulesCount_ == 0) { - dbus_connection_remove_filter(libdbusConnection_, &onLibdbusSignalFilterThunk, this); - } - } + libdbusSignalMatchRulesCount_--; + if (libdbusSignalMatchRulesCount_ == 0) { + dbus_connection_remove_filter(connection_, &onLibdbusSignalFilterThunk, this); + } resumeDispatching(); @@ -932,7 +913,7 @@ void DBusConnection::registerObjectPath(const std::string& objectPath) { if (isConnected()) { DBusError dbusError; - const dbus_bool_t libdbusSuccess = dbus_connection_try_register_object_path(libdbusConnection_, + const dbus_bool_t libdbusSuccess = dbus_connection_try_register_object_path(connection_, objectPath.c_str(), getDBusObjectPathVTable(), this, @@ -960,9 +941,8 @@ void DBusConnection::unregisterObjectPath(const std::string& objectPath) { libdbusRegisteredObjectPaths_.erase(handlerIterator); if (isConnected()) { - dbus_bool_t libdbusSuccess = dbus_connection_unregister_object_path(libdbusConnection_, - objectPath.c_str()); - + dbus_bool_t libdbusSuccess + = dbus_connection_unregister_object_path(connection_, objectPath.c_str()); assert(libdbusSuccess); } } @@ -999,13 +979,16 @@ void DBusConnection::addLibdbusSignalMatchRule(const std::string& objectPath, assert(success.second); if (isConnected()) { + bool libdbusSuccess = true; suspendDispatching(); // add the libdbus message signal filter if (isFirstMatchRule) { - const dbus_bool_t libdbusSuccess = dbus_connection_add_filter(libdbusConnection_, - &onLibdbusSignalFilterThunk, - this, - NULL); + + libdbusSuccess = 0 != dbus_connection_add_filter( + connection_, + &onLibdbusSignalFilterThunk, + this, + NULL); assert(libdbusSuccess); } @@ -1013,10 +996,14 @@ void DBusConnection::addLibdbusSignalMatchRule(const std::string& objectPath, { // finally add the match rule DBusError dbusError; - dbus_bus_add_match(libdbusConnection_, matchRuleString.c_str(), &dbusError.libdbusError_); + dbus_bus_add_match(connection_, matchRuleString.c_str(), &dbusError.libdbusError_); assert(!dbusError); } + if (libdbusSuccess) { + libdbusSignalMatchRulesCount_++; + } + resumeDispatching(); } } @@ -1057,14 +1044,14 @@ void DBusConnection::initLibdbusObjectPathHandlerAfterConnect() { DBusError dbusError; dbus_bool_t libdbusSuccess; - for ( auto handlerIterator = libdbusRegisteredObjectPaths_.begin(); - handlerIterator != libdbusRegisteredObjectPaths_.end(); - handlerIterator++) { + for (auto handlerIterator = libdbusRegisteredObjectPaths_.begin(); + handlerIterator != libdbusRegisteredObjectPaths_.end(); + handlerIterator++) { const std::string& objectPath = handlerIterator->first; dbusError.clear(); - libdbusSuccess = dbus_connection_try_register_object_path(libdbusConnection_, + libdbusSuccess = dbus_connection_try_register_object_path(connection_, objectPath.c_str(), getDBusObjectPathVTable(), this, @@ -1107,24 +1094,38 @@ void DBusConnection::initLibdbusSignalFilterAfterConnect() { template<typename DBusSignalHandlersTable> void notifyDBusSignalHandlers(DBusSignalHandlersTable& dbusSignalHandlerstable, - std::pair<typename DBusSignalHandlersTable::iterator, - typename DBusSignalHandlersTable::iterator>& equalRange, + typename DBusSignalHandlersTable::iterator& signalEntry, const CommonAPI::DBus::DBusMessage& dbusMessage, ::DBusHandlerResult& dbusHandlerResult) { - if (equalRange.first != equalRange.second) { + if (signalEntry == dbusSignalHandlerstable.end() || signalEntry->second.second.empty()) { dbusHandlerResult = DBUS_HANDLER_RESULT_HANDLED; + return; + } + + signalEntry->second.first->lock(); + auto handlerEntry = signalEntry->second.second.begin(); + while (handlerEntry != signalEntry->second.second.end()) { + DBusProxyConnection::DBusSignalHandler* dbusSignalHandler = *handlerEntry; + dbusSignalHandler->onSignalDBusMessage(dbusMessage); + handlerEntry++; } + dbusHandlerResult = DBUS_HANDLER_RESULT_HANDLED; + signalEntry->second.first->unlock(); +} +template<typename DBusSignalHandlersTable> +void notifyDBusOMSignalHandlers(DBusSignalHandlersTable& dbusSignalHandlerstable, + std::pair<typename DBusSignalHandlersTable::iterator, + typename DBusSignalHandlersTable::iterator>& equalRange, + const CommonAPI::DBus::DBusMessage &dbusMessage, + ::DBusHandlerResult &dbusHandlerResult) { + if (equalRange.first != equalRange.second) { + dbusHandlerResult = DBUS_HANDLER_RESULT_HANDLED; + } while (equalRange.first != equalRange.second) { DBusProxyConnection::DBusSignalHandler* dbusSignalHandler = equalRange.first->second; - - auto dbusSignalHandlerSubscriptionStatus = dbusSignalHandler->onSignalDBusMessage(dbusMessage); - - if (dbusSignalHandlerSubscriptionStatus == SubscriptionStatus::CANCEL) { - equalRange.first = dbusSignalHandlerstable.erase(equalRange.first); - } else { - equalRange.first++; - } + dbusSignalHandler->onSignalDBusMessage(dbusMessage); + equalRange.first++; } } @@ -1152,24 +1153,23 @@ void notifyDBusSignalHandlers(DBusSignalHandlersTable& dbusSignalHandlerstable, ::DBusHandlerResult dbusHandlerResult = DBUS_HANDLER_RESULT_NOT_YET_HANDLED; signalGuard_.lock(); - auto dbusSignalHandlerIteratorPair = dbusSignalHandlerTable_.equal_range(DBusSignalHandlerPath( + auto signalEntry = dbusSignalHandlerTable_.find(DBusSignalHandlerPath( objectPath, interfaceName, interfaceMemberName, interfaceMemberSignature)); - notifyDBusSignalHandlers(dbusSignalHandlerTable_, - dbusSignalHandlerIteratorPair, - dbusMessage, - dbusHandlerResult); signalGuard_.unlock(); + notifyDBusSignalHandlers(dbusSignalHandlerTable_, + signalEntry, dbusMessage, dbusHandlerResult); + if (dbusMessage.hasInterfaceName("org.freedesktop.DBus.ObjectManager")) { - const char* dbusSenderName = dbusMessage.getSenderName(); + const char* dbusSenderName = dbusMessage.getSender(); assert(dbusSenderName); dbusObjectManagerSignalGuard_.lock(); auto dbusObjectManagerSignalHandlerIteratorPair = dbusObjectManagerSignalHandlerTable_.equal_range(dbusSenderName); - notifyDBusSignalHandlers(dbusObjectManagerSignalHandlerTable_, + notifyDBusOMSignalHandlers(dbusObjectManagerSignalHandlerTable_, dbusObjectManagerSignalHandlerIteratorPair, dbusMessage, dbusHandlerResult); @@ -1179,53 +1179,36 @@ void notifyDBusSignalHandlers(DBusSignalHandlersTable& dbusSignalHandlerstable, return dbusHandlerResult; } -::DBusHandlerResult DBusConnection::onLibdbusSignalFilterThunk(::DBusConnection* libdbusConnection, +::DBusHandlerResult DBusConnection::onLibdbusSignalFilterThunk(::DBusConnection *_dbusConnection, ::DBusMessage* libdbusMessage, void* userData) { - assert(libdbusConnection); + assert(_dbusConnection); assert(libdbusMessage); assert(userData); DBusConnection* dbusConnection = reinterpret_cast<DBusConnection*>(userData); - - assert(dbusConnection->libdbusConnection_ == libdbusConnection); - + assert(dbusConnection->connection_ == _dbusConnection); return dbusConnection->onLibdbusSignalFilter(libdbusMessage); } -::DBusHandlerResult DBusConnection::onLibdbusObjectPathMessageThunk(::DBusConnection* libdbusConnection, +::DBusHandlerResult DBusConnection::onLibdbusObjectPathMessageThunk(::DBusConnection *_dbusConnection, ::DBusMessage* libdbusMessage, void* userData) { - assert(libdbusConnection); + assert(_dbusConnection); assert(libdbusMessage); assert(userData); DBusConnection* dbusConnection = reinterpret_cast<DBusConnection*>(userData); - - assert(dbusConnection->libdbusConnection_ == libdbusConnection); - + assert(dbusConnection->connection_ == _dbusConnection); return dbusConnection->onLibdbusObjectPathMessage(libdbusMessage); } - -std::shared_ptr<DBusConnection> DBusConnection::getBus(const BusType& busType) { - return std::make_shared<DBusConnection>(busType); -} - -std::shared_ptr<DBusConnection> DBusConnection::wrapLibDBus(::DBusConnection* libDbusConnection) { - return std::make_shared<DBusConnection>(libDbusConnection); -} - -std::shared_ptr<DBusConnection> DBusConnection::getSessionBus() { - return getBus(BusType::SESSION); -} - -std::shared_ptr<DBusConnection> DBusConnection::getSystemBus() { - return getBus(BusType::SYSTEM); +std::shared_ptr<DBusConnection> DBusConnection::getBus(const DBusType_t &_type) { + return std::make_shared<DBusConnection>(_type); } -std::shared_ptr<DBusConnection> DBusConnection::getStarterBus() { - return getBus(BusType::STARTER); +std::shared_ptr<DBusConnection> DBusConnection::wrap(::DBusConnection *_connection) { + return std::make_shared<DBusConnection>(_connection); } } // namespace DBus diff --git a/src/CommonAPI/DBus/DBusConnection.h b/src/CommonAPI/DBus/DBusConnection.h deleted file mode 100644 index 7550c10..0000000 --- a/src/CommonAPI/DBus/DBusConnection.h +++ /dev/null @@ -1,242 +0,0 @@ -/* Copyright (C) 2013 BMW Group - * Author: Manfred Bathelt (manfred.bathelt@bmw.de) - * Author: Juergen Gehring (juergen.gehring@bmw.de) - * 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/. */ - -#if !defined (COMMONAPI_INTERNAL_COMPILATION) -#error "Only <CommonAPI/CommonAPI.h> can be included directly, this file may disappear or change contents." -#endif - -#ifndef COMMONAPI_DBUS_DBUS_CONNECTION_H_ -#define COMMONAPI_DBUS_DBUS_CONNECTION_H_ - -#include "DBusProxyConnection.h" -#include "DBusDaemonProxy.h" -#include "DBusServiceRegistry.h" -#include "DBusObjectManager.h" -#include "DBusMainLoopContext.h" -#include "DBusConnectionBusType.h" - -#include <dbus/dbus.h> - -#include <atomic> - - -namespace CommonAPI { -namespace DBus { - -class DBusObjectManager; - -class DBusConnectionStatusEvent: public DBusProxyConnection::ConnectionStatusEvent { - friend class DBusConnection; - - public: - DBusConnectionStatusEvent(DBusConnection* dbusConnection); - - protected: - virtual void onListenerAdded(const CancellableListener& listener); - - DBusConnection* dbusConnection_; -}; - -struct WatchContext { - WatchContext(std::weak_ptr<MainLoopContext> mainLoopContext, DispatchSource* dispatchSource) : - mainLoopContext_(mainLoopContext), dispatchSource_(dispatchSource) { - } - - std::weak_ptr<MainLoopContext> mainLoopContext_; - DispatchSource* dispatchSource_; -}; - -class DBusConnection: public DBusProxyConnection, public std::enable_shared_from_this<DBusConnection> { - public: - DBusConnection(BusType busType); - - static std::shared_ptr<DBusConnection> getBus(const BusType& dbusBusType); - static std::shared_ptr<DBusConnection> wrapLibDBus(::DBusConnection* libDbusConnection); - static std::shared_ptr<DBusConnection> getSessionBus(); - static std::shared_ptr<DBusConnection> getSystemBus(); - static std::shared_ptr<DBusConnection> getStarterBus(); - - DBusConnection(const DBusConnection&) = delete; - DBusConnection(::DBusConnection* libDbusConnection); - - DBusConnection& operator=(const DBusConnection&) = delete; - virtual ~DBusConnection(); - - BusType getBusType() const; - - bool connect(bool startDispatchThread = true); - bool connect(DBusError& dbusError, bool startDispatchThread = true); - void disconnect(); - - virtual bool isConnected() const; - - virtual ConnectionStatusEvent& getConnectionStatusEvent(); - - virtual bool requestServiceNameAndBlock(const std::string& serviceName) const; - virtual bool releaseServiceName(const std::string& serviceName) const; - - bool sendDBusMessage(const DBusMessage& dbusMessage, uint32_t* allocatedSerial = NULL) const; - - static const int kDefaultSendTimeoutMs = 5000; - - std::future<CallStatus> sendDBusMessageWithReplyAsync( - const DBusMessage& dbusMessage, - std::unique_ptr<DBusMessageReplyAsyncHandler> dbusMessageReplyAsyncHandler, - int timeoutMilliseconds = kDefaultSendTimeoutMs) const; - - DBusMessage sendDBusMessageWithReplyAndBlock(const DBusMessage& dbusMessage, - DBusError& dbusError, - int timeoutMilliseconds = kDefaultSendTimeoutMs) const; - - virtual bool addObjectManagerSignalMemberHandler(const std::string& dbusBusName, - DBusSignalHandler* dbusSignalHandler); - virtual bool removeObjectManagerSignalMemberHandler(const std::string& dbusBusName, - DBusSignalHandler* dbusSignalHandler); - - DBusSignalHandlerToken addSignalMemberHandler(const std::string& objectPath, - const std::string& interfaceName, - const std::string& interfaceMemberName, - const std::string& interfaceMemberSignature, - DBusSignalHandler* dbusSignalHandler, - const bool justAddFilter = false); - - DBusProxyConnection::DBusSignalHandlerToken subscribeForSelectiveBroadcast(bool& subscriptionAccepted, - const std::string& objectPath, - const std::string& interfaceName, - const std::string& interfaceMemberName, - const std::string& interfaceMemberSignature, - DBusSignalHandler* dbusSignalHandler, - DBusProxy* callingProxy); - - void unsubscribeFromSelectiveBroadcast(const std::string& eventName, - DBusProxyConnection::DBusSignalHandlerToken subscription, - DBusProxy* callingProxy, - const DBusSignalHandler* dbusSignalHandler); - - void registerObjectPath(const std::string& objectPath); - void unregisterObjectPath(const std::string& objectPath); - - bool removeSignalMemberHandler(const DBusSignalHandlerToken& dbusSignalHandlerToken, - const DBusSignalHandler* dbusSignalHandler = NULL); - bool readWriteDispatch(int timeoutMilliseconds = -1); - - virtual const std::shared_ptr<DBusServiceRegistry> getDBusServiceRegistry(); - virtual const std::shared_ptr<DBusObjectManager> getDBusObjectManager(); - - void setObjectPathMessageHandler(DBusObjectPathMessageHandler); - bool isObjectPathMessageHandlerSet(); - - virtual bool attachMainLoopContext(std::weak_ptr<MainLoopContext>); - - bool isDispatchReady(); - bool singleDispatch(); - - typedef std::tuple<std::string, std::string, std::string> DBusSignalMatchRuleTuple; - typedef std::pair<uint32_t, std::string> DBusSignalMatchRuleMapping; - typedef std::unordered_map<DBusSignalMatchRuleTuple, DBusSignalMatchRuleMapping> DBusSignalMatchRulesMap; - private: - void dispatch(); - void suspendDispatching() const; - void resumeDispatching() const; - - std::thread* dispatchThread_; - bool stopDispatching_; - - std::weak_ptr<MainLoopContext> mainLoopContext_; - DispatchSource* dispatchSource_; - WatchContext* watchContext_; - - mutable bool pauseDispatching_; - mutable std::mutex dispatchSuspendLock_; - - void addLibdbusSignalMatchRule(const std::string& objectPath, - const std::string& interfaceName, - const std::string& interfaceMemberName, - const bool justAddFilter = false); - - void removeLibdbusSignalMatchRule(const std::string& objectPath, - const std::string& interfaceName, - const std::string& interfaceMemberName); - - void initLibdbusSignalFilterAfterConnect(); - ::DBusHandlerResult onLibdbusSignalFilter(::DBusMessage* libdbusMessage); - - void initLibdbusObjectPathHandlerAfterConnect(); - ::DBusHandlerResult onLibdbusObjectPathMessage(::DBusMessage* libdbusMessage); - - static void onLibdbusPendingCallNotifyThunk(::DBusPendingCall* libdbusPendingCall, void* userData); - static void onLibdbusDataCleanup(void* userData); - - static ::DBusHandlerResult onLibdbusObjectPathMessageThunk(::DBusConnection* libdbusConnection, - ::DBusMessage* libdbusMessage, - void* userData); - - static ::DBusHandlerResult onLibdbusSignalFilterThunk(::DBusConnection* libdbusConnection, - ::DBusMessage* libdbusMessage, - void* userData); - - static dbus_bool_t onAddWatch(::DBusWatch* libdbusWatch, void* data); - static void onRemoveWatch(::DBusWatch* libdbusWatch, void* data); - static void onToggleWatch(::DBusWatch* libdbusWatch, void* data); - - static dbus_bool_t onAddTimeout(::DBusTimeout* dbus_timeout, void* data); - static void onRemoveTimeout(::DBusTimeout* dbus_timeout, void* data); - static void onToggleTimeout(::DBusTimeout* dbus_timeout, void* data); - - static void onWakeupMainContext(void* data); - - void enforceAsynchronousTimeouts() const; - static const DBusObjectPathVTable* getDBusObjectPathVTable(); - - ::DBusConnection* libdbusConnection_; - mutable std::mutex libdbusConnectionGuard_; - std::mutex signalGuard_; - std::mutex objectManagerGuard_; - std::mutex serviceRegistryGuard_; - - BusType busType_; - - std::weak_ptr<DBusServiceRegistry> dbusServiceRegistry_; - std::shared_ptr<DBusObjectManager> dbusObjectManager_; - - DBusConnectionStatusEvent dbusConnectionStatusEvent_; - - DBusSignalMatchRulesMap dbusSignalMatchRulesMap_; - - DBusSignalHandlerTable dbusSignalHandlerTable_; - - std::unordered_map<std::string, size_t> dbusObjectManagerSignalMatchRulesMap_; - std::unordered_multimap<std::string, DBusSignalHandler*> dbusObjectManagerSignalHandlerTable_; - std::mutex dbusObjectManagerSignalGuard_; - - bool addObjectManagerSignalMatchRule(const std::string& dbusBusName); - bool removeObjectManagerSignalMatchRule(const std::string& dbusBusName); - - bool addLibdbusSignalMatchRule(const std::string& dbusMatchRule); - bool removeLibdbusSignalMatchRule(const std::string& dbusMatchRule); - - std::atomic_size_t libdbusSignalMatchRulesCount_; - - // objectPath, referenceCount - typedef std::unordered_map<std::string, uint32_t> LibdbusRegisteredObjectPathHandlersTable; - LibdbusRegisteredObjectPathHandlersTable libdbusRegisteredObjectPaths_; - - DBusObjectPathMessageHandler dbusObjectMessageHandler_; - - mutable std::unordered_map<std::string, uint16_t> connectionNameCount_; - - typedef std::pair<DBusPendingCall*, std::tuple<int, DBusMessageReplyAsyncHandler*, DBusMessage> > TimeoutMapElement; - mutable std::map<DBusPendingCall*, std::tuple<int, DBusMessageReplyAsyncHandler*, DBusMessage>> timeoutMap_; - mutable std::shared_ptr<std::thread> enforcerThread_; - mutable std::mutex enforceTimeoutMutex_; -}; - - -} // namespace DBus -} // namespace CommonAPI - -#endif // COMMONAPI_DBUS_DBUS_CONNECTION_H_ diff --git a/src/CommonAPI/DBus/DBusConnectionBusType.h b/src/CommonAPI/DBus/DBusConnectionBusType.h deleted file mode 100644 index bdb98d9..0000000 --- a/src/CommonAPI/DBus/DBusConnectionBusType.h +++ /dev/null @@ -1,26 +0,0 @@ -/* Copyright (C) 2013 BMW Group - * Author: Manfred Bathelt (manfred.bathelt@bmw.de) - * Author: Juergen Gehring (juergen.gehring@bmw.de) - * 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/. */ - -#ifndef DBUSCONNECTIONBUSTYPE_H_ -#define DBUSCONNECTIONBUSTYPE_H_ - -#include <dbus/dbus-shared.h> - -namespace CommonAPI { -namespace DBus { - -enum BusType { - SESSION = DBUS_BUS_SESSION, - SYSTEM = DBUS_BUS_SYSTEM, - STARTER = DBUS_BUS_STARTER, - WRAPPED -}; - -} // namespace DBus -} // namespace CommonAPI - -#endif /* DBUSCONNECTIONBUSTYPE_H_ */ diff --git a/src/CommonAPI/DBus/DBusDaemonProxy.cpp b/src/CommonAPI/DBus/DBusDaemonProxy.cpp index e6ed98c..489f06b 100644 --- a/src/CommonAPI/DBus/DBusDaemonProxy.cpp +++ b/src/CommonAPI/DBus/DBusDaemonProxy.cpp @@ -1,12 +1,12 @@ -/* Copyright (C) 2013 BMW Group - * Author: Manfred Bathelt (manfred.bathelt@bmw.de) - * Author: Juergen Gehring (juergen.gehring@bmw.de) - * 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 "DBusDaemonProxy.h" -#include "DBusProxyHelper.h" +// 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/. +#include <CommonAPI/Address.hpp> +#include <CommonAPI/DBus/DBusAddress.hpp> +#include <CommonAPI/DBus/DBusDaemonProxy.hpp> +#include <CommonAPI/DBus/DBusProxyHelper.hpp> namespace CommonAPI { namespace DBus { @@ -15,12 +15,14 @@ StaticInterfaceVersionAttribute::StaticInterfaceVersionAttribute(const uint32_t& version_(majorValue, minorValue) { } -void StaticInterfaceVersionAttribute::getValue(CallStatus& callStatus, Version& version) const { - version = version_; - callStatus = CallStatus::SUCCESS; +void StaticInterfaceVersionAttribute::getValue(CallStatus &_status, Version &_version, + const CommonAPI::CallInfo *_info) const { + _version = version_; + _status = CallStatus::SUCCESS; } -std::future<CallStatus> StaticInterfaceVersionAttribute::getValueAsync(AttributeAsyncCallback attributeAsyncCallback) { +std::future<CallStatus> StaticInterfaceVersionAttribute::getValueAsync(AttributeAsyncCallback attributeAsyncCallback, + const CommonAPI::CallInfo *_info) { attributeAsyncCallback(CallStatus::SUCCESS, version_); std::promise<CallStatus> versionPromise; @@ -29,44 +31,22 @@ std::future<CallStatus> StaticInterfaceVersionAttribute::getValueAsync(Attribute return versionPromise.get_future(); } - -static const std::string dbusDaemonBusName_ = "org.freedesktop.DBus"; -static const std::string dbusDaemonObjectPath_ = "/org/freedesktop/DBus"; -static const std::string dbusDaemonInterfaceName_ = DBusDaemonProxy::getInterfaceId(); -static const std::string commonApiParticipantId_ = "org.freedesktop.DBus-/org/freedesktop/DBus"; - +//static const char *DAEMON_COMMONAPI_ADDRESS = "org.freedesktop.DBus-/org/freedesktop/DBus"; +static const char *DAEMON_DBUS_INTERFACE = DBusDaemonProxy::getInterfaceId(); +static const char *DAEMON_DBUS_OBJECT_PATH = "/org/freedesktop/DBus"; +static const char *DAEMON_DBUS_BUS = "org.freedesktop.DBus"; +static DBusAddress dbusProxyAddress(DAEMON_DBUS_INTERFACE, DAEMON_DBUS_OBJECT_PATH, DAEMON_DBUS_BUS); +static CommonAPI::CallInfo daemonProxyInfo(2000); DBusDaemonProxy::DBusDaemonProxy(const std::shared_ptr<DBusProxyConnection>& dbusConnection): - DBusProxyBase(dbusConnection), - nameOwnerChangedEvent_(*this, "NameOwnerChanged", "sss"), + DBusProxyBase(dbusProxyAddress, dbusConnection), + nameOwnerChangedEvent_(*this, + "NameOwnerChanged", "sss", + std::tuple<std::string, std::string, std::string>()), interfaceVersionAttribute_(1, 0) { } void DBusDaemonProxy::init() { - -} - -std::string DBusDaemonProxy::getAddress() const { - return getDomain() + ":" + getServiceId() + ":" + getInstanceId(); -} -const std::string& DBusDaemonProxy::getDomain() const { - return commonApiDomain_; -} -const std::string& DBusDaemonProxy::getServiceId() const { - return dbusDaemonInterfaceName_; -} -const std::string& DBusDaemonProxy::getInstanceId() const { - return commonApiParticipantId_; -} - -const std::string& DBusDaemonProxy::getDBusBusName() const { - return dbusDaemonBusName_; -} -const std::string& DBusDaemonProxy::getDBusObjectPath() const { - return dbusDaemonObjectPath_; -} -const std::string& DBusDaemonProxy::getInterfaceName() const { - return dbusDaemonInterfaceName_; } bool DBusDaemonProxy::isAvailable() const { @@ -93,7 +73,8 @@ void DBusDaemonProxy::listNames(CommonAPI::CallStatus& callStatus, std::vector<s DBusMessage dbusMethodCall = createMethodCall("ListNames", ""); DBusError dbusError; - DBusMessage dbusMessageReply = getDBusConnection()->sendDBusMessageWithReplyAndBlock(dbusMethodCall, dbusError); + DBusMessage dbusMessageReply + = getDBusConnection()->sendDBusMessageWithReplyAndBlock(dbusMethodCall, dbusError, &daemonProxyInfo); if (dbusError || !dbusMessageReply.isMethodReturnType()) { callStatus = CallStatus::REMOTE_ERROR; @@ -112,11 +93,10 @@ void DBusDaemonProxy::listNames(CommonAPI::CallStatus& callStatus, std::vector<s std::future<CallStatus> DBusDaemonProxy::listNamesAsync(ListNamesAsyncCallback listNamesAsyncCallback) const { DBusMessage dbusMessage = createMethodCall("ListNames", ""); - return getDBusConnection()->sendDBusMessageWithReplyAsync( dbusMessage, - DBusProxyAsyncCallbackHandler<std::vector<std::string>>::create(listNamesAsyncCallback), - 2000); + DBusProxyAsyncCallbackHandler<std::vector<std::string>>::create(listNamesAsyncCallback, std::tuple<std::vector<std::string>>()), + &daemonProxyInfo); } void DBusDaemonProxy::nameHasOwner(const std::string& busName, CommonAPI::CallStatus& callStatus, bool& hasOwner) const { @@ -133,7 +113,8 @@ void DBusDaemonProxy::nameHasOwner(const std::string& busName, CommonAPI::CallSt DBusError dbusError; DBusMessage dbusMessageReply = getDBusConnection()->sendDBusMessageWithReplyAndBlock( dbusMethodCall, - dbusError); + dbusError, + &daemonProxyInfo); if (dbusError || !dbusMessageReply.isMethodReturnType()) { callStatus = CallStatus::REMOTE_ERROR; return; @@ -162,23 +143,20 @@ std::future<CallStatus> DBusDaemonProxy::nameHasOwnerAsync(const std::string& bu return getDBusConnection()->sendDBusMessageWithReplyAsync( dbusMessage, - DBusProxyAsyncCallbackHandler<bool>::create(nameHasOwnerAsyncCallback), - 2000); + DBusProxyAsyncCallbackHandler<bool>::create(nameHasOwnerAsyncCallback, std::tuple<bool>()), + &daemonProxyInfo); } std::future<CallStatus> DBusDaemonProxy::getManagedObjectsAsync(const std::string& forDBusServiceName, GetManagedObjectsAsyncCallback callback) const { - // resolve remote objects - auto dbusMethodCallMessage = DBusMessage::createMethodCall( - forDBusServiceName, - "/", - "org.freedesktop.DBus.ObjectManager", - "GetManagedObjects", - ""); + static DBusAddress address(forDBusServiceName, "/", "org.freedesktop.DBus.ObjectManager"); + auto dbusMethodCallMessage = DBusMessage::createMethodCall(address, "GetManagedObjects", ""); return getDBusConnection()->sendDBusMessageWithReplyAsync( dbusMethodCallMessage, - DBusProxyAsyncCallbackHandler<DBusObjectToInterfaceDict>::create(callback), - 2000); + DBusProxyAsyncCallbackHandler<DBusObjectToInterfaceDict>::create( + callback, std::tuple<DBusObjectToInterfaceDict>() + ), + &daemonProxyInfo); } std::future<CallStatus> DBusDaemonProxy::getNameOwnerAsync(const std::string& busName, GetNameOwnerAsyncCallback getNameOwnerAsyncCallback) const { @@ -195,8 +173,8 @@ std::future<CallStatus> DBusDaemonProxy::getNameOwnerAsync(const std::string& bu return getDBusConnection()->sendDBusMessageWithReplyAsync( dbusMessage, - DBusProxyAsyncCallbackHandler<std::string>::create(getNameOwnerAsyncCallback), - 2000); + DBusProxyAsyncCallbackHandler<std::string>::create(getNameOwnerAsyncCallback, std::tuple<std::string>()), + &daemonProxyInfo); } const char* DBusDaemonProxy::getInterfaceId() { diff --git a/src/CommonAPI/DBus/DBusDaemonProxy.h b/src/CommonAPI/DBus/DBusDaemonProxy.h deleted file mode 100644 index 5db2932..0000000 --- a/src/CommonAPI/DBus/DBusDaemonProxy.h +++ /dev/null @@ -1,101 +0,0 @@ -/* Copyright (C) 2013 BMW Group - * Author: Manfred Bathelt (manfred.bathelt@bmw.de) - * Author: Juergen Gehring (juergen.gehring@bmw.de) - * 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/. */ - -#if !defined (COMMONAPI_INTERNAL_COMPILATION) -#error "Only <CommonAPI/CommonAPI.h> can be included directly, this file may disappear or change contents." -#endif - -#ifndef COMMONAPI_DBUS_DBUS_DAEMON_PROXY_H_ -#define COMMONAPI_DBUS_DBUS_DAEMON_PROXY_H_ - -#include "DBusProxyBase.h" -#include "DBusEvent.h" - -#include <functional> -#include <string> -#include <vector> - - -namespace CommonAPI { -namespace DBus { - -class StaticInterfaceVersionAttribute: public InterfaceVersionAttribute { - public: - StaticInterfaceVersionAttribute(const uint32_t& majorValue, const uint32_t& minorValue); - - void getValue(CallStatus& callStatus, Version& version) const; - std::future<CallStatus> getValueAsync(AttributeAsyncCallback attributeAsyncCallback); - - private: - Version version_; -}; - - -class DBusDaemonProxy: public DBusProxyBase { - public: - typedef Event<std::string, std::string, std::string> NameOwnerChangedEvent; - - typedef std::unordered_map<std::string, int> PropertyDictStub; - typedef std::unordered_map<std::string, PropertyDictStub> InterfaceToPropertyDict; - typedef std::unordered_map<std::string, InterfaceToPropertyDict> DBusObjectToInterfaceDict; - - typedef std::function<void(const CommonAPI::CallStatus&, std::vector<std::string>)> ListNamesAsyncCallback; - typedef std::function<void(const CommonAPI::CallStatus&, bool)> NameHasOwnerAsyncCallback; - typedef std::function<void(const CommonAPI::CallStatus&, DBusObjectToInterfaceDict)> GetManagedObjectsAsyncCallback; - typedef std::function<void(const CommonAPI::CallStatus&, std::string)> GetNameOwnerAsyncCallback; - - DBusDaemonProxy(const std::shared_ptr<DBusProxyConnection>& dbusConnection); - - virtual bool isAvailable() const; - virtual bool isAvailableBlocking() const; - virtual ProxyStatusEvent& getProxyStatusEvent(); - virtual InterfaceVersionAttribute& getInterfaceVersionAttribute(); - - void init(); - - static const char* getInterfaceId(); - - NameOwnerChangedEvent& getNameOwnerChangedEvent(); - - void listNames(CommonAPI::CallStatus& callStatus, std::vector<std::string>& busNames) const; - std::future<CallStatus> listNamesAsync(ListNamesAsyncCallback listNamesAsyncCallback) const; - - void nameHasOwner(const std::string& busName, CommonAPI::CallStatus& callStatus, bool& hasOwner) const; - std::future<CallStatus> nameHasOwnerAsync(const std::string& busName, - NameHasOwnerAsyncCallback nameHasOwnerAsyncCallback) const; - - std::future<CallStatus> getManagedObjectsAsync(const std::string& forDBusServiceName, - GetManagedObjectsAsyncCallback) const; - - /** - * Get the unique connection/bus name of the primary owner of the name given - * - * @param busName Name to get the owner of - * @param getNameOwnerAsyncCallback callback functor - * - * @return CallStatus::REMOTE_ERROR if the name is unknown, otherwise CallStatus::SUCCESS and the uniq name of the owner - */ - std::future<CallStatus> getNameOwnerAsync(const std::string& busName, GetNameOwnerAsyncCallback getNameOwnerAsyncCallback) const; - - virtual std::string getAddress() const; - virtual const std::string& getDomain() const; - virtual const std::string& getServiceId() const; - virtual const std::string& getInstanceId() const; - - virtual const std::string& getDBusBusName() const; - virtual const std::string& getDBusObjectPath() const; - virtual const std::string& getInterfaceName() const; - - private: - DBusEvent<NameOwnerChangedEvent> nameOwnerChangedEvent_; - StaticInterfaceVersionAttribute interfaceVersionAttribute_; -}; - -} // namespace DBus -} // namespace CommonAPI - -#endif // COMMONAPI_DBUS_DBUS_DAEMON_PROXY_H_ diff --git a/src/CommonAPI/DBus/DBusDeployment.cpp b/src/CommonAPI/DBus/DBusDeployment.cpp new file mode 100644 index 0000000..973d5ff --- /dev/null +++ b/src/CommonAPI/DBus/DBusDeployment.cpp @@ -0,0 +1,14 @@ +// 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 4b58a5e..9dfb082 100644 --- a/src/CommonAPI/DBus/DBusError.cpp +++ b/src/CommonAPI/DBus/DBusError.cpp @@ -1,18 +1,16 @@ -/* Copyright (C) 2013 BMW Group - * Author: Manfred Bathelt (manfred.bathelt@bmw.de) - * Author: Juergen Gehring (juergen.gehring@bmw.de) - * 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 "DBusError.h" +// 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/. #include <cassert> #include <cstring> +#include <CommonAPI/DBus/DBusError.hpp> + namespace CommonAPI { namespace DBus { - DBusError::DBusError() { dbus_error_init(&libdbusError_); } @@ -22,7 +20,7 @@ DBusError::~DBusError() { } DBusError::operator bool() const { - return dbus_error_is_set(&libdbusError_); + return 0 != dbus_error_is_set(&libdbusError_); } void DBusError::clear() { diff --git a/src/CommonAPI/DBus/DBusError.h b/src/CommonAPI/DBus/DBusError.h deleted file mode 100644 index 8feaa99..0000000 --- a/src/CommonAPI/DBus/DBusError.h +++ /dev/null @@ -1,45 +0,0 @@ -/* Copyright (C) 2013 BMW Group - * Author: Manfred Bathelt (manfred.bathelt@bmw.de) - * Author: Juergen Gehring (juergen.gehring@bmw.de) - * 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/. */ - -#if !defined (COMMONAPI_INTERNAL_COMPILATION) -#error "Only <CommonAPI/CommonAPI.h> can be included directly, this file may disappear or change contents." -#endif - -#ifndef COMMONAPI_DBUS_DBUS_ERROR_H_ -#define COMMONAPI_DBUS_DBUS_ERROR_H_ - -#include <string> -#include <dbus/dbus.h> - -namespace CommonAPI { -namespace DBus { - -class DBusConnection; - - -class DBusError { - public: - DBusError(); - ~DBusError(); - - operator bool() const; - - void clear(); - - std::string getName() const; - std::string getMessage() const; - - private: - ::DBusError libdbusError_; - - friend class DBusConnection; -}; - -} // namespace DBus -} // namespace CommonAPI - -#endif // COMMONAPI_DBUS_DBUS_ERROR_H_ diff --git a/src/CommonAPI/DBus/DBusEvent.h b/src/CommonAPI/DBus/DBusEvent.h deleted file mode 100644 index df21e24..0000000 --- a/src/CommonAPI/DBus/DBusEvent.h +++ /dev/null @@ -1,110 +0,0 @@ -/* Copyright (C) 2013 BMW Group - * Author: Manfred Bathelt (manfred.bathelt@bmw.de) - * Author: Juergen Gehring (juergen.gehring@bmw.de) - * 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/. */ - -#if !defined (COMMONAPI_INTERNAL_COMPILATION) -#error "Only <CommonAPI/CommonAPI.h> can be included directly, this file may disappear or change contents." -#endif - -#ifndef COMMONAPI_DBUS_DBUS_EVENT_H_ -#define COMMONAPI_DBUS_DBUS_EVENT_H_ - -#include "DBusProxyConnection.h" -#include "DBusMessage.h" -#include "DBusSerializableArguments.h" -#include "DBusHelper.h" - -#include <CommonAPI/Event.h> - -namespace CommonAPI { -namespace DBus { - -class DBusProxyBase; - - -template <typename _EventType, typename _DBusProxy = DBusProxyBase> -class DBusEvent: public _EventType, public DBusProxyConnection::DBusSignalHandler { - public: - typedef typename _EventType::ArgumentsTuple ArgumentsTuple; - typedef typename _EventType::CancellableListener CancellableListener; - - - DBusEvent(_DBusProxy& dbusProxy, const char* eventName, const char* eventSignature): - dbusProxy_(dbusProxy), - eventName_(eventName), - eventSignature_(eventSignature) { - interfaceName_ = dbusProxy.getInterfaceName().c_str(); - objectPath_ = dbusProxy_.getDBusObjectPath().c_str(); - assert(eventName_); - assert(eventSignature_); - assert(objectPath_); - assert(interfaceName_); - } - - DBusEvent(_DBusProxy& dbusProxy, const char* eventName, const char* eventSignature, const char* objPath, const char* interfaceName) : - dbusProxy_(dbusProxy), - eventName_(eventName), - eventSignature_(eventSignature), - objectPath_(objPath), - interfaceName_(interfaceName) { - assert(eventName); - assert(eventSignature); - assert(objPath); - assert(interfaceName); - } - - virtual ~DBusEvent() { - if (this->hasListeners()) - dbusProxy_.removeSignalMemberHandler(subscription_, this); - } - - virtual SubscriptionStatus onSignalDBusMessage(const DBusMessage& dbusMessage) { - return unpackArgumentsAndHandleSignalDBusMessage(dbusMessage, ArgumentsTuple()); - } - protected: - virtual void onFirstListenerAdded(const CancellableListener&) { - subscription_ = dbusProxy_.addSignalMemberHandler(objectPath_, - interfaceName_, - eventName_, - eventSignature_, - this); - } - - virtual void onLastListenerRemoved(const CancellableListener&) { - dbusProxy_.removeSignalMemberHandler(subscription_, this); - } - - template<typename ... _Arguments> - inline SubscriptionStatus unpackArgumentsAndHandleSignalDBusMessage(const DBusMessage& dbusMessage, - std::tuple<_Arguments...> argTuple) { - return handleSignalDBusMessage(dbusMessage, std::move(argTuple), typename make_sequence<sizeof...(_Arguments)>::type()); - } - - template<typename ... _Arguments, int ... _ArgIndices> - inline SubscriptionStatus handleSignalDBusMessage(const DBusMessage& dbusMessage, - std::tuple<_Arguments...> argTuple, - index_sequence<_ArgIndices...>) { - DBusInputStream dbusInputStream(dbusMessage); - const bool success = DBusSerializableArguments<_Arguments...>::deserialize( - dbusInputStream, - std::get<_ArgIndices>(argTuple)...); - // Continue subscription if deserialization failed - return success ? this->notifyListeners(std::get<_ArgIndices>(argTuple)...) : SubscriptionStatus::RETAIN; - } - - _DBusProxy& dbusProxy_; - const char* eventName_; - const char* eventSignature_; - const char* objectPath_; - const char* interfaceName_; - DBusProxyConnection::DBusSignalHandlerToken subscription_; -}; - -} // namespace DBus -} // namespace CommonAPI - -#endif // COMMONAPI_DBUS_DBUS_EVENT_H_ - diff --git a/src/CommonAPI/DBus/DBusFactory.cpp b/src/CommonAPI/DBus/DBusFactory.cpp index c0b2cdd..4f7e0b9 100644 --- a/src/CommonAPI/DBus/DBusFactory.cpp +++ b/src/CommonAPI/DBus/DBusFactory.cpp @@ -1,217 +1,346 @@ -/* Copyright (C) 2013 BMW Group - * Author: Manfred Bathelt (manfred.bathelt@bmw.de) - * Author: Juergen Gehring (juergen.gehring@bmw.de) - * 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 "DBusProxy.h" -#include "DBusConnection.h" -#include "DBusFactory.h" -#include "DBusServiceRegistry.h" -#include "DBusUtils.h" -#include "DBusServicePublisher.h" - -#include <algorithm> -#include <cassert> +// 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/. + +#include <iostream> #include <sstream> -#include <unordered_map> -#include <vector> + +#include <CommonAPI/Logger.hpp> +#include <CommonAPI/Runtime.hpp> +#include <CommonAPI/DBus/DBusAddressTranslator.hpp> +#include <CommonAPI/DBus/DBusConnection.hpp> +#include <CommonAPI/DBus/DBusFactory.hpp> +#include <CommonAPI/DBus/DBusProxy.hpp> +#include <CommonAPI/DBus/DBusStubAdapter.hpp> namespace CommonAPI { namespace DBus { - -std::unordered_map<std::string, DBusProxyFactoryFunction>* registeredProxyFactoryFunctions_; -std::unordered_map<std::string, DBusAdapterFactoryFunction>* registeredAdapterFactoryFunctions_; - - -void DBusFactory::registerProxyFactoryMethod(std::string interfaceName, DBusProxyFactoryFunction proxyFactoryMethod) { - if(!registeredProxyFactoryFunctions_) { - registeredProxyFactoryFunctions_ = new std::unordered_map<std::string, DBusProxyFactoryFunction>(); - } - registeredProxyFactoryFunctions_->insert({interfaceName, proxyFactoryMethod}); +INITIALIZER(FactoryInit) { + Runtime::get()->registerFactory("dbus", Factory::get()); } -void DBusFactory::registerAdapterFactoryMethod(std::string interfaceName, DBusAdapterFactoryFunction adapterFactoryMethod) { - if(!registeredAdapterFactoryFunctions_) { - registeredAdapterFactoryFunctions_ = new std::unordered_map<std::string, DBusAdapterFactoryFunction>(); - } - registeredAdapterFactoryFunctions_->insert({interfaceName, adapterFactoryMethod}); +std::shared_ptr<CommonAPI::DBus::Factory> +Factory::get() { + static std::shared_ptr<Factory> theFactory = std::make_shared<Factory>(); + return theFactory; } - -DBusFactory::DBusFactory(std::shared_ptr<Runtime> runtime, - const MiddlewareInfo* middlewareInfo, - std::shared_ptr<MainLoopContext> mainLoopContext, - const DBusFactoryConfig& DBusFactoryConfig) : - CommonAPI::Factory(runtime, middlewareInfo), - mainLoopContext_(mainLoopContext), - DBusFactoryConfig_(DBusFactoryConfig){ - - dbusConnection_ = CommonAPI::DBus::DBusConnection::getBus(DBusFactoryConfig_.busType_); - bool startDispatchThread = !mainLoopContext_; - dbusConnection_->connect(startDispatchThread); - if (mainLoopContext_) { - dbusConnection_->attachMainLoopContext(mainLoopContext_); - } +Factory::Factory() + : defaultBusType_(DBusType_t::SESSION) { } - -DBusFactory::~DBusFactory() { +Factory::~Factory() { } - -std::vector<std::string> DBusFactory::getAvailableServiceInstances(const std::string& serviceName, - const std::string& domainName) { - return dbusConnection_->getDBusServiceRegistry()->getAvailableServiceInstances(serviceName, domainName); +void +Factory::registerProxyCreateMethod( + const std::string &_interface, ProxyCreateFunction _function) { + proxyCreateFunctions_[_interface] = _function; } - -void DBusFactory::getAvailableServiceInstancesAsync(Factory::GetAvailableServiceInstancesCallback callback, const std::string& serviceName, const std::string& serviceDomainName) { - dbusConnection_->getDBusServiceRegistry()->getAvailableServiceInstancesAsync(callback, serviceName, serviceDomainName); +void +Factory::registerStubAdapterCreateMethod( + const std::string &_interface, StubAdapterCreateFunction _function) { + stubAdapterCreateFunctions_[_interface] = _function; } - -bool DBusFactory::isServiceInstanceAlive(const std::string& serviceAddress) { - std::vector<std::string> parts = split(serviceAddress, ':'); - assert(parts[0] == "local"); - - std::string interfaceName; - std::string connectionName; - std::string objectPath; - DBusAddressTranslator::getInstance().searchForDBusAddress(serviceAddress, interfaceName, connectionName, objectPath); - - return dbusConnection_->getDBusServiceRegistry()->isServiceInstanceAlive(interfaceName, connectionName, objectPath); +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; } - -bool DBusFactory::isServiceInstanceAlive(const std::string& participantId, - const std::string& serviceName, - const std::string& domainName) { - std::string serviceAddress = domainName + ":" + serviceName + ":" + participantId; - return isServiceInstanceAlive(serviceAddress); +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; } - -SubscriptionStatus DBusFactory::isServiceInstanceAliveCallbackThunk(Factory::IsServiceInstanceAliveCallback callback, const AvailabilityStatus& status, std::shared_ptr<DBusServiceRegistry> serviceRegistry) { - callback(status == AvailabilityStatus::AVAILABLE); - return SubscriptionStatus::CANCEL; +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; } -void DBusFactory::isServiceInstanceAliveAsync(Factory::IsServiceInstanceAliveCallback callback, const std::string& serviceAddress) { - std::string interfaceName; - std::string connectionName; - std::string objectPath; - - DBusAddressTranslator::getInstance().searchForDBusAddress(serviceAddress, interfaceName, connectionName, objectPath); - - std::shared_ptr<DBusServiceRegistry> serviceRegistry = dbusConnection_->getDBusServiceRegistry(); - - serviceRegistry->subscribeAvailabilityListener( - serviceAddress, - std::bind(&DBusFactory::isServiceInstanceAliveCallbackThunk, - this, - callback, - std::placeholders::_1, - serviceRegistry) - ); +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; } -std::shared_ptr<CommonAPI::DBus::DBusConnection> DBusFactory::getDbusConnection() { - return dbusConnection_; +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; } -void DBusFactory::isServiceInstanceAliveAsync(Factory::IsServiceInstanceAliveCallback callback, - const std::string& serviceInstanceID, - const std::string& serviceName, - const std::string& serviceDomainName) { - std::string commonApiAddress = serviceDomainName + ":" + serviceName + ":" + serviceInstanceID; - isServiceInstanceAliveAsync(callback, commonApiAddress); +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; } +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; +} -std::shared_ptr<Proxy> DBusFactory::createProxy(const char* interfaceId, - const std::string& participantId, - const std::string& serviceName, - const std::string& domain) { - std::string commonApiAddress = domain + ":" + serviceName + ":" + participantId; - - std::string interfaceName; - std::string connectionName; - std::string objectPath; - - DBusAddressTranslator::getInstance().searchForDBusAddress(commonApiAddress, interfaceName, connectionName, objectPath); +/////////////////////////////////////////////////////////////////////////////// +// Connections +/////////////////////////////////////////////////////////////////////////////// +std::shared_ptr<DBusConnection> +Factory::getConnection(const ConnectionId_t &_connectionId) { - if(!registeredProxyFactoryFunctions_) { - registeredProxyFactoryFunctions_ = new std::unordered_map<std::string, DBusProxyFactoryFunction> {}; - } + auto itsConnectionIterator = connections_.find(_connectionId); + if (itsConnectionIterator != connections_.end()) { + return itsConnectionIterator->second; + } - for (auto it = registeredProxyFactoryFunctions_->begin(); it != registeredProxyFactoryFunctions_->end(); ++it) { - if(it->first == interfaceId) { - std::shared_ptr<DBusProxy> proxy = (it->second)(shared_from_this(), commonApiAddress, interfaceName, connectionName, objectPath, dbusConnection_); - proxy->init(); - return proxy; - } - } + // No connection found, lets create and initialize one + std::shared_ptr<DBusConnection> itsConnection + = std::make_shared<DBusConnection>(defaultBusType_); + connections_.insert({ _connectionId, itsConnection }); - return NULL; + itsConnection->connect(true); + return itsConnection; } -std::shared_ptr<DBusStubAdapter> DBusFactory::createDBusStubAdapter(const std::shared_ptr<StubBase>& stubBase, - const char* interfaceId, - const std::string& participantId, - const std::string& serviceName, - const std::string& domain) { - assert(dbusConnection_->isConnected()); - - std::string commonApiAddress = domain + ":" + serviceName + ":" + participantId; +std::shared_ptr<DBusConnection> +Factory::getConnection(std::shared_ptr<MainLoopContext> _context) { + if (!_context) + return getConnection(DEFAULT_CONNECTION_ID); - std::string interfaceName; - std::string connectionName; - std::string objectPath; + auto itsConnectionIterator = contextConnections_.find(_context.get()); + if (itsConnectionIterator != contextConnections_.end()) { + return itsConnectionIterator->second; + } - DBusAddressTranslator::getInstance().searchForDBusAddress(commonApiAddress, interfaceName, connectionName, objectPath); + // No connection found, lets create and initialize one + std::shared_ptr<DBusConnection> itsConnection + = std::make_shared<DBusConnection>(defaultBusType_); + contextConnections_.insert({ _context.get(), itsConnection } ); - if (!registeredAdapterFactoryFunctions_) { - registeredAdapterFactoryFunctions_ = new std::unordered_map<std::string, DBusAdapterFactoryFunction> {}; - } - - auto registeredAdapterFactoryFunctionsIter = registeredAdapterFactoryFunctions_->find(interfaceId); - const bool hasRegisteredAdapterFactoryFunctions = (registeredAdapterFactoryFunctionsIter != registeredAdapterFactoryFunctions_->end()); - std::shared_ptr<DBusStubAdapter> dbusStubAdapter; + itsConnection->connect(false); + if (_context) + itsConnection->attachMainLoopContext(_context); - if (hasRegisteredAdapterFactoryFunctions) { - const auto& dbusAdapterFactoryFunction = registeredAdapterFactoryFunctionsIter->second; + return itsConnection; +} - dbusStubAdapter = dbusAdapterFactoryFunction(shared_from_this(), commonApiAddress, interfaceName, connectionName, objectPath, dbusConnection_, stubBase); - dbusStubAdapter->init(dbusStubAdapter); +/////////////////////////////////////////////////////////////////////////////// +// Service registration +/////////////////////////////////////////////////////////////////////////////// +std::shared_ptr<DBusStubAdapter> +Factory::getRegisteredService(const std::string &_address) { + auto serviceIterator = services_.find(_address); + if (serviceIterator != services_.end()) { + return serviceIterator->second; } + return nullptr; +} - return dbusStubAdapter; +/////////////////////////////////////////////////////////////////////////////// +// Managed Services +/////////////////////////////////////////////////////////////////////////////// +std::shared_ptr<DBusStubAdapter> +Factory::createDBusStubAdapter( + const std::shared_ptr<StubBase> &_stub, + const std::string &_interface, + 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); + if (stubAdapter) + stubAdapter->init(stubAdapter); + } + return stubAdapter; } -bool DBusFactory::unregisterService(const std::string& participantId, const std::string& serviceName, const std::string& domain) { - std::string serviceAddress(domain + ":" + serviceName + ":" + participantId); - return DBusServicePublisher::getInstance()->unregisterService(serviceAddress); +bool +Factory::registerManagedService(const std::shared_ptr<DBusStubAdapter> &_stubAdapter) { + auto itsAddress = _stubAdapter->getAddress().getAddress(); + + 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; + } + + return false; } -COMMONAPI_DEPRECATED bool DBusFactory::registerAdapter(std::shared_ptr<StubBase> stubBase, - const char* interfaceId, - const std::string& participantId, - const std::string& serviceName, - const std::string& domain) { - std::shared_ptr<DBusServicePublisher> pub = std::dynamic_pointer_cast<DBusServicePublisher>(runtime_->getServicePublisher()); - return pub->registerService( - stubBase, - interfaceId, - participantId, - serviceName, - domain, - shared_from_this()); +bool +Factory::unregisterManagedService(const std::string &_address) { + return unregisterManagedService(services_.find(_address)); } +bool +Factory::unregisterManagedService(const ServicesMap::iterator &iterator) { + if (iterator == services_.end()) + return true; + + 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); + if (isUnregistered) { + connection->releaseServiceName(serviceName); + services_.erase(iterator); + } + // TODO: log error + return isUnregistered; +} } // namespace DBus } // namespace CommonAPI diff --git a/src/CommonAPI/DBus/DBusFactory.h b/src/CommonAPI/DBus/DBusFactory.h deleted file mode 100644 index 8b290fe..0000000 --- a/src/CommonAPI/DBus/DBusFactory.h +++ /dev/null @@ -1,93 +0,0 @@ -/* Copyright (C) 2013 BMW Group - * Author: Manfred Bathelt (manfred.bathelt@bmw.de) - * Author: Juergen Gehring (juergen.gehring@bmw.de) - * 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/. */ - -#if !defined (COMMONAPI_INTERNAL_COMPILATION) -#error "Only <CommonAPI/CommonAPI.h> can be included directly, this file may disappear or change contents." -#endif - -#ifndef COMMONAPI_DBUS_DBUS_FACTORY_H_ -#define COMMONAPI_DBUS_DBUS_FACTORY_H_ - -#include <thread> - -#include <CommonAPI/Factory.h> - -#include "DBusStubAdapter.h" -#include "DBusConnection.h" -#include "DBusProxy.h" - -namespace CommonAPI { -namespace DBus { - -class DBusMainLoopContext; -class DBusFactory; - -typedef std::shared_ptr<DBusProxy> (*DBusProxyFactoryFunction)(const std::shared_ptr<DBusFactory>& factory, - const std::string& commonApiAddress, - const std::string& interfaceName, - const std::string& busName, - const std::string& objectPath, - const std::shared_ptr<DBusProxyConnection>& dbusProxyConnection); - -typedef std::shared_ptr<DBusStubAdapter> (*DBusAdapterFactoryFunction) (const std::shared_ptr<DBusFactory>& factory, - const std::string& commonApiAddress, - const std::string& interfaceName, - const std::string& busName, - const std::string& objectPath, - const std::shared_ptr<DBusProxyConnection>& dbusProxyConnection, - const std::shared_ptr<StubBase>& stubBase); - -class DBusFactory: public Factory, public std::enable_shared_from_this<DBusFactory> { - public: - DBusFactory(std::shared_ptr<Runtime> runtime, const MiddlewareInfo* middlewareInfo, std::shared_ptr<MainLoopContext> mainLoopContext, const DBusFactoryConfig& dbusFactoryConfig = DBusFactoryConfig()); - - - virtual ~DBusFactory(); - - static void registerProxyFactoryMethod(std::string interfaceName, DBusProxyFactoryFunction proxyFactoryFunction); - static void registerAdapterFactoryMethod(std::string interfaceName, DBusAdapterFactoryFunction adapterFactoryMethod); - - virtual std::vector<std::string> getAvailableServiceInstances(const std::string& serviceInterfaceName, const std::string& serviceDomainName = "local"); - virtual bool isServiceInstanceAlive(const std::string& serviceAddress); - virtual bool isServiceInstanceAlive(const std::string& participantId, const std::string& serviceName, const std::string& domain = "local"); - - virtual void getAvailableServiceInstancesAsync(GetAvailableServiceInstancesCallback callback, const std::string& serviceName, const std::string& serviceDomainName = "local"); - virtual void isServiceInstanceAliveAsync(IsServiceInstanceAliveCallback callback, const std::string& serviceAddress); - virtual void isServiceInstanceAliveAsync(IsServiceInstanceAliveCallback callback, const std::string& serviceInstanceID, const std::string& serviceName, const std::string& serviceDomainName = "local"); - - virtual bool unregisterService(const std::string& participantId, const std::string& serviceName, const std::string& domain = "local"); - - std::shared_ptr<DBusStubAdapter> createDBusStubAdapter(const std::shared_ptr<StubBase>& stubBase, - const char* interfaceId, - const std::string& participantId, - const std::string& serviceName, - const std::string& domain); - - std::shared_ptr<CommonAPI::DBus::DBusConnection> getDbusConnection(); - - virtual std::shared_ptr<Proxy> createProxy(const char* interfaceId, const std::string& participantId, const std::string& serviceName, const std::string& domain); - - protected: - - COMMONAPI_DEPRECATED virtual bool registerAdapter(std::shared_ptr<StubBase> stubBase, - const char* interfaceId, - const std::string& participantId, - const std::string& serviceName, - const std::string& domain); - - private: - SubscriptionStatus isServiceInstanceAliveCallbackThunk(Factory::IsServiceInstanceAliveCallback callback, const AvailabilityStatus& status, std::shared_ptr<DBusServiceRegistry> serviceRegistry); - - std::shared_ptr<CommonAPI::DBus::DBusConnection> dbusConnection_; - std::shared_ptr<MainLoopContext> mainLoopContext_; - DBusFactoryConfig DBusFactoryConfig_; -}; - -} // namespace DBus -} // namespace CommonAPI - -#endif // COMMONAPI_DBUS_DBUS_FACTORY_H_ diff --git a/src/CommonAPI/DBus/DBusFreedesktopPropertiesStub.cpp b/src/CommonAPI/DBus/DBusFreedesktopPropertiesStub.cpp index 9823af5..7d9ce62 100644 --- a/src/CommonAPI/DBus/DBusFreedesktopPropertiesStub.cpp +++ b/src/CommonAPI/DBus/DBusFreedesktopPropertiesStub.cpp @@ -1,109 +1,105 @@ -/* Copyright (C) 2013 BMW Group - * Author: Manfred Bathelt (manfred.bathelt@bmw.de) - * Author: Juergen Gehring (juergen.gehring@bmw.de) - * 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 "DBusFreedesktopPropertiesStub.h" -#include "DBusStubAdapter.h" -#include "DBusServicePublisher.h" -#include "DBusOutputStream.h" -#include "DBusInputStream.h" +// 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/. #include <cassert> #include <vector> +#include <CommonAPI/DBus/DBusFreedesktopPropertiesStub.hpp> +#include <CommonAPI/DBus/DBusStubAdapter.hpp> +#include <CommonAPI/DBus/DBusOutputStream.hpp> +#include <CommonAPI/DBus/DBusInputStream.hpp> + namespace CommonAPI { namespace DBus { -DBusFreedesktopPropertiesStub::DBusFreedesktopPropertiesStub(const std::string& dbusObjectPath, - const std::string& dbusInterfaceName, - const std::shared_ptr<DBusProxyConnection>& dbusConnection, - const std::shared_ptr<DBusStubAdapter>& dbusStubAdapter) : - dbusObjectPath_(dbusObjectPath), - dbusConnection_(dbusConnection), - dbusStubAdapter_(dbusStubAdapter) { - assert(!dbusObjectPath.empty()); - assert(dbusObjectPath[0] == '/'); - assert(dbusConnection); +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) { + assert(!path_.empty()); + assert(path_[0] == '/'); + assert(_connection); dbusInterfacesLock_.lock(); - if(managedInterfaces_.find(dbusInterfaceName) == managedInterfaces_.end()) { - managedInterfaces_.insert({dbusInterfaceName, dbusStubAdapter}); + if(managedInterfaces_.find(_interface) == managedInterfaces_.end()) { + managedInterfaces_.insert({ _interface, _adapter }); } dbusInterfacesLock_.unlock(); - } DBusFreedesktopPropertiesStub::~DBusFreedesktopPropertiesStub() { - // TODO: maybee some deregistration etc. + // TODO: Check if there is some deregistration etc. necessary } const char* DBusFreedesktopPropertiesStub::getMethodsDBusIntrospectionXmlData() const { - return "<interface name=\"org.freedesktop.DBus.Properties\">\n" - "<method name=\"Get\">\n" - "<arg type=\"s\" name=\"interface_name\" direction=\"in\"/>\n" - "<arg type=\"s\" name=\"property_name\" direction=\"in\"/>\n" - "<arg type=\"v\" name=\"value\" direction=\"out\"/>\n" - "</method>\n" - "<method name=\"GetAll\">\n" - "<arg type=\"s\" name=\"interface_name\" direction=\"in\"/>\n" - "<arg type=\"a{sv}\" name=\"properties\" direction=\"out\"/>\n" - "</method>\n" - "<method name=\"Set\">\n" - "<arg type=\"s\" name=\"interface_name\" direction=\"in\"/>\n" - "<arg type=\"s\" name=\"property_name\" direction=\"in\"/>\n" - "<arg type=\"v\" name=\"value\" direction=\"in\"/>\n" - "</method>\n" - "<signal name=\"PropertiesChanged\">\n" - "<arg type=\"s\" name=\"interface_name\"/>\n" - "<arg type=\"a{sv}\" name=\"changed_properties\"/>\n" - "<arg type=\"as\" name=\"invalidated_properties\"/>\n" - "</signal>\n" - "</interface>\n"; + return "<method name=\"Get\">\n" + "<arg type=\"s\" name=\"interface_name\" direction=\"in\"/>\n" + "<arg type=\"s\" name=\"property_name\" direction=\"in\"/>\n" + "<arg type=\"v\" name=\"value\" direction=\"out\"/>\n" + "</method>\n" + "<method name=\"GetAll\">\n" + "<arg type=\"s\" name=\"interface_name\" direction=\"in\"/>\n" + "<arg type=\"a{sv}\" name=\"properties\" direction=\"out\"/>\n" + "</method>\n" + "<method name=\"Set\">\n" + "<arg type=\"s\" name=\"interface_name\" direction=\"in\"/>\n" + "<arg type=\"s\" name=\"property_name\" direction=\"in\"/>\n" + "<arg type=\"v\" name=\"value\" direction=\"in\"/>\n" + "</method>\n" + "<signal name=\"PropertiesChanged\">\n" + "<arg type=\"s\" name=\"interface_name\"/>\n" + "<arg type=\"a{sv}\" name=\"changed_properties\"/>\n" + "<arg type=\"as\" name=\"invalidated_properties\"/>\n" + "</signal>\n"; } -bool DBusFreedesktopPropertiesStub::onInterfaceDBusMessage(const DBusMessage& dbusMessage) { - auto dbusConnection = dbusConnection_.lock(); - - if (!dbusConnection || !dbusConnection->isConnected()) { +bool +DBusFreedesktopPropertiesStub::onInterfaceDBusMessage(const DBusMessage &_message) { + auto connection = connection_.lock(); + if (!connection || !connection->isConnected()) { return false; } - if (!dbusMessage.isMethodCallType() || !(dbusMessage.hasMemberName("Get") || dbusMessage.hasMemberName("GetAll") || dbusMessage.hasMemberName("Set"))) { + if (!_message.isMethodCallType() || + !(_message.hasMemberName("Get") || + _message.hasMemberName("GetAll") || + _message.hasMemberName("Set"))) { return false; } - DBusInputStream dbusInputStream(dbusMessage); - std::string interfaceName; - - dbusInputStream >> interfaceName; - - if(dbusInputStream.hasError()) { + std::string interface; + DBusInputStream input(_message); + input >> interface; + if(input.hasError()) { return false; } - std::lock_guard<std::mutex> dbusInterfacesLock(dbusInterfacesLock_); - - auto managedInterfacesIterator = managedInterfaces_.find(interfaceName); + std::lock_guard<std::mutex> itsLock(dbusInterfacesLock_); - if(managedInterfacesIterator == managedInterfaces_.end()) { + auto it = managedInterfaces_.find(interface); + if(it == managedInterfaces_.end()) { return false; } - return managedInterfacesIterator->second->onInterfaceDBusFreedesktopPropertiesMessage(dbusMessage); + return it->second->onInterfaceDBusFreedesktopPropertiesMessage(_message); } const bool DBusFreedesktopPropertiesStub::hasFreedesktopProperties() { return false; } -const std::string& DBusFreedesktopPropertiesStub::getDBusObjectPath() const { - return dbusObjectPath_; +const std::string &DBusFreedesktopPropertiesStub::getObjectPath() const { + return path_; } -const char* DBusFreedesktopPropertiesStub::getInterfaceName() { - return "org.freedesktop.DBus.Properties"; +const std::string &DBusFreedesktopPropertiesStub::getInterface() { + static std::string theInterface("org.freedesktop.DBus.Properties"); + return theInterface; } } // namespace DBus diff --git a/src/CommonAPI/DBus/DBusFreedesktopPropertiesStub.h b/src/CommonAPI/DBus/DBusFreedesktopPropertiesStub.h deleted file mode 100644 index c6b38a0..0000000 --- a/src/CommonAPI/DBus/DBusFreedesktopPropertiesStub.h +++ /dev/null @@ -1,60 +0,0 @@ -/* Copyright (C) 2013 BMW Group - * Author: Manfred Bathelt (manfred.bathelt@bmw.de) - * Author: Juergen Gehring (juergen.gehring@bmw.de) - * 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/. */ - -#if !defined (COMMONAPI_INTERNAL_COMPILATION) -#error "Only <CommonAPI/CommonAPI.h> can be included directly, this file may disappear or change contents." -#endif - -#ifndef COMMONAPI_DBUS_DBUS_FREEDESKTOP_PROPERTIES_STUB_H_ -#define COMMONAPI_DBUS_DBUS_FREEDESKTOP_PROPERTIES_STUB_H_ - -#include "DBusInterfaceHandler.h" - -#include <memory> -#include <mutex> -#include <string> - -namespace CommonAPI { -namespace DBus { - -class DBusStubAdapter; - -/** - * Stub for standard <a href="http://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces-properties">org.freedesktop.dbus.Properties</a> interface. - * - * DBusFreedesktopPropertiesStub gets the DBusStubAdapter for handling the actual properties with instantiation. - */ -class DBusFreedesktopPropertiesStub: public DBusInterfaceHandler { -public: - DBusFreedesktopPropertiesStub(const std::string& dbusObjectPath, - const std::string& dbusInterfaceName, - const std::shared_ptr<DBusProxyConnection>&, - const std::shared_ptr<DBusStubAdapter>& dbusStubAdapter); - - virtual ~DBusFreedesktopPropertiesStub(); - - const std::string& getDBusObjectPath() const; - static const char* getInterfaceName(); - - virtual const char* getMethodsDBusIntrospectionXmlData() const; - virtual bool onInterfaceDBusMessage(const DBusMessage& dbusMessage); - virtual const bool hasFreedesktopProperties(); -private: - std::string dbusObjectPath_; - std::weak_ptr<DBusProxyConnection> dbusConnection_; - std::shared_ptr<DBusStubAdapter> dbusStubAdapter_; - - typedef std::unordered_map<std::string, std::shared_ptr<DBusStubAdapter>> DBusInterfacesMap; - DBusInterfacesMap managedInterfaces_; - - std::mutex dbusInterfacesLock_; -}; - -} // namespace DBus -} // namespace CommonAPI - -#endif // COMMONAPI_DBUS_DBUS_FREEDESKTOP_PROPERTIES_STUB_H_ diff --git a/src/CommonAPI/DBus/DBusFunctionalHash.cpp b/src/CommonAPI/DBus/DBusFunctionalHash.cpp index a3a334a..7eeb67f 100644 --- a/src/CommonAPI/DBus/DBusFunctionalHash.cpp +++ b/src/CommonAPI/DBus/DBusFunctionalHash.cpp @@ -1,16 +1,15 @@ -/* Copyright (C) 2013 BMW Group - * Author: Manfred Bathelt (manfred.bathelt@bmw.de) - * Author: Juergen Gehring (juergen.gehring@bmw.de) - * 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 "DBusFunctionalHash.h" - -#include <murmurhash/MurmurHash3.h> +// 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/. #include <cassert> #include <cstring> +#include <murmurhash/MurmurHash3.h> + +#include <CommonAPI/DBus/DBusFunctionalHash.hpp> + /* * @see http://code.google.com/p/smhasher/ */ diff --git a/src/CommonAPI/DBus/DBusFunctionalHash.h b/src/CommonAPI/DBus/DBusFunctionalHash.h deleted file mode 100644 index 7ffec89..0000000 --- a/src/CommonAPI/DBus/DBusFunctionalHash.h +++ /dev/null @@ -1,80 +0,0 @@ -/* Copyright (C) 2013 BMW Group - * Author: Manfred Bathelt (manfred.bathelt@bmw.de) - * Author: Juergen Gehring (juergen.gehring@bmw.de) - * 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/. */ - -#if !defined (COMMONAPI_INTERNAL_COMPILATION) -#error "Only <CommonAPI/CommonAPI.h> can be included directly, this file may disappear or change contents." -#endif - -#ifndef COMMONAPI_DBUS_DBUS_FUNCTIONAL_HASH_H_ -#define COMMONAPI_DBUS_DBUS_FUNCTIONAL_HASH_H_ - -#include <functional> -#include <string> -#include <tuple> - -namespace std { - -template<> -struct hash<pair<const char*, const char*> > : - public unary_function<pair<const char*, const char*>, size_t> { - - size_t operator()(const pair<const char*, const char*>& t) const; -}; - -template<> -struct hash<const char*> : - public unary_function<const char*, size_t> { - - size_t operator()(const char* const t) const; -}; - -template<> -struct hash<pair<string, string> > : - public unary_function<pair<string, string>, size_t> { - - size_t operator()(const pair<string, string>& t) const; -}; - -template<> -struct hash<tuple<string, string, string> > : - public unary_function<tuple<string, string, string>, size_t> { - - size_t operator()(const tuple<string, string, string>& t) const; -}; - -template<> -struct hash<tuple<string, string, string, bool> > : - public unary_function<tuple<string, string, string, bool>, size_t> { - - size_t operator()(const tuple<string, string, string, bool>& t) const; -}; - -template<> -struct hash<tuple<string, string, string, int> > : - public unary_function<tuple<string, string, string, int>, size_t> { - - size_t operator()(const tuple<string, string, string, int>& t) const; -}; - -template<> -struct hash<tuple<string, string, string, string> > : - public std::unary_function<tuple<string, string, string, string>, size_t> { - - size_t operator()(const tuple<string, string, string, string>& t) const; -}; - -template<> -struct equal_to<pair<const char*, const char*> > : public binary_function<pair<const char*, const char*>, - pair<const char*, const char*>, - bool> { - - bool operator()(const pair<const char*, const char*>& a, const pair<const char*, const char*>& b) const; -}; - -} // namespace std - -#endif // COMMONAPI_DBUS_DBUS_FUNCTIONAL_HASH_H_ diff --git a/src/CommonAPI/DBus/DBusHelper.h b/src/CommonAPI/DBus/DBusHelper.h deleted file mode 100644 index bcf80d1..0000000 --- a/src/CommonAPI/DBus/DBusHelper.h +++ /dev/null @@ -1,42 +0,0 @@ -/* Copyright (C) 2013 BMW Group - * Author: Manfred Bathelt (manfred.bathelt@bmw.de) - * Author: Juergen Gehring (juergen.gehring@bmw.de) - * 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/. */ - -#if !defined (COMMONAPI_INTERNAL_COMPILATION) -#error "Only <CommonAPI/CommonAPI.h> can be included directly, this file may disappear or change contents." -#endif - -#ifndef COMMONAPI_DBUS_DBUS_HELPER_H_ -#define COMMONAPI_DBUS_DBUS_HELPER_H_ - -namespace CommonAPI { -namespace DBus { - -template <int ...> -struct index_sequence {}; - - -template <int N, int ...S> -struct make_sequence : make_sequence<N-1, N-1, S...> {}; - -template <int ...S> -struct make_sequence<0, S...> { - typedef index_sequence<S...> type; -}; - - -template <int N, int _Offset, int ...S> -struct make_sequence_range : make_sequence_range<N-1, _Offset, N-1+_Offset, S...> {}; - -template <int _Offset, int ...S> -struct make_sequence_range<0, _Offset, S...> { - typedef index_sequence<S...> type; -}; - -} // namespace DBus -} // namespace CommonAPI - -#endif // COMMONAPI_DBUS_DBUS_HELPER_H_ diff --git a/src/CommonAPI/DBus/DBusInputStream.cpp b/src/CommonAPI/DBus/DBusInputStream.cpp index c1ef4a3..07964d8 100644 --- a/src/CommonAPI/DBus/DBusInputStream.cpp +++ b/src/CommonAPI/DBus/DBusInputStream.cpp @@ -1,354 +1,141 @@ -/* Copyright (C) 2013 BMW Group - * Author: Manfred Bathelt (manfred.bathelt@bmw.de) - * Author: Juergen Gehring (juergen.gehring@bmw.de) - * 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 "DBusInputStream.h" +// 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/. + +#include <iomanip> + +#include <CommonAPI/DBus/DBusInputStream.hpp> namespace CommonAPI { namespace DBus { -DBusInputStream::DBusInputStream(const CommonAPI::DBus::DBusMessage& message) : - dataBegin_(message.getBodyData()), - currentDataPosition_(0), - dataLength_(message.getBodyLength()), - exception_(nullptr), - message_(message) { +DBusInputStream::DBusInputStream(const CommonAPI::DBus::DBusMessage &_message) + : begin_(_message.getBodyData()), + current_(0), + size_(_message.getBodyLength()), + exception_(nullptr), + message_(_message) { } DBusInputStream::~DBusInputStream() {} const CommonAPI::DBus::DBusError& DBusInputStream::getError() const { - return *exception_; + return (*exception_); } bool DBusInputStream::isErrorSet() const { - return exception_ != nullptr; + return (exception_ != nullptr); } void DBusInputStream::clearError() { exception_ = nullptr; } -void DBusInputStream::alignToBoundary(const size_t alignBoundary) { - const unsigned int alignMask = alignBoundary - 1; - currentDataPosition_ = (currentDataPosition_ + alignMask) & (~alignMask); -} - -char* DBusInputStream::readRawData(const size_t numBytesToRead) { - assert((currentDataPosition_ + numBytesToRead) <= dataLength_); - - char* dataPtr = (char*) (dataBegin_ + currentDataPosition_); - currentDataPosition_ += numBytesToRead; - return dataPtr; -} - -template<> -DBusInputStream& DBusInputStream::readBasicTypeValue<float>(float& val) { - if (sizeof(val) > 1) - alignToBoundary(sizeof(double)); - - val = (float) (*(reinterpret_cast<double*>(readRawData(sizeof(double))))); - return *this; -} - -InputStream& DBusInputStream::readValue(bool& boolValue) { - alignToBoundary(4); - readBasicTypeValue(boolValue); - alignToBoundary(4); - return *this; -} - -InputStream& DBusInputStream::readValue(int8_t& int8Value) { - return readBasicTypeValue(int8Value); -} -InputStream& DBusInputStream::readValue(int16_t& int16Value) { - return readBasicTypeValue(int16Value); -} -InputStream& DBusInputStream::readValue(int32_t& int32Value) { - return readBasicTypeValue(int32Value); -} -InputStream& DBusInputStream::readValue(int64_t& int64Value) { - return readBasicTypeValue(int64Value); -} - -InputStream& DBusInputStream::readValue(uint8_t& uint8Value) { - return readBasicTypeValue(uint8Value); -} -InputStream& DBusInputStream::readValue(uint16_t& uint16Value) { - return readBasicTypeValue(uint16Value); -} -InputStream& DBusInputStream::readValue(uint32_t& uint32Value) { - return readBasicTypeValue(uint32Value); -} -InputStream& DBusInputStream::readValue(uint64_t& uint64Value) { - return readBasicTypeValue(uint64Value); +void DBusInputStream::align(const size_t _boundary) { + const unsigned int mask = _boundary - 1; + current_ = (current_ + mask) & (~mask); } -InputStream& DBusInputStream::readValue(float& floatValue) { - return readBasicTypeValue(floatValue); -} -InputStream& DBusInputStream::readValue(double& doubleValue) { - return readBasicTypeValue(doubleValue); -} - -InputStream& DBusInputStream::readValue(std::string& stringValue) { - uint32_t lengthOfString; - readValue(lengthOfString); - - // length field does not include terminating 0-byte, therefore length of data to read is +1 - char* dataPtr = readRawData(lengthOfString + 1); - - // The string contained in a DBus-message is required to be 0-terminated, therefore the following line works - stringValue = dataPtr; - - return *this; -} - -InputStream& DBusInputStream::readValue(ByteBuffer& byteBufferValue) { - *this >> byteBufferValue; - return *this; -} - -InputStream& DBusInputStream::readEnumValue(int8_t& int8BackingTypeValue) { - return readValue(int8BackingTypeValue); -} -InputStream& DBusInputStream::readEnumValue(int16_t& int16BackingTypeValue) { - return readValue(int16BackingTypeValue); -} -InputStream& DBusInputStream::readEnumValue(int32_t& int32BackingTypeValue) { - return readValue(int32BackingTypeValue); -} -InputStream& DBusInputStream::readEnumValue(int64_t& int64BackingTypeValue) { - return readValue(int64BackingTypeValue); -} -InputStream& DBusInputStream::readEnumValue(uint8_t& uint8BackingTypeValue) { - return readValue(uint8BackingTypeValue); -} -InputStream& DBusInputStream::readEnumValue(uint16_t& uint16BackingTypeValue) { - return readValue(uint16BackingTypeValue); -} -InputStream& DBusInputStream::readEnumValue(uint32_t& uint32BackingTypeValue) { - return readValue(uint32BackingTypeValue); -} -InputStream& DBusInputStream::readEnumValue(uint64_t& uint64BackingTypeValue) { - return readValue(uint64BackingTypeValue); -} - -InputStream& DBusInputStream::readVersionValue(Version& versionValue) { - alignToBoundary(8); - readValue(versionValue.Major); - readValue(versionValue.Minor); - return *this; -} +char *DBusInputStream::_readRaw(const size_t _size) { + assert(current_ + _size <= size_); -void DBusInputStream::beginReadSerializableStruct(const SerializableStruct& serializableStruct) { - alignToBoundary(8); + char *data = (char *) (begin_ + current_); + current_ += _size; + return data; } -void DBusInputStream::endReadSerializableStruct(const SerializableStruct& serializableStruct) { -} - -void DBusInputStream::beginReadSerializablePolymorphicStruct(uint32_t& serialId) { - alignToBoundary(8); - readValue(serialId); - skipOverSignature(); - alignToBoundary(8); -} - -void DBusInputStream::endReadSerializablePolymorphicStruct(const uint32_t& serialId) { -} - -void DBusInputStream::readSerializableVariant(SerializableVariant& serializableVariant) { - alignToBoundary(8); - uint8_t containedTypeIndex; - readValue(containedTypeIndex); - skipOverSignature(); - - serializableVariant.readFromInputStream(containedTypeIndex, *this); -} - -void DBusInputStream::beginReadBoolVector() { - beginReadGenericVector(); - savedStreamPositions_.push(currentDataPosition_); -} - -void DBusInputStream::beginReadInt8Vector() { - beginReadGenericVector(); - savedStreamPositions_.push(currentDataPosition_); -} - -void DBusInputStream::beginReadInt16Vector() { - beginReadGenericVector(); - savedStreamPositions_.push(currentDataPosition_); -} - -void DBusInputStream::beginReadInt32Vector() { - beginReadGenericVector(); - savedStreamPositions_.push(currentDataPosition_); -} - -void DBusInputStream::beginReadInt64Vector() { - beginReadGenericVector(); - alignToBoundary(8); - savedStreamPositions_.push(currentDataPosition_); -} - -void DBusInputStream::beginReadUInt8Vector() { - beginReadGenericVector(); - savedStreamPositions_.push(currentDataPosition_); -} - -void DBusInputStream::beginReadUInt16Vector() { - beginReadGenericVector(); - savedStreamPositions_.push(currentDataPosition_); -} - -void DBusInputStream::beginReadUInt32Vector() { - beginReadGenericVector(); - savedStreamPositions_.push(currentDataPosition_); -} - -void DBusInputStream::beginReadUInt64Vector() { - beginReadGenericVector(); - alignToBoundary(8); - savedStreamPositions_.push(currentDataPosition_); -} - -void DBusInputStream::beginReadFloatVector() { - beginReadGenericVector(); - alignToBoundary(8); - savedStreamPositions_.push(currentDataPosition_); -} - -void DBusInputStream::beginReadDoubleVector() { - beginReadGenericVector(); - alignToBoundary(8); - savedStreamPositions_.push(currentDataPosition_); -} - -void DBusInputStream::beginReadStringVector() { - beginReadGenericVector(); - savedStreamPositions_.push(currentDataPosition_); -} - -void DBusInputStream::beginReadByteBufferVector() { - beginReadGenericVector(); - savedStreamPositions_.push(currentDataPosition_); -} - -void DBusInputStream::beginReadVersionVector() { - beginReadGenericVector(); - alignToBoundary(8); - savedStreamPositions_.push(currentDataPosition_); +void DBusInputStream::setError() { + exception_ = new CommonAPI::DBus::DBusError(); } -void DBusInputStream::beginReadInt8EnumVector() { - beginReadGenericVector(); - savedStreamPositions_.push(currentDataPosition_); +void DBusInputStream::pushPosition() { + positions_.push(current_); } -void DBusInputStream::beginReadInt16EnumVector() { - beginReadGenericVector(); - savedStreamPositions_.push(currentDataPosition_); +size_t DBusInputStream::popPosition() { + size_t itsPosition = positions_.top(); + positions_.pop(); + return itsPosition; } -void DBusInputStream::beginReadInt32EnumVector() { - beginReadGenericVector(); - savedStreamPositions_.push(currentDataPosition_); +void DBusInputStream::pushSize(size_t _size) { + sizes_.push(_size); } -void DBusInputStream::beginReadInt64EnumVector() { - beginReadGenericVector(); - alignToBoundary(8); - savedStreamPositions_.push(currentDataPosition_); +size_t DBusInputStream::popSize() { + size_t itsSize = sizes_.top(); + sizes_.pop(); + return itsSize; } -void DBusInputStream::beginReadUInt8EnumVector() { - beginReadGenericVector(); - savedStreamPositions_.push(currentDataPosition_); +InputStream<DBusInputStream> &DBusInputStream::readValue(bool &_value, const EmptyDeployment *_depl) { + uint32_t tmp; + readValue(tmp, _depl); + if (tmp > 1) + setError(); + _value = (tmp != 0); + return (*this); } -void DBusInputStream::beginReadUInt16EnumVector() { - beginReadGenericVector(); - savedStreamPositions_.push(currentDataPosition_); +InputStream<DBusInputStream> &DBusInputStream::readValue(int8_t &_value, const EmptyDeployment *_depl) { + return _readValue(_value); } -void DBusInputStream::beginReadUInt32EnumVector() { - beginReadGenericVector(); - savedStreamPositions_.push(currentDataPosition_); +InputStream<DBusInputStream> &DBusInputStream::readValue(int16_t &_value, const EmptyDeployment *_depl) { + return _readValue(_value); } -void DBusInputStream::beginReadUInt64EnumVector() { - beginReadGenericVector(); - alignToBoundary(8); - savedStreamPositions_.push(currentDataPosition_); +InputStream<DBusInputStream> &DBusInputStream::readValue(int32_t &_value, const EmptyDeployment *_depl) { + return _readValue(_value); } -void DBusInputStream::beginReadVectorOfSerializableStructs() { - beginReadGenericVector(); - alignToBoundary(8); - savedStreamPositions_.push(currentDataPosition_); +InputStream<DBusInputStream> &DBusInputStream::readValue(int64_t &_value, const EmptyDeployment *_depl) { + return _readValue(_value); } -void DBusInputStream::beginReadVectorOfSerializableVariants() { - beginReadGenericVector(); - alignToBoundary(8); - savedStreamPositions_.push(currentDataPosition_); +InputStream<DBusInputStream> &DBusInputStream::readValue(uint8_t &_value, const EmptyDeployment *_depl) { + return _readValue(_value); } -void DBusInputStream::beginReadVectorOfVectors() { - beginReadGenericVector(); - savedStreamPositions_.push(currentDataPosition_); +InputStream<DBusInputStream> &DBusInputStream::readValue(uint16_t &_value, const EmptyDeployment *_depl) { + return _readValue(_value); } -void DBusInputStream::beginReadVectorOfMaps() { - beginReadGenericVector(); - alignToBoundary(4); - savedStreamPositions_.push(currentDataPosition_); +InputStream<DBusInputStream> &DBusInputStream::readValue(uint32_t &_value, const EmptyDeployment *_depl) { + return _readValue(_value); } -void DBusInputStream::beginReadVectorOfSerializablePolymorphicStructs() { - beginReadGenericVector(); - alignToBoundary(8); - savedStreamPositions_.push(currentDataPosition_); +InputStream<DBusInputStream> &DBusInputStream::readValue(uint64_t &_value, const EmptyDeployment *_depl) { + return _readValue(_value); } -bool DBusInputStream::hasMoreVectorElements() { - return bytesToRead_.top() > currentDataPosition_ - savedStreamPositions_.top(); +InputStream<DBusInputStream> &DBusInputStream::readValue(float &_value, const EmptyDeployment *_depl) { + return _readValue(_value); } -void DBusInputStream::endReadVector() { - bytesToRead_.pop(); - savedStreamPositions_.pop(); +InputStream<DBusInputStream> &DBusInputStream::readValue(double &_value, const EmptyDeployment *_depl) { + return _readValue(_value); } -void DBusInputStream::beginReadMap() { - uint32_t vectorByteSize; - readBasicTypeValue(vectorByteSize); - bytesToRead_.push(vectorByteSize); - alignToBoundary(8); - savedStreamPositions_.push(currentDataPosition_); -} +InputStream<DBusInputStream> &DBusInputStream::readValue(std::string &_value, const EmptyDeployment *_depl) { + uint32_t length; + _readValue(length); -bool DBusInputStream::hasMoreMapElements() { - return bytesToRead_.top() > currentDataPosition_ - savedStreamPositions_.top(); -} + // length field does not include terminating 0-byte, therefore length of data to read is +1 + char *data = _readRaw(length + 1); -void DBusInputStream::endReadMap() { - bytesToRead_.pop(); - savedStreamPositions_.pop(); -} + // The string contained in a DBus-message is required to be 0-terminated, therefore the following line works + _value = data; -void DBusInputStream::beginReadMapElement() { - alignToBoundary(8); -} -void DBusInputStream::endReadMapElement() { + return (*this); } -void DBusInputStream::setError() { - exception_ = new CommonAPI::DBus::DBusError(); +InputStream<DBusInputStream> &DBusInputStream::readValue(Version &_value, const EmptyDeployment *_depl) { + align(8); + _readValue(_value.Major); + _readValue(_value.Minor); + return *this; } } // namespace DBus diff --git a/src/CommonAPI/DBus/DBusInputStream.h b/src/CommonAPI/DBus/DBusInputStream.h deleted file mode 100644 index b91583c..0000000 --- a/src/CommonAPI/DBus/DBusInputStream.h +++ /dev/null @@ -1,233 +0,0 @@ -/* Copyright (C) 2013 BMW Group - * Author: Manfred Bathelt (manfred.bathelt@bmw.de) - * Author: Juergen Gehring (juergen.gehring@bmw.de) - * 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/. */ - -#if !defined (COMMONAPI_INTERNAL_COMPILATION) -#error "Only <CommonAPI/CommonAPI.h> can be included directly, this file may disappear or change contents." -#endif - -#ifndef COMMONAPI_DBUS_DBUS_INPUT_STREAM_H_ -#define COMMONAPI_DBUS_DBUS_INPUT_STREAM_H_ - -#include "DBusError.h" -#include "DBusMessage.h" - -#include <CommonAPI/InputStream.h> - -#include <stdint.h> -#include <cassert> -#include <string> -#include <vector> -#include <stack> - -namespace CommonAPI { -namespace DBus { - -/** - * Used to mark the position of a pointer within an array of bytes. - */ -typedef uint32_t position_t; - -/** - * @class DBusInputMessageStream - * - * Used to deserialize and read data from a #DBusMessage. For all data types that can be read from a #DBusMessage, a ">>"-operator should be defined to handle the reading - * (this operator is predefined for all basic data types and for vectors). - */ -class DBusInputStream: public InputStream { -public: - virtual bool hasError() const { - return isErrorSet(); - } - - virtual InputStream& readValue(bool& boolValue); - - virtual InputStream& readValue(int8_t& int8Value); - virtual InputStream& readValue(int16_t& int16Value); - virtual InputStream& readValue(int32_t& int32Value); - virtual InputStream& readValue(int64_t& int64Value); - - virtual InputStream& readValue(uint8_t& uint8Value); - virtual InputStream& readValue(uint16_t& uint16Value); - virtual InputStream& readValue(uint32_t& uint32Value); - virtual InputStream& readValue(uint64_t& uint64Value); - - virtual InputStream& readValue(float& floatValue); - virtual InputStream& readValue(double& doubleValue); - - virtual InputStream& readValue(std::string& stringValue); - virtual InputStream& readValue(ByteBuffer& byteBufferValue); - - virtual InputStream& readEnumValue(int8_t& int8BackingTypeValue); - virtual InputStream& readEnumValue(int16_t& int16BackingTypeValue); - virtual InputStream& readEnumValue(int32_t& int32BackingTypeValue); - virtual InputStream& readEnumValue(int64_t& int64BackingTypeValue); - virtual InputStream& readEnumValue(uint8_t& uint8BackingTypeValue); - virtual InputStream& readEnumValue(uint16_t& uint16BackingTypeValue); - virtual InputStream& readEnumValue(uint32_t& uint32BackingTypeValue); - virtual InputStream& readEnumValue(uint64_t& uint64BackingTypeValue); - - virtual InputStream& readVersionValue(Version& versionValue); - - virtual void beginReadSerializableStruct(const SerializableStruct& serializableStruct); - virtual void endReadSerializableStruct(const SerializableStruct& serializableStruct); - - virtual void beginReadSerializablePolymorphicStruct(uint32_t& serialId); - virtual void endReadSerializablePolymorphicStruct(const uint32_t& serialId); - - virtual void readSerializableVariant(SerializableVariant& serializableVariant); - - virtual void beginReadBoolVector(); - virtual void beginReadInt8Vector(); - virtual void beginReadInt16Vector(); - virtual void beginReadInt32Vector(); - virtual void beginReadInt64Vector(); - virtual void beginReadUInt8Vector(); - virtual void beginReadUInt16Vector(); - virtual void beginReadUInt32Vector(); - virtual void beginReadUInt64Vector(); - virtual void beginReadFloatVector(); - virtual void beginReadDoubleVector(); - virtual void beginReadStringVector(); - virtual void beginReadByteBufferVector(); - virtual void beginReadVersionVector(); - - virtual void beginReadInt8EnumVector(); - virtual void beginReadInt16EnumVector(); - virtual void beginReadInt32EnumVector(); - virtual void beginReadInt64EnumVector(); - virtual void beginReadUInt8EnumVector(); - virtual void beginReadUInt16EnumVector(); - virtual void beginReadUInt32EnumVector(); - virtual void beginReadUInt64EnumVector(); - - virtual void beginReadVectorOfSerializableStructs(); - virtual void beginReadVectorOfSerializableVariants(); - virtual void beginReadVectorOfVectors(); - virtual void beginReadVectorOfMaps(); - - virtual void beginReadVectorOfSerializablePolymorphicStructs(); - - virtual bool hasMoreVectorElements(); - virtual void endReadVector(); - - virtual void beginReadMap(); - virtual bool hasMoreMapElements(); - virtual void endReadMap(); - virtual void beginReadMapElement(); - virtual void endReadMapElement(); - - /** - * Creates a #DBusInputMessageStream which can be used to deserialize and read data from the given #DBusMessage. - * As no message-signature is checked, the user is responsible to ensure that the correct data types are read in the correct order. - * - * @param message the #DBusMessage from which data should be read. - */ - DBusInputStream(const CommonAPI::DBus::DBusMessage& message); - DBusInputStream(const DBusInputStream& imessagestream) = delete; - - /** - * Destructor; does not call the destructor of the referred #DBusMessage. Make sure to maintain a reference to the - * #DBusMessage outside of the stream if you intend to make further use of the message. - */ - ~DBusInputStream(); - - /** - * Marks the stream as erroneous. - */ - void setError(); - - /** - * @return An instance of #DBusError if this stream is in an erroneous state, NULL otherwise - */ - const CommonAPI::DBus::DBusError& getError() const; - - /** - * @return true if this stream is in an erroneous state, false otherwise. - */ - bool isErrorSet() const; - - /** - * Marks the state of the stream as cleared from all errors. Further reading is possible afterwards. - * The stream will have maintained the last valid position from before its state became erroneous. - */ - void clearError(); - - /** - * Aligns the stream to the given byte boundary, i.e. the stream skips as many bytes as are necessary to execute the next read - * starting from the given boundary. - * - * @param alignBoundary the byte boundary to which the stream needs to be aligned. - */ - void alignToBoundary(const size_t alignBoundary); - - /** - * Reads the given number of bytes and returns them as an array of characters. - * - * Actually, for performance reasons this command only returns a pointer to the current position in the stream, - * and then increases the position of this pointer by the number of bytes indicated by the given parameter. - * It is the user's responsibility to actually use only the number of bytes he indicated he would use. - * It is assumed the user knows what kind of value is stored next in the #DBusMessage the data is streamed from. - * Using a reinterpret_cast on the returned pointer should then restore the original value. - * - * Example use case: - * @code - * ... - * inputMessageStream.alignForBasicType(sizeof(int32_t)); - * char* const dataPtr = inputMessageStream.read(sizeof(int32_t)); - * int32_t val = *(reinterpret_cast<int32_t*>(dataPtr)); - * ... - * @endcode - */ - char* readRawData(const size_t numBytesToRead); - - /** - * Handles all reading of basic types from a given #DBusInputMessageStream. - * Basic types in this context are: uint8_t, uint16_t, uint32_t, uint64_t, int8_t, int16_t, int32_t, int64_t, float, double. - * Any types not listed here (especially all complex types, e.g. structs, unions etc.) need to provide a - * specialized implementation of this operator. - * - * @tparam _BasicType The type of the value that is to be read from the given stream. - * @param val The variable in which the retrieved value is to be stored - * @param inputMessageStream The stream which the value is to be read from - * @return The given inputMessageStream to allow for successive reading - */ - template<typename _BasicType> - DBusInputStream& readBasicTypeValue(_BasicType& val) { - if (sizeof(val) > 1) - alignToBoundary(sizeof(_BasicType)); - - val = *(reinterpret_cast<_BasicType*>(readRawData(sizeof(_BasicType)))); - return *this; - } - -private: - inline void beginReadGenericVector() { - uint32_t vectorByteSize; - readBasicTypeValue(vectorByteSize); - bytesToRead_.push(vectorByteSize); - } - - inline void skipOverSignature() { - uint8_t signatureLength; - readValue(signatureLength); - readRawData(signatureLength + 1); - } - - char* dataBegin_; - position_t currentDataPosition_; - size_t dataLength_; - CommonAPI::DBus::DBusError* exception_; - CommonAPI::DBus::DBusMessage message_; - - std::stack<uint32_t> bytesToRead_; - std::stack<position_t> savedStreamPositions_; -}; - -} // namespace DBus -} // namespace CommonAPI - -#endif // COMMONAPI_DBUS_DBUS_INPUT_STREAM_H_ diff --git a/src/CommonAPI/DBus/DBusInstanceAvailabilityStatusChangedEvent.h b/src/CommonAPI/DBus/DBusInstanceAvailabilityStatusChangedEvent.h deleted file mode 100644 index f9e5a1e..0000000 --- a/src/CommonAPI/DBus/DBusInstanceAvailabilityStatusChangedEvent.h +++ /dev/null @@ -1,140 +0,0 @@ -/* Copyright (C) 2013 BMW Group - * Author: Manfred Bathelt (manfred.bathelt@bmw.de) - * Author: Juergen Gehring (juergen.gehring@bmw.de) - * 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/. */ - -#if !defined (COMMONAPI_INTERNAL_COMPILATION) -#error "Only <CommonAPI/CommonAPI.h> can be included directly, this file may disappear or change contents." -#endif - -#ifndef COMMONAPI_DBUS_DBUS_INSTANCE_AVAILABILITY_STATUS_CHANGED_EVENT_H_ -#define COMMONAPI_DBUS_DBUS_INSTANCE_AVAILABILITY_STATUS_CHANGED_EVENT_H_ - -#include <CommonAPI/ProxyManager.h> - -#include "DBusProxy.h" -#include "DBusObjectManagerStub.h" -#include "DBusInstanceAvailabilityStatusChangedEvent.h" - -#include <functional> -#include <future> -#include <string> -#include <vector> - - -namespace CommonAPI { -namespace DBus { - -// TODO move logic to DBusServiceRegistry, now every proxy will deserialize the messages! -class DBusInstanceAvailabilityStatusChangedEvent: - public ProxyManager::InstanceAvailabilityStatusChangedEvent, - public DBusProxyConnection::DBusSignalHandler { - public: - DBusInstanceAvailabilityStatusChangedEvent(DBusProxy& dbusProxy, const std::string& interfaceName) : - dbusProxy_(dbusProxy), - observedInterfaceName_(interfaceName) { - } - - virtual SubscriptionStatus onSignalDBusMessage(const DBusMessage& dbusMessage) { - if (dbusMessage.hasMemberName("InterfacesAdded")) { - onInterfacesAddedSignal(dbusMessage); - } else if (dbusMessage.hasMemberName("InterfacesRemoved")) { - onInterfacesRemovedSignal(dbusMessage); - } - - return CommonAPI::SubscriptionStatus::RETAIN; - } - - virtual ~DBusInstanceAvailabilityStatusChangedEvent() { - dbusProxy_.removeSignalMemberHandler(interfacesAddedSubscription_); - dbusProxy_.removeSignalMemberHandler(interfacesRemovedSubscription_); - } - - protected: - virtual void onFirstListenerAdded(const CancellableListener&) { - interfacesAddedSubscription_ = dbusProxy_.addSignalMemberHandler( - dbusProxy_.getDBusObjectPath(), - DBusObjectManagerStub::getInterfaceName(), - "InterfacesAdded", - "oa{sa{sv}}", - this); - - interfacesRemovedSubscription_ = dbusProxy_.addSignalMemberHandler( - dbusProxy_.getDBusObjectPath(), - DBusObjectManagerStub::getInterfaceName(), - "InterfacesRemoved", - "oas", - this); - } - - virtual void onLastListenerRemoved(const CancellableListener&) { - dbusProxy_.removeSignalMemberHandler(interfacesAddedSubscription_); - dbusProxy_.removeSignalMemberHandler(interfacesRemovedSubscription_); - } - - private: - inline void onInterfacesAddedSignal(const DBusMessage& dbusMessage) { - DBusInputStream dbusInputStream(dbusMessage); - std::string dbusObjectPath; - DBusObjectManagerStub::DBusInterfacesAndPropertiesDict dbusInterfacesAndPropertiesDict; - - dbusInputStream >> dbusObjectPath; - assert(!dbusInputStream.hasError()); - - dbusInputStream >> dbusInterfacesAndPropertiesDict; - assert(!dbusInputStream.hasError()); - - for (const auto& dbusInterfaceIterator : dbusInterfacesAndPropertiesDict) { - const std::string& dbusInterfaceName = dbusInterfaceIterator.first; - - if(dbusInterfaceName == observedInterfaceName_) { - notifyInterfaceStatusChanged(dbusObjectPath, dbusInterfaceName, AvailabilityStatus::AVAILABLE); - } - } - } - - inline void onInterfacesRemovedSignal(const DBusMessage& dbusMessage) { - DBusInputStream dbusInputStream(dbusMessage); - std::string dbusObjectPath; - std::vector<std::string> dbusInterfaceNames; - - dbusInputStream >> dbusObjectPath; - assert(!dbusInputStream.hasError()); - - dbusInputStream >> dbusInterfaceNames; - assert(!dbusInputStream.hasError()); - - for (const auto& dbusInterfaceName : dbusInterfaceNames) { - if(dbusInterfaceName == observedInterfaceName_) { - notifyInterfaceStatusChanged(dbusObjectPath, dbusInterfaceName, AvailabilityStatus::NOT_AVAILABLE); - } - } - } - - void notifyInterfaceStatusChanged(const std::string& dbusObjectPath, - const std::string& dbusInterfaceName, - const AvailabilityStatus& availabilityStatus) { - std::string commonApiAddress; - - DBusAddressTranslator::getInstance().searchForCommonAddress( - dbusInterfaceName, - dbusProxy_.getDBusBusName(), - dbusObjectPath, - commonApiAddress); - - notifyListeners(commonApiAddress, availabilityStatus); - } - - - DBusProxy& dbusProxy_; - std::string observedInterfaceName_; - DBusProxyConnection::DBusSignalHandlerToken interfacesAddedSubscription_; - DBusProxyConnection::DBusSignalHandlerToken interfacesRemovedSubscription_; -}; - -} // namespace DBus -} // namespace CommonAPI - -#endif // COMMONAPI_DBUS_DBUS_INSTANCE_AVAILABILITY_STATUS_CHANGED_EVENT_H_ diff --git a/src/CommonAPI/DBus/DBusInterfaceHandler.h b/src/CommonAPI/DBus/DBusInterfaceHandler.h deleted file mode 100644 index 1ee2cb1..0000000 --- a/src/CommonAPI/DBus/DBusInterfaceHandler.h +++ /dev/null @@ -1,32 +0,0 @@ -/* Copyright (C) 2013 BMW Group - * Author: Manfred Bathelt (manfred.bathelt@bmw.de) - * Author: Juergen Gehring (juergen.gehring@bmw.de) - * 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/. */ -#ifndef COMMONAPI_DBUS_INTERFACE_HANDLER_H_ -#define COMMONAPI_DBUS_INTERFACE_HANDLER_H_ - -#include "DBusProxyConnection.h" -#include "DBusMessage.h" - -#include <memory> - -namespace CommonAPI { -namespace DBus { - -class DBusInterfaceHandler { - public: - virtual ~DBusInterfaceHandler() { } - - virtual const char* getMethodsDBusIntrospectionXmlData() const = 0; - - virtual bool onInterfaceDBusMessage(const DBusMessage& dbusMessage) = 0; - - virtual const bool hasFreedesktopProperties() = 0; -}; - -} // namespace dbus -} // namespace CommonAPI - -#endif // COMMONAPI_DBUS_INTERFACE_HANDLER_H_ diff --git a/src/CommonAPI/DBus/DBusLegacyVariant.h b/src/CommonAPI/DBus/DBusLegacyVariant.h deleted file mode 100644 index ec3b5c9..0000000 --- a/src/CommonAPI/DBus/DBusLegacyVariant.h +++ /dev/null @@ -1,138 +0,0 @@ -/* Copyright (C) 2013 BMW Group - * Author: Manfred Bathelt (manfred.bathelt@bmw.de) - * Author: Juergen Gehring (juergen.gehring@bmw.de) - * 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/. */ - -#if !defined (COMMONAPI_INTERNAL_COMPILATION) -#error "Only <CommonAPI/CommonAPI.h> can be included directly, this file may disappear or change contents." -#endif - -#ifndef DBUSLEGACYVARIANT_H_ -#define DBUSLEGACYVARIANT_H_ - -#include <CommonAPI/SerializableVariant.h> -#include "DBusOutputStream.h" -#include "DBusInputStream.h" - -namespace CommonAPI { -namespace DBus { - -template<class Visitor, class Variant, typename ... _Types> -struct ApplyIndexForStringVisitor -; - -template<class Visitor, class Variant> -struct ApplyIndexForStringVisitor<Visitor, Variant> { - static const uint8_t index = 0; - - static uint8_t visit(Visitor&, const Variant&) { - //won't be called - assert(false); - return 0; - } -}; - -template<class Visitor, class Variant, typename _Type, typename ... _Types> -struct ApplyIndexForStringVisitor<Visitor, Variant, _Type, _Types...> { - static const uint8_t index = ApplyIndexForStringVisitor<Visitor, Variant, - _Types...>::index + 1; - - static uint8_t visit(Visitor& visitor, const Variant& var) { - DBusTypeOutputStream typeStream_; - TypeWriter<_Type>::writeType(typeStream_); - const std::string sig = typeStream_.retrieveSignature(); -#ifdef WIN32 - if (visitor.operator()<_Type>(sig)) { -#else - if (visitor.template operator()<_Type>(sig)) { -#endif - return index; - } else { - return ApplyIndexForStringVisitor<Visitor, Variant, _Types...>::visit(visitor, - var); - } - } -}; - -template<typename ... _Types> -struct TypeOutputStreamCompareVisitor { -public: - TypeOutputStreamCompareVisitor(const std::string& type) : - type_(type) { - } - - template<typename _Type> - bool operator()(const std::string& ntype) const { - int comp = type_.compare(0, type_.size(), ntype); - if (comp == 0) { - return true; - } else { - return false; - } - } -private: - const std::string type_; - -}; - -template< class > -class DBusLegacyVariantWrapper; - -template < - template <class...> class _Type, class... _Types> -class DBusLegacyVariantWrapper<_Type<_Types...>> { -public: - - DBusLegacyVariantWrapper() : - contained_() { - } - - DBusLegacyVariantWrapper(CommonAPI::Variant<_Types...>& cont) : - contained_(cont) { - } - - - uint8_t getIndexForType(const std::string& type) const { - TypeOutputStreamCompareVisitor<_Types...> visitor(type); - return ApplyIndexForStringVisitor<TypeOutputStreamCompareVisitor<_Types...>, Variant<_Types...>, _Types...>::visit( - visitor, contained_); - } - - CommonAPI::Variant<_Types...> contained_; -}; - -} /* namespace DBus */ - -//template <template <class...> class _Type, class... _Types> -template <typename ... _Types> -inline OutputStream& operator<<(OutputStream& outputStream, const DBus::DBusLegacyVariantWrapper<Variant<_Types...> >& serializableVariant) { - DBus::DBusTypeOutputStream typeOutputStream; - serializableVariant.contained_.writeToTypeOutputStream(typeOutputStream); - std::string sigStr = typeOutputStream.retrieveSignature(); - uint8_t length = (uint8_t) sigStr.length(); - assert(length < 256); - outputStream << length; - outputStream.writeRawData(sigStr.c_str(), length + 1); - serializableVariant.contained_.writeToOutputStream(outputStream); - return outputStream; -} - -//template <template <class...> class _Type, class... _Types> -template <typename ... _Types> -inline InputStream& operator>>(InputStream& inputStream, DBus::DBusLegacyVariantWrapper<Variant<_Types...> >& serializableVariant) { - uint8_t signatureLength; - inputStream.readValue(signatureLength); - assert(signatureLength < 256); - char * buf = inputStream.readRawData(signatureLength + 1); - std::string sigString; - sigString.assign(buf, buf + signatureLength); - uint8_t containedTypeIndex = serializableVariant.getIndexForType(sigString); - serializableVariant.contained_.readFromInputStream(containedTypeIndex, inputStream); - return inputStream; -} - -} /* namespace CommonAPI */ - -#endif /* DBUSLEGACYVARIANT_H_ */ diff --git a/src/CommonAPI/DBus/DBusMainLoopContext.cpp b/src/CommonAPI/DBus/DBusMainLoopContext.cpp index c093a67..dea1ff9 100644 --- a/src/CommonAPI/DBus/DBusMainLoopContext.cpp +++ b/src/CommonAPI/DBus/DBusMainLoopContext.cpp @@ -1,26 +1,22 @@ -/* Copyright (C) 2013 BMW Group - * Author: Manfred Bathelt (manfred.bathelt@bmw.de) - * Author: Juergen Gehring (juergen.gehring@bmw.de) - * 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 "DBusMainLoopContext.h" -#include "DBusConnection.h" +// 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> #else #include <poll.h> #endif + #include <chrono> +#include <CommonAPI/DBus/DBusMainLoopContext.hpp> +#include <CommonAPI/DBus/DBusConnection.hpp> namespace CommonAPI { namespace DBus { - DBusDispatchSource::DBusDispatchSource(DBusConnection* dbusConnection): dbusConnection_(dbusConnection) { } @@ -48,14 +44,18 @@ DBusWatch::DBusWatch(::DBusWatch* libdbusWatch, std::weak_ptr<MainLoopContext>& } bool DBusWatch::isReadyToBeWatched() { - return dbus_watch_get_enabled(libdbusWatch_); + return 0 != dbus_watch_get_enabled(libdbusWatch_); } void DBusWatch::startWatching() { if(!dbus_watch_get_enabled(libdbusWatch_)) stopWatching(); unsigned int channelFlags_ = dbus_watch_get_flags(libdbusWatch_); - short int pollFlags = POLLERR | POLLHUP; +#ifdef WIN32 + short int pollFlags = 0; +#else + short int pollFlags = POLLERR | POLLHUP; +#endif if(channelFlags_ & DBUS_WATCH_READABLE) { pollFlags |= POLLIN; } @@ -63,7 +63,12 @@ void DBusWatch::startWatching() { pollFlags |= POLLOUT; } - pollFileDescriptor_.fd = dbus_watch_get_unix_fd(libdbusWatch_); +#ifdef WIN32 + pollFileDescriptor_.fd = dbus_watch_get_socket(libdbusWatch_); +#else + pollFileDescriptor_.fd = dbus_watch_get_unix_fd(libdbusWatch_); +#endif + pollFileDescriptor_.events = pollFlags; pollFileDescriptor_.revents = 0; @@ -74,8 +79,9 @@ void DBusWatch::startWatching() { void DBusWatch::stopWatching() { auto lockedContext = mainLoopContext_.lock(); - assert(lockedContext); - lockedContext->deregisterWatch(this); + if (lockedContext) { + lockedContext->deregisterWatch(this); + } } const pollfd& DBusWatch::getAssociatedFileDescriptor() { @@ -83,7 +89,13 @@ const pollfd& DBusWatch::getAssociatedFileDescriptor() { } void DBusWatch::dispatch(unsigned int eventFlags) { - dbus_watch_handle(libdbusWatch_, eventFlags); + // Pollflags do not correspond directly to DBus watch flags + unsigned int dbusWatchFlags = (eventFlags & POLLIN) | + ((eventFlags & POLLOUT) >> 1) | + ((eventFlags & POLLERR) >> 1) | + ((eventFlags & POLLHUP) >> 1); + + dbus_watch_handle(libdbusWatch_, dbusWatchFlags); } const std::vector<DispatchSource*>& DBusWatch::getDependentDispatchSources() { @@ -102,7 +114,7 @@ DBusTimeout::DBusTimeout(::DBusTimeout* libdbusTimeout, std::weak_ptr<MainLoopCo } bool DBusTimeout::isReadyToBeMonitored() { - return dbus_timeout_get_enabled(libdbusTimeout_); + return 0 != dbus_timeout_get_enabled(libdbusTimeout_); } void DBusTimeout::startMonitoring() { @@ -115,8 +127,9 @@ void DBusTimeout::startMonitoring() { void DBusTimeout::stopMonitoring() { dueTimeInMs_ = TIMEOUT_INFINITE; auto lockedContext = mainLoopContext_.lock(); - assert(lockedContext); - lockedContext->deregisterTimeoutSource(this); + if (lockedContext) { + lockedContext->deregisterTimeoutSource(this); + } } bool DBusTimeout::dispatch() { @@ -142,6 +155,5 @@ void DBusTimeout::recalculateDueTime() { } } - } // namespace DBus } // namespace CommonAPI diff --git a/src/CommonAPI/DBus/DBusMainLoopContext.h b/src/CommonAPI/DBus/DBusMainLoopContext.h deleted file mode 100644 index 439d530..0000000 --- a/src/CommonAPI/DBus/DBusMainLoopContext.h +++ /dev/null @@ -1,92 +0,0 @@ -/* Copyright (C) 2013 BMW Group - * Author: Manfred Bathelt (manfred.bathelt@bmw.de) - * Author: Juergen Gehring (juergen.gehring@bmw.de) - * 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/. */ - -#if !defined (COMMONAPI_INTERNAL_COMPILATION) -#error "Only <CommonAPI/CommonAPI.h> can be included directly, this file may disappear or change contents." -#endif - -#ifndef DBUS_MAINLOOPCONTEXT_H_ -#define DBUS_MAINLOOPCONTEXT_H_ - -#include <list> -#include <memory> -#include <CommonAPI/MainLoopContext.h> - -#include <dbus/dbus.h> - - - -namespace CommonAPI { -namespace DBus { - -class DBusConnection; - - - -class DBusDispatchSource: public DispatchSource { - public: - DBusDispatchSource(DBusConnection* dbusConnection); - ~DBusDispatchSource(); - - bool prepare(int64_t& timeout); - bool check(); - bool dispatch(); - - private: - DBusConnection* dbusConnection_; -}; - -class DBusWatch: public Watch { - public: - DBusWatch(::DBusWatch* libdbusWatch, std::weak_ptr<MainLoopContext>& mainLoopContext); - - bool isReadyToBeWatched(); - void startWatching(); - void stopWatching(); - - void dispatch(unsigned int eventFlags); - - const pollfd& getAssociatedFileDescriptor(); - - const std::vector<DispatchSource*>& getDependentDispatchSources(); - void addDependentDispatchSource(DispatchSource* dispatchSource); - private: - bool isReady(); - - ::DBusWatch* libdbusWatch_; - pollfd pollFileDescriptor_; - std::vector<DispatchSource*> dependentDispatchSources_; - - std::weak_ptr<MainLoopContext> mainLoopContext_; -}; - - -class DBusTimeout: public Timeout { - public: - DBusTimeout(::DBusTimeout* libdbusTimeout, std::weak_ptr<MainLoopContext>& mainLoopContext); - - bool isReadyToBeMonitored(); - void startMonitoring(); - void stopMonitoring(); - - bool dispatch(); - - int64_t getTimeoutInterval() const; - int64_t getReadyTime() const; - private: - void recalculateDueTime(); - - int64_t dueTimeInMs_; - ::DBusTimeout* libdbusTimeout_; - std::weak_ptr<MainLoopContext> mainLoopContext_; -}; - - -} // namespace DBus -} // namespace CommonAPI - -#endif diff --git a/src/CommonAPI/DBus/DBusMessage.cpp b/src/CommonAPI/DBus/DBusMessage.cpp index 512ed57..e041b79 100644 --- a/src/CommonAPI/DBus/DBusMessage.cpp +++ b/src/CommonAPI/DBus/DBusMessage.cpp @@ -1,280 +1,242 @@ -/* Copyright (C) 2013 BMW Group - * Author: Manfred Bathelt (manfred.bathelt@bmw.de) - * Author: Juergen Gehring (juergen.gehring@bmw.de) - * 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 "DBusMessage.h" +// 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/. #include <cassert> #include <cstring> +#include <CommonAPI/DBus/DBusAddress.hpp> +#include <CommonAPI/DBus/DBusMessage.hpp> + namespace CommonAPI { namespace DBus { -DBusMessage::DBusMessage(): - libdbusMessage_(NULL) { +DBusMessage::DBusMessage() + : message_(NULL) { } -DBusMessage::DBusMessage(::DBusMessage* libdbusMessage) { - libdbusMessage_ = libdbusMessage != NULL ? dbus_message_ref(libdbusMessage) : NULL; +DBusMessage::DBusMessage(::DBusMessage *_message) { + message_ = (_message != nullptr ? dbus_message_ref(_message) : nullptr); } -DBusMessage::DBusMessage(::DBusMessage* libdbusMessage, bool increaseReferenceCount) { - assert(libdbusMessage); - - libdbusMessage_ = increaseReferenceCount ? dbus_message_ref(libdbusMessage) : libdbusMessage; +DBusMessage::DBusMessage(::DBusMessage *_message, bool reference) { + assert(_message); + message_ = (reference ? dbus_message_ref(message_) : _message); } -DBusMessage::DBusMessage(const DBusMessage& src) { - libdbusMessage_ = src.libdbusMessage_ != NULL ? dbus_message_ref(src.libdbusMessage_) : NULL; +DBusMessage::DBusMessage(const DBusMessage &_source) { + message_ = (_source.message_ != nullptr ? + dbus_message_ref(_source.message_) : nullptr); } -DBusMessage::DBusMessage(DBusMessage&& rsrc) { - libdbusMessage_ = rsrc.libdbusMessage_; - rsrc.libdbusMessage_ = NULL; +DBusMessage::DBusMessage(DBusMessage &&_source) { + message_ = _source.message_; + _source.message_ = nullptr; } DBusMessage::~DBusMessage() { - if (libdbusMessage_) - dbus_message_unref(libdbusMessage_); + if (message_) + dbus_message_unref(message_); } -DBusMessage& DBusMessage::operator=(const DBusMessage& src) { - if (this != &src) { - if (libdbusMessage_) - dbus_message_unref(libdbusMessage_); +DBusMessage & +DBusMessage::operator=(const DBusMessage &_source) { + if (this != &_source) { + if (message_) + dbus_message_unref(message_); - libdbusMessage_ = src.libdbusMessage_ != NULL ? dbus_message_ref(src.libdbusMessage_) : NULL; + message_ = (_source.message_ != nullptr ? + dbus_message_ref(_source.message_) : nullptr); } - - return *this; + return (*this); } -DBusMessage& DBusMessage::operator=(DBusMessage&& rsrc) { - if (this != &rsrc) { - if (libdbusMessage_) - dbus_message_unref(libdbusMessage_); +DBusMessage & +DBusMessage::operator=(DBusMessage &&_source) { + if (this != &_source) { + if (message_) + dbus_message_unref(message_); - libdbusMessage_ = rsrc.libdbusMessage_; - rsrc.libdbusMessage_ = NULL; + message_ = _source.message_; + _source.message_ = NULL; } - - return *this; + return (*this); } DBusMessage::operator bool() const { - const bool isNotNullDBusMessage = (libdbusMessage_ != NULL); - return isNotNullDBusMessage; + return (nullptr != message_); } -DBusMessage DBusMessage::createOrgFreedesktopOrgMethodCall(const char* methodName, const char* signature) { - return DBusMessage::createMethodCall("org.freedesktop.DBus", - "/", - "org.freedesktop.DBus", - methodName, - signature); -} - -DBusMessage DBusMessage::createOrgFreedesktopOrgMethodCall(const std::string& methodName, - const std::string& signature) { - assert(!methodName.empty()); +DBusMessage +DBusMessage::createOrgFreedesktopOrgMethodCall( + const std::string &_method, const std::string &_signature) { - return createOrgFreedesktopOrgMethodCall(methodName.c_str(), - signature.empty() ? NULL : signature.c_str()); + static DBusAddress address("org.freedesktop.DBus", "/", "org.freedesktop.DBus"); + return DBusMessage::createMethodCall(address, _method, _signature); } -DBusMessage DBusMessage::createMethodCall(const char* busName, - const char* objectPath, - const char* interfaceName, - const char* methodName, - const char* signature) { - assert(busName); - assert(objectPath); - assert(interfaceName); - assert(methodName); +DBusMessage +DBusMessage::createMethodCall( + const DBusAddress &_address, + const std::string &_method, const std::string &_signature) { - ::DBusMessage* libdbusMessageCall = dbus_message_new_method_call(busName, - objectPath, - interfaceName, - methodName); - assert(libdbusMessageCall); + std::string service = _address.getService(); + std::string path = _address.getObjectPath(); + std::string interface = _address.getInterface(); - if (signature) - dbus_message_set_signature(libdbusMessageCall, signature); + ::DBusMessage *methodCall = dbus_message_new_method_call( + service.c_str(), path.c_str(), + interface.c_str(), _method.c_str()); + assert(methodCall); - const bool increaseLibdbusMessageReferenceCount = false; - return DBusMessage(libdbusMessageCall, increaseLibdbusMessageReferenceCount); -} + if ("" != _signature) + dbus_message_set_signature(methodCall, _signature.c_str()); -DBusMessage DBusMessage::createMethodCall(const std::string& busName, - const std::string& objectPath, - const std::string& interfaceName, - const std::string& methodName, - const std::string& signature) { - assert(!busName.empty()); - assert(!objectPath.empty()); - assert(!interfaceName.empty()); - assert(!methodName.empty()); - - return createMethodCall(busName.c_str(), - objectPath.c_str(), - interfaceName.c_str(), - methodName.c_str(), - signature.empty() ? NULL : signature.c_str()); + return DBusMessage(methodCall, false); } -DBusMessage DBusMessage::createMethodReturn(const char* signature) const { - ::DBusMessage* libdbusMessageReturn = dbus_message_new_method_return(libdbusMessage_); - assert(libdbusMessageReturn); +DBusMessage +DBusMessage::createMethodReturn(const std::string &_signature) const { + ::DBusMessage *methodReturn = dbus_message_new_method_return(message_); + assert(methodReturn); - if (signature) - dbus_message_set_signature(libdbusMessageReturn, signature); + if ("" != _signature) + dbus_message_set_signature(methodReturn, _signature.c_str()); - const bool increaseLibdbusMessageReferenceCount = false; - return DBusMessage(libdbusMessageReturn, increaseLibdbusMessageReferenceCount); + return DBusMessage(methodReturn, false); } -DBusMessage DBusMessage::createMethodReturn(const std::string& signature) const { - return createMethodReturn(signature.empty() ? NULL : signature.c_str()); -} +DBusMessage +DBusMessage::createMethodError( + const std::string &_code, const std::string &_info) const { -DBusMessage DBusMessage::createMethodError(const std::string& name, const std::string& reason) const { - ::DBusMessage* libdbusMessageError = dbus_message_new_error(libdbusMessage_, name.c_str(), reason.c_str()); - assert(libdbusMessageError); + ::DBusMessage *methodError + = dbus_message_new_error(message_, _code.c_str(), _info.c_str()); + assert(methodError); - const bool increaseLibdbusMessageReferenceCount = false; - return DBusMessage(libdbusMessageError, increaseLibdbusMessageReferenceCount); + return DBusMessage(methodError, false); } -DBusMessage DBusMessage::createSignal(const char* objectPath, - const char* interfaceName, - const char* signalName, - const char* signature) { - assert(objectPath); - assert(interfaceName); - assert(signalName); - - ::DBusMessage* libdbusMessageSignal = dbus_message_new_signal(objectPath, - interfaceName, - signalName); - assert(libdbusMessageSignal); +DBusMessage +DBusMessage::createSignal( + const std::string &_path, const std::string &_interface, + const std::string &_signal, const std::string &_signature) { - if (signature) - dbus_message_set_signature(libdbusMessageSignal, signature); + ::DBusMessage *messageSignal + = dbus_message_new_signal(_path.c_str(), _interface.c_str(), _signal.c_str()); + assert(messageSignal); - const bool increaseLibdbusMessageReferenceCount = false; - return DBusMessage(libdbusMessageSignal, increaseLibdbusMessageReferenceCount); -} - -DBusMessage DBusMessage::createSignal(const std::string& objectPath, - const std::string& interfaceName, - const std::string& signalName, - const std::string& signature) { - assert(!objectPath.empty()); - assert(!interfaceName.empty()); - assert(!signalName.empty()); + if ("" != _signature) + dbus_message_set_signature(messageSignal, _signature.c_str()); - return createSignal(objectPath.c_str(), - interfaceName.c_str(), - signalName.c_str(), - signature.empty() ? NULL : signature.c_str()); + return DBusMessage(messageSignal, false); } -const char* DBusMessage::getObjectPath() const { - return dbus_message_get_path(libdbusMessage_); +const char * +DBusMessage::getObjectPath() const { + return dbus_message_get_path(message_); } -const char* DBusMessage::getSenderName() const { - return dbus_message_get_sender(libdbusMessage_); +const char * +DBusMessage::getSender() const { + return dbus_message_get_sender(message_); } -const char* DBusMessage::getInterfaceName() const { - return dbus_message_get_interface(libdbusMessage_); +const char * +DBusMessage::getInterface() const { + return dbus_message_get_interface(message_); } -const char* DBusMessage::getMemberName() const { - return dbus_message_get_member(libdbusMessage_); +const char * +DBusMessage::getMember() const { + return dbus_message_get_member(message_); } -const char* DBusMessage::getSignatureString() const { - return dbus_message_get_signature(libdbusMessage_); +const char * +DBusMessage::getSignature() const { + return dbus_message_get_signature(message_); } -const char* DBusMessage::getErrorName() const { +const char * +DBusMessage::getError() const { assert(isErrorType()); + return dbus_message_get_error_name(message_); +} - return dbus_message_get_error_name(libdbusMessage_); +const char * +DBusMessage::getDestination() const { + return dbus_message_get_destination(message_); } -const char* DBusMessage::getDestination() const { - return dbus_message_get_destination(libdbusMessage_); +const uint32_t DBusMessage::getSerial() const { + return dbus_message_get_serial(message_); } -bool DBusMessage::hasObjectPath(const char* objectPath) const { - const char* dbusMessageObjectPath = getObjectPath(); +bool +DBusMessage::hasObjectPath(const char *_path) const { + const char *path = getObjectPath(); - assert(objectPath); - assert(dbusMessageObjectPath); + assert(_path); + assert(path); - return !strcmp(dbusMessageObjectPath, objectPath); + return (!strcmp(path, _path)); } -bool DBusMessage::hasInterfaceName(const char* interfaceName) const { - const char* dbusMessageInterfaceName = getInterfaceName(); +bool DBusMessage::hasInterfaceName(const char *_interface) const { + const char *interface = getInterface(); - assert(interfaceName); - assert(dbusMessageInterfaceName); + assert(_interface); + assert(interface); - return !strcmp(dbusMessageInterfaceName, interfaceName); + return (!strcmp(interface, _interface)); } -bool DBusMessage::hasMemberName(const char* memberName) const { - const char* dbusMessageMemberName = getMemberName(); +bool DBusMessage::hasMemberName(const char *_member) const { + const char *member = getMember(); - assert(memberName); - assert(dbusMessageMemberName); + assert(_member); + assert(member); - return !strcmp(dbusMessageMemberName, memberName); + return (!strcmp(member, _member)); } -bool DBusMessage::hasSignature(const char* signature) const { - const char* dbusMessageSignature = getSignatureString(); +bool DBusMessage::hasSignature(const char *_signature) const { + const char *signature = getSignature(); + assert(_signature); assert(signature); - assert(dbusMessageSignature); - return !strcmp(dbusMessageSignature, signature); + return (!strcmp(signature, _signature)); } const DBusMessage::Type DBusMessage::getType() const { - const int libdbusType = dbus_message_get_type(libdbusMessage_); - return static_cast<Type>(libdbusType); + return static_cast<Type>(dbus_message_get_type(message_)); } -char* DBusMessage::getBodyData() const { - return dbus_message_get_body(libdbusMessage_); +char * DBusMessage::getBodyData() const { + return dbus_message_get_body(message_); } int DBusMessage::getBodyLength() const { - return dbus_message_get_body_length(libdbusMessage_); + return dbus_message_get_body_length(message_); } int DBusMessage::getBodySize() const { - return dbus_message_get_body_allocated(libdbusMessage_); + return dbus_message_get_body_allocated(message_); } -bool DBusMessage::setBodyLength(const int bodyLength) { - return dbus_message_set_body_length(libdbusMessage_, bodyLength); +bool DBusMessage::setBodyLength(const int _length) { + return 0 != dbus_message_set_body_length(message_, _length); } -bool DBusMessage::setDestination(const char* destination) +bool DBusMessage::setDestination(const char *_destination) { - return dbus_message_set_destination(libdbusMessage_, destination); + return 0 != dbus_message_set_destination(message_, _destination); } -bool DBusMessage::hasObjectPath(const std::string& objectPath) const { - return hasObjectPath(objectPath.c_str()); +bool DBusMessage::hasObjectPath(const std::string &_path) const { + return hasObjectPath(_path.c_str()); } bool DBusMessage::isInvalidType() const { diff --git a/src/CommonAPI/DBus/DBusMessage.h b/src/CommonAPI/DBus/DBusMessage.h deleted file mode 100644 index 66addf3..0000000 --- a/src/CommonAPI/DBus/DBusMessage.h +++ /dev/null @@ -1,117 +0,0 @@ -/* Copyright (C) 2013 BMW Group - * Author: Manfred Bathelt (manfred.bathelt@bmw.de) - * Author: Juergen Gehring (juergen.gehring@bmw.de) - * 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/. */ - -#if !defined (COMMONAPI_INTERNAL_COMPILATION) -#error "Only <CommonAPI/CommonAPI.h> can be included directly, this file may disappear or change contents." -#endif - -#ifndef COMMONAPI_DBUS_DBUS_MESSAGE_H_ -#define COMMONAPI_DBUS_DBUS_MESSAGE_H_ - -#include <string> - -#include <dbus/dbus.h> - -namespace CommonAPI { -namespace DBus { - -class DBusConnection; - -class DBusMessage { - public: - DBusMessage(); - DBusMessage(::DBusMessage* libdbusMessage); - DBusMessage(::DBusMessage* libdbusMessage, bool increaseReferenceCount); - DBusMessage(const DBusMessage& src); - DBusMessage(DBusMessage&& src); - - ~DBusMessage(); - - DBusMessage& operator=(const DBusMessage& src); - DBusMessage& operator=(DBusMessage&& rsrc); - operator bool() const; - - static DBusMessage createOrgFreedesktopOrgMethodCall(const char* methodName, - const char* signature = NULL); - - static DBusMessage createOrgFreedesktopOrgMethodCall(const std::string& methodName, - const std::string& signature = ""); - - static DBusMessage createMethodCall(const char* busName, - const char* objectPath, - const char* interfaceName, - const char* methodName, - const char* signature = NULL); - - static DBusMessage createMethodCall(const std::string& busName, - const std::string& objectPath, - const std::string& interfaceName, - const std::string& methodName, - const std::string& signature = ""); - - DBusMessage createMethodReturn(const char* signature = NULL) const; - - DBusMessage createMethodReturn(const std::string& signature) const; - - DBusMessage createMethodError(const std::string& name, const std::string& reason = "") const; - - static DBusMessage createSignal(const char* objectPath, - const char* interfaceName, - const char* signalName, - const char* signature = NULL); - - static DBusMessage createSignal(const std::string& objectPath, - const std::string& interfaceName, - const std::string& signalName, - const std::string& signature = ""); - - const char* getSenderName() const; - const char* getObjectPath() const; - const char* getInterfaceName() const; - const char* getMemberName() const; - const char* getSignatureString() const; - const char* getErrorName() const; - const char* getDestination() const; - - bool hasObjectPath(const std::string& objectPath) const; - - bool hasObjectPath(const char* objectPath) const; - bool hasInterfaceName(const char* interfaceName) const; - bool hasMemberName(const char* memberName) const; - bool hasSignature(const char* signature) const; - - enum class Type: int { - Invalid = DBUS_MESSAGE_TYPE_INVALID, - MethodCall = DBUS_MESSAGE_TYPE_METHOD_CALL, - MethodReturn = DBUS_MESSAGE_TYPE_METHOD_RETURN, - Error = DBUS_MESSAGE_TYPE_ERROR, - Signal = DBUS_MESSAGE_TYPE_SIGNAL - }; - const Type getType() const; - bool isInvalidType() const; - bool isMethodCallType() const; - bool isMethodReturnType() const; - bool isErrorType() const; - bool isSignalType() const; - - char* getBodyData() const; - int getBodyLength() const; - int getBodySize() const; - - bool setBodyLength(const int bodyLength); - bool setDestination(const char* destination); - - private: - ::DBusMessage* libdbusMessage_; - - friend class DBusConnection; -}; - -} // namespace DBus -} // namespace CommonAPI - -#endif // COMMONAPI_DBUS_DBUS_MESSAGE_H_ diff --git a/src/CommonAPI/DBus/DBusMultiEvent.h b/src/CommonAPI/DBus/DBusMultiEvent.h deleted file mode 100644 index a98dd80..0000000 --- a/src/CommonAPI/DBus/DBusMultiEvent.h +++ /dev/null @@ -1,121 +0,0 @@ -/* Copyright (C) 2013 BMW Group - * Author: Manfred Bathelt (manfred.bathelt@bmw.de) - * Author: Juergen Gehring (juergen.gehring@bmw.de) - * 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/. */ - -#if !defined (COMMONAPI_INTERNAL_COMPILATION) -#error "Only <CommonAPI/CommonAPI.h> can be included directly, this file may disappear or change contents." -#endif - -#ifndef COMMONAPI_DBUS_DBUS_MULTI_EVENT_H_ -#define COMMONAPI_DBUS_DBUS_MULTI_EVENT_H_ - -#include <CommonAPI/Event.h> - -#include <string> -#include <unordered_map> - - -namespace CommonAPI { -namespace DBus { - -template <typename... _Arguments> -class DBusMultiEvent { - public: - typedef std::function<SubscriptionStatus(const std::string&, const _Arguments&...)> Listener; - typedef std::unordered_multimap<std::string, Listener> ListenersMap; - typedef typename ListenersMap::iterator Subscription; - - Subscription subscribeAll(const Listener& listener); - Subscription subscribe(const std::string& eventName, const Listener& listener); - - void unsubscribe(Subscription listenerSubscription); - - virtual ~DBusMultiEvent() { } - - protected: - SubscriptionStatus notifyListeners(const std::string& name, const _Arguments&... eventArguments); - - virtual void onFirstListenerAdded(const std::string& name, const Listener& listener) { } - virtual void onListenerAdded(const std::string& name, const Listener& listener) { } - - virtual void onListenerRemoved(const std::string& name, const Listener& listener) { } - virtual void onLastListenerRemoved(const std::string& name, const Listener& listener) { } - - private: - typedef std::pair<typename ListenersMap::iterator, typename ListenersMap::iterator> IteratorRange; - SubscriptionStatus notifyListenersRange(const std::string& name, IteratorRange listenersRange, const _Arguments&... eventArguments); - - ListenersMap listenersMap_; -}; - -template <typename... _Arguments> -typename DBusMultiEvent<_Arguments...>::Subscription -DBusMultiEvent<_Arguments...>::subscribeAll(const Listener& listener) { - return subscribe(std::string(), listener); -} - -template <typename... _Arguments> -typename DBusMultiEvent<_Arguments...>::Subscription -DBusMultiEvent<_Arguments...>::subscribe(const std::string& eventName, const Listener& listener) { - const bool firstListenerAdded = listenersMap_.empty(); - - auto listenerSubscription = listenersMap_.insert({eventName, listener}); - - if (firstListenerAdded) { - onFirstListenerAdded(eventName, listener); - } - - onListenerAdded(eventName, listener); - - return listenerSubscription; -} - -template <typename... _Arguments> -void DBusMultiEvent<_Arguments...>::unsubscribe(Subscription listenerSubscription) { - const std::string name = listenerSubscription->first; - const Listener listener = listenerSubscription->second; - - listenersMap_.erase(listenerSubscription); - - onListenerRemoved(name, listener); - - const bool lastListenerRemoved = listenersMap_.empty(); - if (lastListenerRemoved) - onLastListenerRemoved(name, listener); -} - -template <typename... _Arguments> -SubscriptionStatus DBusMultiEvent<_Arguments...>::notifyListeners(const std::string& name, const _Arguments&... eventArguments) { - const SubscriptionStatus subscriptionStatus = notifyListenersRange(name, listenersMap_.equal_range(name), eventArguments...); - - if (subscriptionStatus == SubscriptionStatus::CANCEL) - return SubscriptionStatus::CANCEL; - - return notifyListenersRange(name, listenersMap_.equal_range(std::string()), eventArguments...); -} - -template <typename... _Arguments> -SubscriptionStatus DBusMultiEvent<_Arguments...>::notifyListenersRange( - const std::string& name, - IteratorRange listenersRange, - const _Arguments&... eventArguments) { - for (auto iterator = listenersRange.first; iterator != listenersRange.second; iterator++) { - const Listener& listener = iterator->second; - const SubscriptionStatus listenerSubcriptionStatus = listener(name, eventArguments...); - - if (listenerSubcriptionStatus == SubscriptionStatus::CANCEL) { - auto listenerIterator = iterator; - listenersMap_.erase(listenerIterator); - } - } - - return listenersMap_.empty() ? SubscriptionStatus::CANCEL : SubscriptionStatus::RETAIN; -} - -} // namespace DBus -} // namespace CommonAPI - -#endif // COMMONAPI_DBUS_DBUS_MULTI_EVENT_H_ diff --git a/src/CommonAPI/DBus/DBusObjectManager.cpp b/src/CommonAPI/DBus/DBusObjectManager.cpp index df43bf0..35a3d4f 100644 --- a/src/CommonAPI/DBus/DBusObjectManager.cpp +++ b/src/CommonAPI/DBus/DBusObjectManager.cpp @@ -1,26 +1,23 @@ -/* Copyright (C) 2013 BMW Group - * Author: Manfred Bathelt (manfred.bathelt@bmw.de) - * Author: Juergen Gehring (juergen.gehring@bmw.de) - * 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 "DBusObjectManager.h" -#include "DBusDaemonProxy.h" -#include "DBusStubAdapter.h" -#include "DBusOutputStream.h" -#include "DBusUtils.h" - -#include "DBusFreedesktopPropertiesStub.h" - -#include <CommonAPI/utils.h> - -#include <dbus/dbus-protocol.h> +// 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/. #include <cassert> #include <sstream> - #include <unordered_set> +#include <dbus/dbus-protocol.h> + +#include <CommonAPI/Utils.hpp> +#include <CommonAPI/DBus/DBusAddress.hpp> +#include <CommonAPI/DBus/DBusDaemonProxy.hpp> +#include <CommonAPI/DBus/DBusFreedesktopPropertiesStub.hpp> +#include <CommonAPI/DBus/DBusObjectManager.hpp> +#include <CommonAPI/DBus/DBusOutputStream.hpp> +#include <CommonAPI/DBus/DBusStubAdapter.hpp> +#include <CommonAPI/DBus/DBusUtils.hpp> + namespace CommonAPI { namespace DBus { @@ -48,34 +45,36 @@ DBusObjectManager::~DBusObjectManager() { } bool DBusObjectManager::registerDBusStubAdapter(std::shared_ptr<DBusStubAdapter> dbusStubAdapter) { - const auto& dbusStubAdapterObjectPath = dbusStubAdapter->getObjectPath(); - const auto& dbusStubAdapterInterfaceName = dbusStubAdapter->getInterfaceName(); + const auto& dbusStubAdapterObjectPath = dbusStubAdapter->getDBusAddress().getObjectPath(); + const auto& dbusStubAdapterInterfaceName = dbusStubAdapter->getDBusAddress().getInterface(); DBusInterfaceHandlerPath dbusStubAdapterHandlerPath(dbusStubAdapterObjectPath, dbusStubAdapterInterfaceName); bool isRegistrationSuccessful = false; objectPathLock_.lock(); isRegistrationSuccessful = addDBusInterfaceHandler(dbusStubAdapterHandlerPath, dbusStubAdapter); - if(isRegistrationSuccessful && dbusStubAdapter->hasFreedesktopProperties()) { + if (isRegistrationSuccessful && dbusStubAdapter->hasFreedesktopProperties()) { const std::shared_ptr<DBusFreedesktopPropertiesStub> dbusFreedesktopPropertiesStub = - std::make_shared<DBusFreedesktopPropertiesStub>(dbusStubAdapterObjectPath, - dbusStubAdapterInterfaceName, - dbusStubAdapter->getDBusConnection(), - dbusStubAdapter); + std::make_shared<DBusFreedesktopPropertiesStub>(dbusStubAdapterObjectPath, + dbusStubAdapterInterfaceName, + dbusStubAdapter->getDBusConnection(), + dbusStubAdapter); isRegistrationSuccessful = isRegistrationSuccessful - && addDBusInterfaceHandler( - {dbusFreedesktopPropertiesStub->getDBusObjectPath(), - dbusFreedesktopPropertiesStub->getInterfaceName() - }, - dbusFreedesktopPropertiesStub); + && addDBusInterfaceHandler({ dbusFreedesktopPropertiesStub->getObjectPath(), + dbusFreedesktopPropertiesStub->getInterface() }, + dbusFreedesktopPropertiesStub); } - if (isRegistrationSuccessful && dbusStubAdapter->isManagingInterface()) { + if (isRegistrationSuccessful && dbusStubAdapter->isManaging()) { auto managerStubIterator = managerStubs_.find(dbusStubAdapterObjectPath); const bool managerStubExists = managerStubIterator != managerStubs_.end(); if (!managerStubExists) { - const std::shared_ptr<DBusObjectManagerStub> newManagerStub = std::make_shared<DBusObjectManagerStub>(dbusStubAdapterObjectPath, dbusStubAdapter->getDBusConnection()); + const std::shared_ptr<DBusObjectManagerStub> newManagerStub + = std::make_shared<DBusObjectManagerStub>( + dbusStubAdapterObjectPath, + dbusStubAdapter->getDBusConnection() + ); auto insertResult = managerStubs_.insert( {dbusStubAdapterObjectPath, {newManagerStub, 1} }); assert(insertResult.second); managerStubIterator = insertResult.first; @@ -109,15 +108,15 @@ bool DBusObjectManager::registerDBusStubAdapter(std::shared_ptr<DBusStubAdapter> bool DBusObjectManager::unregisterDBusStubAdapter(std::shared_ptr<DBusStubAdapter> dbusStubAdapter) { - const auto& dbusStubAdapterObjectPath = dbusStubAdapter->getObjectPath(); - const auto& dbusStubAdapterInterfaceName = dbusStubAdapter->getInterfaceName(); + const auto& dbusStubAdapterObjectPath = dbusStubAdapter->getDBusAddress().getObjectPath(); + const auto& dbusStubAdapterInterfaceName = dbusStubAdapter->getDBusAddress().getInterface(); DBusInterfaceHandlerPath dbusStubAdapterHandlerPath(dbusStubAdapterObjectPath, dbusStubAdapterInterfaceName); bool isDeregistrationSuccessful = false; objectPathLock_.lock(); isDeregistrationSuccessful = removeDBusInterfaceHandler(dbusStubAdapterHandlerPath, dbusStubAdapter); - if (isDeregistrationSuccessful && dbusStubAdapter->isManagingInterface()) { + if (isDeregistrationSuccessful && dbusStubAdapter->isManaging()) { auto managerStubIterator = managerStubs_.find(dbusStubAdapterObjectPath); assert(managerStubIterator != managerStubs_.end()); @@ -155,7 +154,7 @@ bool DBusObjectManager::exportManagedDBusStubAdapter(const std::string& parentOb assert(foundManagerStubIterator != managerStubs_.end()); if (std::get<0>(foundManagerStubIterator->second)->exportManagedDBusStubAdapter(dbusStubAdapter)) { - //XXX Other handling necessary? + // TODO Check if other handling is necessary? return true; } return false; @@ -168,7 +167,7 @@ bool DBusObjectManager::unexportManagedDBusStubAdapter(const std::string& parent assert(foundManagerStubIterator != managerStubs_.end()); if (std::get<0>(foundManagerStubIterator->second)->unexportManagedDBusStubAdapter(dbusStubAdapter)) { - //XXX Other handling necessary? + // Check if other handling is necessary? return true; } return false; @@ -177,7 +176,7 @@ bool DBusObjectManager::unexportManagedDBusStubAdapter(const std::string& parent bool DBusObjectManager::handleMessage(const DBusMessage& dbusMessage) { const char* objectPath = dbusMessage.getObjectPath(); - const char* interfaceName = dbusMessage.getInterfaceName(); + const char* interfaceName = dbusMessage.getInterface(); assert(objectPath); assert(interfaceName); @@ -322,7 +321,6 @@ bool DBusObjectManager::onIntrospectableInterfaceDBusMessage(const DBusMessage& return false; } - std::shared_ptr<DBusObjectManagerStub> DBusObjectManager::getRootDBusObjectManagerStub() { return rootDBusObjectManagerStub_; } diff --git a/src/CommonAPI/DBus/DBusObjectManager.h b/src/CommonAPI/DBus/DBusObjectManager.h deleted file mode 100644 index 6ce6e6c..0000000 --- a/src/CommonAPI/DBus/DBusObjectManager.h +++ /dev/null @@ -1,72 +0,0 @@ -/* Copyright (C) 2013 BMW Group - * Author: Manfred Bathelt (manfred.bathelt@bmw.de) - * Author: Juergen Gehring (juergen.gehring@bmw.de) - * 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/. */ - -#if !defined (COMMONAPI_INTERNAL_COMPILATION) -#error "Only <CommonAPI/CommonAPI.h> can be included directly, this file may disappear or change contents." -#endif - -#ifndef COMMONAPI_DBUS_DBUS_OBJECT_MANAGER_H_ -#define COMMONAPI_DBUS_DBUS_OBJECT_MANAGER_H_ - -#include "DBusProxyConnection.h" -#include "DBusMessage.h" -#include "DBusObjectManagerStub.h" - - -namespace CommonAPI { -namespace DBus { - -class DBusStubAdapter; -class DBusInterfaceHandler; - -class DBusObjectManager { - public: - DBusObjectManager(const std::shared_ptr<DBusProxyConnection>&); - ~DBusObjectManager(); - - bool registerDBusStubAdapter(std::shared_ptr<DBusStubAdapter> dbusStubAdapter); - bool unregisterDBusStubAdapter(std::shared_ptr<DBusStubAdapter> dbusStubAdapter); - - //Zusammenfassbar mit "registerDBusStubAdapter"? - bool exportManagedDBusStubAdapter(const std::string& parentObjectPath, std::shared_ptr<DBusStubAdapter> dbusStubAdapter); - bool unexportManagedDBusStubAdapter(const std::string& parentObjectPath, std::shared_ptr<DBusStubAdapter> dbusStubAdapter); - - bool handleMessage(const DBusMessage&); - - std::shared_ptr<DBusObjectManagerStub> getRootDBusObjectManagerStub(); - - private: - // objectPath, interfaceName - typedef std::pair<std::string, std::string> DBusInterfaceHandlerPath; - - bool addDBusInterfaceHandler(const DBusInterfaceHandlerPath& dbusInterfaceHandlerPath, - std::shared_ptr<DBusInterfaceHandler> dbusInterfaceHandler); - - bool removeDBusInterfaceHandler(const DBusInterfaceHandlerPath& dbusInterfaceHandlerPath, - std::shared_ptr<DBusInterfaceHandler> dbusInterfaceHandler); - - bool onIntrospectableInterfaceDBusMessage(const DBusMessage& callMessage); - bool onFreedesktopPropertiesDBusMessage(const DBusMessage& callMessage); - - - typedef std::unordered_map<DBusInterfaceHandlerPath, std::shared_ptr<DBusInterfaceHandler>> DBusRegisteredObjectsTable; - DBusRegisteredObjectsTable dbusRegisteredObjectsTable_; - - std::shared_ptr<DBusObjectManagerStub> rootDBusObjectManagerStub_; - - typedef std::pair<std::shared_ptr<DBusObjectManagerStub>, uint32_t> ReferenceCountedDBusObjectManagerStub; - typedef std::unordered_map<std::string, ReferenceCountedDBusObjectManagerStub> RegisteredObjectManagersTable; - RegisteredObjectManagersTable managerStubs_; - - std::weak_ptr<DBusProxyConnection> dbusConnection_; - std::recursive_mutex objectPathLock_; -}; - -} // namespace DBus -} // namespace CommonAPI - -#endif // COMMONAPI_DBUS_DBUS_OBJECT_MANAGER_H_ diff --git a/src/CommonAPI/DBus/DBusObjectManagerStub.cpp b/src/CommonAPI/DBus/DBusObjectManagerStub.cpp index 970f366..e292473 100644 --- a/src/CommonAPI/DBus/DBusObjectManagerStub.cpp +++ b/src/CommonAPI/DBus/DBusObjectManagerStub.cpp @@ -1,17 +1,16 @@ -/* Copyright (C) 2013 BMW Group - * Author: Manfred Bathelt (manfred.bathelt@bmw.de) - * Author: Juergen Gehring (juergen.gehring@bmw.de) - * 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 "DBusObjectManagerStub.h" -#include "DBusStubAdapter.h" -#include "DBusServicePublisher.h" -#include "DBusOutputStream.h" +// 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/. #include <cassert> #include <vector> +#include <CommonAPI/DBus/DBusObjectManagerStub.hpp> +#include <CommonAPI/DBus/DBusOutputStream.hpp> +#include <CommonAPI/DBus/DBusStubAdapter.hpp> +#include <CommonAPI/DBus/DBusTypes.hpp> + namespace CommonAPI { namespace DBus { @@ -30,11 +29,12 @@ DBusObjectManagerStub::~DBusObjectManagerStub() { for (auto& dbusInterfaceIterator : registeredDBusInterfacesMap) { auto managedDBusStubAdapter = dbusInterfaceIterator.second; - auto managedDBusStubAdapterServiceAddress = managedDBusStubAdapter->getAddress(); - + auto managedDBusStubAdapterServiceAddress = managedDBusStubAdapter->getDBusAddress(); +#ifdef LB_TODO const bool isServiceUnregistered = DBusServicePublisher::getInstance()->unregisterManagedService( managedDBusStubAdapterServiceAddress); assert(isServiceUnregistered); +#endif } } } @@ -88,8 +88,8 @@ bool DBusObjectManagerStub::unexportManagedDBusStubAdapter(std::shared_ptr<DBusS bool DBusObjectManagerStub::isDBusStubAdapterExported(std::shared_ptr<DBusStubAdapter> dbusStubAdapter) { assert(dbusStubAdapter); - const auto& dbusObjectPath = dbusStubAdapter->getObjectPath(); - const auto& dbusInterfaceName = dbusStubAdapter->getInterfaceName(); + const auto& dbusObjectPath = dbusStubAdapter->getDBusAddress().getObjectPath(); + const auto& dbusInterfaceName = dbusStubAdapter->getDBusAddress().getInterface(); std::lock_guard<std::mutex> dbusObjectManagerStubLock(dbusObjectManagerStubLock_); @@ -113,8 +113,8 @@ bool DBusObjectManagerStub::isDBusStubAdapterExported(std::shared_ptr<DBusStubAd } bool DBusObjectManagerStub::registerDBusStubAdapter(std::shared_ptr<DBusStubAdapter> dbusStubAdapter) { - const auto& dbusObjectPath = dbusStubAdapter->getObjectPath(); - const auto& dbusInterfaceName = dbusStubAdapter->getInterfaceName(); + const auto& dbusObjectPath = dbusStubAdapter->getDBusAddress().getObjectPath(); + const auto& dbusInterfaceName = dbusStubAdapter->getDBusAddress().getInterface(); const auto& registeredDBusObjectPathIterator = registeredDBusObjectPathsMap_.find(dbusObjectPath); const bool isKnownDBusObjectPath = (registeredDBusObjectPathIterator != registeredDBusObjectPathsMap_.end()); bool isRegisterationSuccessful = false; @@ -139,8 +139,8 @@ bool DBusObjectManagerStub::registerDBusStubAdapter(std::shared_ptr<DBusStubAdap } bool DBusObjectManagerStub::unregisterDBusStubAdapter(std::shared_ptr<DBusStubAdapter> dbusStubAdapter) { - const auto& dbusObjectPath = dbusStubAdapter->getObjectPath(); - const auto& dbusInterfaceName = dbusStubAdapter->getInterfaceName(); + const auto& dbusObjectPath = dbusStubAdapter->getDBusAddress().getObjectPath(); + const auto& dbusInterfaceName = dbusStubAdapter->getDBusAddress().getInterface(); const auto& registeredDBusObjectPathIterator = registeredDBusObjectPathsMap_.find(dbusObjectPath); const bool isKnownDBusObjectPath = (registeredDBusObjectPathIterator != registeredDBusObjectPathsMap_.end()); @@ -174,15 +174,15 @@ bool DBusObjectManagerStub::emitInterfacesAddedSignal(std::shared_ptr<DBusStubAd assert(dbusConnection); assert(dbusConnection->isConnected()); - const auto& dbusStubObjectPath = dbusStubAdapter->getObjectPath(); - const auto& dbusStubInterfaceName = dbusStubAdapter->getInterfaceName(); + const auto& dbusStubObjectPath = dbusStubAdapter->getDBusAddress().getObjectPath(); + const auto& dbusStubInterfaceName = dbusStubAdapter->getDBusAddress().getInterface(); DBusMessage dbusSignal = DBusMessage::createSignal(dbusObjectPath_, getInterfaceName(), "InterfacesAdded", "oa{sa{sv}}"); DBusOutputStream dbusOutputStream(dbusSignal); DBusInterfacesAndPropertiesDict dbusInterfacesAndPropertiesDict({ { dbusStubInterfaceName, DBusPropertiesChangedDict() } }); - if (dbusStubAdapter->isManagingInterface()) { + if (dbusStubAdapter->isManaging()) { dbusInterfacesAndPropertiesDict.insert({ getInterfaceName(), DBusPropertiesChangedDict() }); } @@ -203,13 +203,13 @@ bool DBusObjectManagerStub::emitInterfacesRemovedSignal(std::shared_ptr<DBusStub assert(dbusConnection); assert(dbusConnection->isConnected()); - const auto& dbusStubObjectPath = dbusStubAdapter->getObjectPath(); - const auto& dbusStubInterfaceName = dbusStubAdapter->getInterfaceName(); + const auto& dbusStubObjectPath = dbusStubAdapter->getDBusAddress().getObjectPath(); + const auto& dbusStubInterfaceName = dbusStubAdapter->getDBusAddress().getInterface(); DBusMessage dbusSignal = DBusMessage::createSignal(dbusObjectPath_, getInterfaceName(), "InterfacesRemoved", "oas"); DBusOutputStream dbusOutputStream(dbusSignal); std::vector<std::string> removedInterfaces({ { dbusStubInterfaceName } }); - if (dbusStubAdapter->isManagingInterface()) { + if (dbusStubAdapter->isManaging()) { removedInterfaces.push_back(getInterfaceName()); } @@ -265,7 +265,7 @@ bool DBusObjectManagerStub::onInterfaceDBusMessage(const DBusMessage& dbusMessag dbusInterfacesAndPropertiesDict.insert({ registeredDBusInterfaceName, DBusPropertiesChangedDict() }); - if (registeredDBusStubAdapter->isManagingInterface()) { + if (registeredDBusStubAdapter->isManaging()) { dbusInterfacesAndPropertiesDict.insert({ getInterfaceName(), DBusPropertiesChangedDict() }); } } diff --git a/src/CommonAPI/DBus/DBusObjectManagerStub.h b/src/CommonAPI/DBus/DBusObjectManagerStub.h deleted file mode 100644 index 7de54f2..0000000 --- a/src/CommonAPI/DBus/DBusObjectManagerStub.h +++ /dev/null @@ -1,127 +0,0 @@ -/* Copyright (C) 2013 BMW Group - * Author: Manfred Bathelt (manfred.bathelt@bmw.de) - * Author: Juergen Gehring (juergen.gehring@bmw.de) - * 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/. */ -#ifndef COMMONAPI_DBUS_DBUS_FREEDESKTOP_OBJECT_MANAGER_STUB_H_ -#define COMMONAPI_DBUS_DBUS_FREEDESKTOP_OBJECT_MANAGER_STUB_H_ - - -#include "DBusInterfaceHandler.h" - -#include <memory> -#include <mutex> -#include <string> - -namespace CommonAPI { -namespace DBus { - -class DBusStubAdapter; - -/** - * Stub for standard <a href="http://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces-objectmanager">org.freedesktop.dbus.ObjectManager</a> interface. - * - * Instantiated within a manager stub and it must hold reference to all registered objects. - * Whenever the manager gets destroyed all references to registered objects are lost too. - * This duplicates the semantic of the CommonAPI::ServicePublisher class. - * - * Only one DBusStubAdapter instance could be registered per DBusObjectManagerStub instance. - * - * The owner of the DBusObjectManagerStub instance must take care of registering and unregistering it. - * - * Example stub life cycle: - * - create CommonAPI::ServicePublisher - * - create stub A - * - register stub A to CommonAPI::ServicePublisher - * - create stub B - * - register stub B with stub A as object manager - * - drop all references to stub B, stub A keeps a reference to stub B - * - drop all references to stub A, CommonAPI::ServicePublisher keeps a reference to stub A - * - reference overview: Application > CommonAPI::ServicePublisher > Stub A > Stub B - * - drop all references to CommonAPI::ServicePublisher causes all object references to be dropped - */ -class DBusObjectManagerStub: public DBusInterfaceHandler { - public: - // serialization trick: use bool instead of variant since we never serialize it - typedef std::unordered_map<std::string, bool> DBusPropertiesChangedDict; - typedef std::unordered_map<std::string, DBusPropertiesChangedDict> DBusInterfacesAndPropertiesDict; - typedef std::unordered_map<std::string, DBusInterfacesAndPropertiesDict> DBusObjectPathAndInterfacesDict; - - public: - DBusObjectManagerStub(const std::string& dbusObjectPath, const std::shared_ptr<DBusProxyConnection>&); - - /** - * Unregisters all currently registered DBusStubAdapter instances from the DBusServicePublisher - */ - virtual ~DBusObjectManagerStub(); - - /** - * Export DBusStubAdapter instance with the current DBusObjectManagerStub instance. - * - * The DBusStubAdapter must be registered with the DBusServicePublisher! - * - * On registering a - * <a href="http://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces-objectmanager">InsterfaceAdded</a> - * signal will be emitted with the DBusObjectManagerStub instance's current D-Bus object path. - * - * @param dbusStubAdapter a refernce to DBusStubAdapter instance - * - * @return false if the @a dbusStubAdapter instance was already registered - * @return false if sending the InterfaceAdded signal fails - * - * @see ~DBusObjectManagerStub() - * @see CommonAPI::ServicePublisher - * @see DBusObjectManager - */ - bool exportManagedDBusStubAdapter(std::shared_ptr<DBusStubAdapter> dbusStubAdapter); - - /** - * Unexport DBusStubAdapter instance from this DBusObjectManagerStub instance. - * - * On unregistering a - * <a href="http://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces-objectmanager">InsterfaceRemoved</a> - * signal will be emitted with the DBusObjectManagerStub instance's current D-Bus object path. - * - * @param dbusStubAdapter - * - * @return false if @a dbusStubAdapter wasn't registered - * @return true even if sending the InterfaceRemoved signal fails - * - * @see exportDBusStubAdapter() - */ - bool unexportManagedDBusStubAdapter(std::shared_ptr<DBusStubAdapter> dbusStubAdapter); - - bool isDBusStubAdapterExported(std::shared_ptr<DBusStubAdapter> dbusStubAdapter); - - const std::string& getDBusObjectPath() const; - static const char* getInterfaceName(); - - virtual const char* getMethodsDBusIntrospectionXmlData() const; - virtual bool onInterfaceDBusMessage(const DBusMessage& dbusMessage); - virtual const bool hasFreedesktopProperties(); - - private: - bool registerDBusStubAdapter(std::shared_ptr<DBusStubAdapter> dbusStubAdapter); - bool unregisterDBusStubAdapter(std::shared_ptr<DBusStubAdapter> dbusStubAdapter); - - bool emitInterfacesAddedSignal(std::shared_ptr<DBusStubAdapter> dbusStubAdapter, - const std::shared_ptr<DBusProxyConnection>& dbusConnection) const; - - bool emitInterfacesRemovedSignal(std::shared_ptr<DBusStubAdapter> dbusStubAdapter, - const std::shared_ptr<DBusProxyConnection>& dbusConnection) const; - - std::string dbusObjectPath_; - std::weak_ptr<DBusProxyConnection> dbusConnection_; - - typedef std::unordered_map<std::string, std::shared_ptr<DBusStubAdapter>> DBusInterfacesMap; - typedef std::unordered_map<std::string, DBusInterfacesMap> DBusObjectPathsMap; - DBusObjectPathsMap registeredDBusObjectPathsMap_; - - std::mutex dbusObjectManagerStubLock_; -}; - -} // namespace DBus -} // namespace CommonAPI - -#endif // COMMONAPI_DBUS_DBUS_FREEDESKTOP_OBJECT_MANAGER_STUB_H_ diff --git a/src/CommonAPI/DBus/DBusOutputStream.cpp b/src/CommonAPI/DBus/DBusOutputStream.cpp index 4dfc9fa..7d59360 100644 --- a/src/CommonAPI/DBus/DBusOutputStream.cpp +++ b/src/CommonAPI/DBus/DBusOutputStream.cpp @@ -1,297 +1,53 @@ -/* Copyright (C) 2013 BMW Group - * Author: Manfred Bathelt (manfred.bathelt@bmw.de) - * Author: Juergen Gehring (juergen.gehring@bmw.de) - * 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 "DBusOutputStream.h" +// 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/. -namespace CommonAPI { -namespace DBus { +//#define COMMONAPI_DBUS_DEBUG_SERIALIZATION -DBusOutputStream::DBusOutputStream(DBusMessage dbusMessage) : - dbusMessage_(dbusMessage) { -} +#ifdef COMMONAPI_DBUS_DEBUG_SERIALIZATION +#include <iomanip> +#include <sstream> +#endif -DBusOutputStream::~DBusOutputStream() {} +#include <CommonAPI/DBus/DBusOutputStream.hpp> -OutputStream& DBusOutputStream::writeValue(const bool& boolValue) { - alignToBoundary(4); - writeBasicTypeValue(boolValue); - alignToBoundary(4); - return *this; -} - -OutputStream& DBusOutputStream::writeValue(const int8_t& int8Value) { - return writeBasicTypeValue(int8Value); -} -OutputStream& DBusOutputStream::writeValue(const int16_t& int16Value) { - return writeBasicTypeValue(int16Value); -} -OutputStream& DBusOutputStream::writeValue(const int32_t& int32Value) { - return writeBasicTypeValue(int32Value); -} -OutputStream& DBusOutputStream::writeValue(const int64_t& int64Value) { - return writeBasicTypeValue(int64Value); -} - -OutputStream& DBusOutputStream::writeValue(const uint8_t& uint8Value) { - return writeBasicTypeValue(uint8Value); -} -OutputStream& DBusOutputStream::writeValue(const uint16_t& uint16Value) { - return writeBasicTypeValue(uint16Value); -} -OutputStream& DBusOutputStream::writeValue(const uint32_t& uint32Value) { - return writeBasicTypeValue(uint32Value); -} -OutputStream& DBusOutputStream::writeValue(const uint64_t& uint64Value) { - return writeBasicTypeValue(uint64Value); -} - -OutputStream& DBusOutputStream::writeValue(const float& floatValue) { - return writeBasicTypeValue((double) floatValue); -} -OutputStream& DBusOutputStream::writeValue(const double& doubleValue) { - return writeBasicTypeValue(doubleValue); -} - -OutputStream& DBusOutputStream::writeValue(const std::string& stringValue) { - return writeString(stringValue.c_str(), stringValue.length()); -} - -OutputStream& DBusOutputStream::writeValue(const ByteBuffer& byteBufferValue) { - return *this; -} - -OutputStream& DBusOutputStream::writeEnumValue(const int8_t& int8BackingTypeValue) { - return writeValue(int8BackingTypeValue); -} -OutputStream& DBusOutputStream::writeEnumValue(const int16_t& int16BackingTypeValue) { - return writeValue(int16BackingTypeValue); -} -OutputStream& DBusOutputStream::writeEnumValue(const int32_t& int32BackingTypeValue) { - return writeValue(int32BackingTypeValue); -} -OutputStream& DBusOutputStream::writeEnumValue(const int64_t& int64BackingTypeValue) { - return writeValue(int64BackingTypeValue); -} -OutputStream& DBusOutputStream::writeEnumValue(const uint8_t& uint8BackingTypeValue) { - return writeValue(uint8BackingTypeValue); -} -OutputStream& DBusOutputStream::writeEnumValue(const uint16_t& uint16BackingTypeValue) { - return writeValue(uint16BackingTypeValue); -} -OutputStream& DBusOutputStream::writeEnumValue(const uint32_t& uint32BackingTypeValue) { - return writeValue(uint32BackingTypeValue); -} -OutputStream& DBusOutputStream::writeEnumValue(const uint64_t& uint64BackingTypeValue) { - return writeValue(uint64BackingTypeValue); -} - -void DBusOutputStream::beginWriteBoolVector(uint32_t sizeOfVector) { - beginWriteGenericVector(); - rememberCurrentStreamPosition(); -} -void DBusOutputStream::beginWriteInt8Vector(uint32_t sizeOfVector) { - beginWriteGenericVector(); - rememberCurrentStreamPosition(); -} -void DBusOutputStream::beginWriteInt16Vector(uint32_t sizeOfVector) { - beginWriteGenericVector(); - rememberCurrentStreamPosition(); -} -void DBusOutputStream::beginWriteInt32Vector(uint32_t sizeOfVector) { - beginWriteGenericVector(); - rememberCurrentStreamPosition(); -} -void DBusOutputStream::beginWriteInt64Vector(uint32_t sizeOfVector) { - beginWriteGenericVector(); - alignToBoundary(8); - rememberCurrentStreamPosition(); -} -void DBusOutputStream::beginWriteUInt8Vector(uint32_t sizeOfVector) { - beginWriteGenericVector(); - rememberCurrentStreamPosition(); -} -void DBusOutputStream::beginWriteUInt16Vector(uint32_t sizeOfVector) { - beginWriteGenericVector(); - rememberCurrentStreamPosition(); -} -void DBusOutputStream::beginWriteUInt32Vector(uint32_t sizeOfVector) { - beginWriteGenericVector(); - rememberCurrentStreamPosition(); -} -void DBusOutputStream::beginWriteUInt64Vector(uint32_t sizeOfVector) { - beginWriteGenericVector(); - alignToBoundary(8); - rememberCurrentStreamPosition(); -} -void DBusOutputStream::beginWriteFloatVector(uint32_t sizeOfVector) { - beginWriteGenericVector(); - alignToBoundary(8); - rememberCurrentStreamPosition(); -} -void DBusOutputStream::beginWriteDoubleVector(uint32_t sizeOfVector) { - beginWriteGenericVector(); - alignToBoundary(8); - rememberCurrentStreamPosition(); -} -void DBusOutputStream::beginWriteStringVector(uint32_t sizeOfVector) { - beginWriteGenericVector(); - rememberCurrentStreamPosition(); -} -void DBusOutputStream::beginWriteByteBufferVector(uint32_t sizeOfVector) { - beginWriteGenericVector(); - rememberCurrentStreamPosition(); -} -void DBusOutputStream::beginWriteVersionVector(uint32_t sizeOfVector) { - beginWriteGenericVector(); - alignToBoundary(8); - rememberCurrentStreamPosition(); -} - -void DBusOutputStream::beginWriteInt8EnumVector(uint32_t sizeOfVector) { - beginWriteGenericVector(); - rememberCurrentStreamPosition(); -} -void DBusOutputStream::beginWriteInt16EnumVector(uint32_t sizeOfVector) { - beginWriteGenericVector(); - rememberCurrentStreamPosition(); -} -void DBusOutputStream::beginWriteInt32EnumVector(uint32_t sizeOfVector) { - beginWriteGenericVector(); - rememberCurrentStreamPosition(); -} -void DBusOutputStream::beginWriteInt64EnumVector(uint32_t sizeOfVector) { - beginWriteGenericVector(); - alignToBoundary(8); - rememberCurrentStreamPosition(); -} -void DBusOutputStream::beginWriteUInt8EnumVector(uint32_t sizeOfVector) { - beginWriteGenericVector(); - rememberCurrentStreamPosition(); -} -void DBusOutputStream::beginWriteUInt16EnumVector(uint32_t sizeOfVector) { - beginWriteGenericVector(); - rememberCurrentStreamPosition(); -} -void DBusOutputStream::beginWriteUInt32EnumVector(uint32_t sizeOfVector) { - beginWriteGenericVector(); - rememberCurrentStreamPosition(); -} -void DBusOutputStream::beginWriteUInt64EnumVector(uint32_t sizeOfVector) { - beginWriteGenericVector(); - alignToBoundary(8); - rememberCurrentStreamPosition(); -} - -void DBusOutputStream::beginWriteVectorOfSerializableStructs(uint32_t sizeOfVector) { - beginWriteGenericVector(); - alignToBoundary(8); - rememberCurrentStreamPosition(); -} -void DBusOutputStream::beginWriteVectorOfSerializableVariants(uint32_t sizeOfVector) { - beginWriteGenericVector(); - alignToBoundary(8); - rememberCurrentStreamPosition(); -} -void DBusOutputStream::beginWriteVectorOfVectors(uint32_t sizeOfVector) { - beginWriteGenericVector(); - rememberCurrentStreamPosition(); -} -void DBusOutputStream::beginWriteVectorOfMaps(uint32_t sizeOfVector) { - beginWriteGenericVector(); - alignToBoundary(4); - rememberCurrentStreamPosition(); -} - -void DBusOutputStream::beginWriteVectorOfSerializablePolymorphicStructs(uint32_t sizeOfVector) { - beginWriteGenericVector(); - alignToBoundary(8); - rememberCurrentStreamPosition(); -} - -void DBusOutputStream::endWriteVector() { - uint32_t numOfWrittenBytes = getCurrentStreamPosition() - popRememberedStreamPosition(); - writeBasicTypeValueAtPosition(popRememberedStreamPosition(), numOfWrittenBytes); -} - -OutputStream& DBusOutputStream::writeVersionValue(const Version& versionValue) { - alignToBoundary(8); - writeValue(versionValue.Major); - writeValue(versionValue.Minor); - return *this; -} - -void DBusOutputStream::beginWriteSerializableStruct(const SerializableStruct& serializableStruct) { - alignToBoundary(8); -} -void DBusOutputStream::endWriteSerializableStruct(const SerializableStruct& serializableStruct) { -} - -void DBusOutputStream::beginWriteSerializablePolymorphicStruct(const std::shared_ptr<SerializablePolymorphicStruct>& serializableStruct) { - alignToBoundary(8); - writeValue(serializableStruct->getSerialId()); - - DBusTypeOutputStream typeOutputStream; - typeOutputStream.beginWriteStructType(); - serializableStruct->createTypeSignature(typeOutputStream); - typeOutputStream.endWriteStructType(); - - writeSignature(std::move(typeOutputStream.retrieveSignature())); - - beginWriteSerializableStruct(*serializableStruct); -} - -void DBusOutputStream::endWriteSerializablePolymorphicStruct(const std::shared_ptr<SerializablePolymorphicStruct>& serializableStruct) { - endWriteSerializableStruct(*serializableStruct); -} - -void DBusOutputStream::beginWriteMap(size_t elementCount) { - alignToBoundary(sizeof(uint32_t)); - rememberCurrentStreamPosition(); - writeBasicTypeValue((uint32_t) 0); - alignToBoundary(8); - rememberCurrentStreamPosition(); -} +namespace CommonAPI { +namespace DBus { -void DBusOutputStream::endWriteMap() { - uint32_t numOfWrittenBytes = getCurrentStreamPosition() - popRememberedStreamPosition(); - writeBasicTypeValueAtPosition(popRememberedStreamPosition(), numOfWrittenBytes); +DBusOutputStream::DBusOutputStream(DBusMessage dbusMessage) + : dbusMessage_(dbusMessage) { } -void DBusOutputStream::beginWriteMapElement() { - alignToBoundary(8); +// Internal +size_t DBusOutputStream::getPosition() { + return payload_.size(); } -void DBusOutputStream::endWriteMapElement() { -} - -void DBusOutputStream::beginWriteSerializableVariant(const SerializableVariant& serializableVariant) { - alignToBoundary(8); - writeValue(serializableVariant.getValueType()); - DBusTypeOutputStream typeOutputStream; - serializableVariant.writeToTypeOutputStream(typeOutputStream); - writeSignature(std::move(typeOutputStream.retrieveSignature())); +void DBusOutputStream::pushPosition() { + positions_.push(payload_.size()); } -void DBusOutputStream::endWriteSerializableVariant(const SerializableVariant& serializableVariant) { +size_t DBusOutputStream::popPosition() { + size_t itsPosition = positions_.top(); + positions_.pop(); + return itsPosition; } +// TODO Check where dbusError_ is set bool DBusOutputStream::hasError() const { return dbusError_; } -/** - * Writes the data that was buffered within this #DBusOutputMessageStream to the #DBusMessage that was given to the constructor. Each call to flush() - * will completely override the data that currently is contained in the #DBusMessage. The data that is buffered in this #DBusOutputMessageStream is - * not deleted by calling flush(). - */ +// Writes the data that was buffered within this #DBusOutputMessageStream to +// the #DBusMessage that was given to the constructor. Each call to flush() +// will completely override the data that currently is contained in the +// #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); char* destinationDataPtr = dbusMessage_.getBodyData(); - memcpy(destinationDataPtr, payload_.c_str(), toWrite); } @@ -299,8 +55,10 @@ void DBusOutputStream::setError() { } /** - * Reserves the given number of bytes for writing, thereby negating the need to dynamically allocate memory while writing. - * Use this method for optimization: If possible, reserve as many bytes as you need for your data before doing any writing. + * Reserves the given number of bytes for writing, thereby negating the need to + * dynamically allocate memory while writing. Use this method for optimization: + * If possible, reserve as many bytes as you need for your data before doing + * any writing. * * @param numOfBytes The number of bytes that should be reserved for writing. */ @@ -309,49 +67,35 @@ void DBusOutputStream::reserveMemory(size_t numOfBytes) { payload_.reserve(numOfBytes); } -DBusOutputStream& DBusOutputStream::writeString(const char* cString, const uint32_t& length) { - assert(cString != NULL); - assert(cString[length] == '\0'); - - *this << length; +DBusOutputStream& DBusOutputStream::writeString(const char *_value, const uint32_t &_length) { + assert(_value != NULL); + assert(_value[_length] == '\0'); - writeRawData(cString, length + 1); + _writeValue(_length); + _writeRaw(_value, _length + 1); - return *this; + return (*this); } -//Additional 0-termination, so this is 8 byte of \0 +// Additional 0-termination, so this is 8 byte of \0 static const char eightByteZeroString[] = "\0\0\0\0\0\0\0"; -void DBusOutputStream::alignToBoundary(const size_t alignBoundary) { - assert(alignBoundary > 0 && alignBoundary <= 8 && (alignBoundary % 2 == 0 || alignBoundary == 1)); +void DBusOutputStream::align(const size_t _boundary) { + assert(_boundary > 0 && _boundary <= 8 && + (_boundary % 2 == 0 || _boundary == 1)); - size_t alignMask = alignBoundary - 1; - size_t necessaryAlignment = ((alignMask - (payload_.size() & alignMask)) + 1) & alignMask; + size_t mask = _boundary - 1; + size_t necessary = ((mask - (payload_.size() & mask)) + 1) & mask; - writeRawData(eightByteZeroString, necessaryAlignment); + _writeRaw(eightByteZeroString, necessary); } -bool DBusOutputStream::writeRawData(const char* rawDataPtr, const size_t sizeInByte) { - assert(sizeInByte >= 0); - - payload_.append(rawDataPtr, sizeInByte); - - return true; -} - -bool DBusOutputStream::writeRawDataAtPosition(size_t position, const char* rawDataPtr, const size_t sizeInByte) { - assert(sizeInByte >= 0); - - payload_ = payload_.replace(position, sizeInByte, rawDataPtr, sizeInByte); - - return true; +void DBusOutputStream::_writeRaw(const char *_data, const size_t _size) { + payload_.append(_data, _size); } -void DBusOutputStream::beginWriteGenericVector() { - alignToBoundary(sizeof(uint32_t)); - rememberCurrentStreamPosition(); - writeBasicTypeValue((uint32_t) 0); +void DBusOutputStream::_writeRawAt(const char *_data, const size_t _size, size_t _position) { + payload_ = payload_.replace(_position, _size, _data, _size); } void DBusOutputStream::writeSignature(const std::string& signature) { @@ -359,22 +103,8 @@ void DBusOutputStream::writeSignature(const std::string& signature) { assert(signatureLength > 0 && signatureLength < 256); const uint8_t wireLength = (uint8_t) signatureLength; - *this << wireLength; - writeRawData(signature.c_str(), wireLength + 1); -} - -void DBusOutputStream::rememberCurrentStreamPosition() { - savedStreamPositions_.push(payload_.size()); -} - -size_t DBusOutputStream::popRememberedStreamPosition() { - size_t val = savedStreamPositions_.top(); - savedStreamPositions_.pop(); - return val; -} - -size_t DBusOutputStream::getCurrentStreamPosition() { - return payload_.size(); + (*this) << wireLength; + _writeRaw(signature.c_str(), wireLength + 1); } } // namespace DBus diff --git a/src/CommonAPI/DBus/DBusOutputStream.h b/src/CommonAPI/DBus/DBusOutputStream.h deleted file mode 100644 index 51e5f2f..0000000 --- a/src/CommonAPI/DBus/DBusOutputStream.h +++ /dev/null @@ -1,351 +0,0 @@ -/* Copyright (C) 2013 BMW Group - * Author: Manfred Bathelt (manfred.bathelt@bmw.de) - * Author: Juergen Gehring (juergen.gehring@bmw.de) - * 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/. */ - -#if !defined (COMMONAPI_INTERNAL_COMPILATION) -#error "Only <CommonAPI/CommonAPI.h> can be included directly, this file may disappear or change contents." -#endif - -#ifndef COMMONAPI_DBUS_DBUS_OUTPUT_MESSAGE_STREAM_H_ -#define COMMONAPI_DBUS_DBUS_OUTPUT_MESSAGE_STREAM_H_ - -#include "DBusMessage.h" -#include "DBusError.h" - -#include <CommonAPI/OutputStream.h> - -#include <string> -#include <cstring> -#include <vector> -#include <cassert> -#include <stack> -#include <memory> - -namespace CommonAPI { -namespace DBus { - -class DBusTypeOutputStream: public TypeOutputStream { -public: - DBusTypeOutputStream() : - signature_("") { - - } - virtual ~DBusTypeOutputStream() {} - - virtual void writeBoolType() { - signature_.append("b"); - } - - virtual void writeInt8Type() { - signature_.append("y"); - } - virtual void writeInt16Type() { - signature_.append("n"); - } - virtual void writeInt32Type() { - signature_.append("i"); - } - virtual void writeInt64Type() { - signature_.append("x"); - } - - virtual void writeUInt8Type() { - signature_.append("y"); - } - virtual void writeUInt16Type() { - signature_.append("q"); - } - virtual void writeUInt32Type() { - signature_.append("u"); - } - virtual void writeUInt64Type() { - signature_.append("t"); - } - - virtual void writeInt8EnumType() { - signature_.append("y"); - } - virtual void writeInt16EnumType() { - signature_.append("n"); - } - virtual void writeInt32EnumType() { - signature_.append("i"); - } - virtual void writeInt64EnumType() { - signature_.append("x"); - } - - virtual void writeUInt8EnumType() { - signature_.append("y"); - } - virtual void writeUInt16EnumType() { - signature_.append("n"); - } - virtual void writeUInt32EnumType() { - signature_.append("u"); - } - virtual void writeUInt64EnumType() { - signature_.append("t"); - } - - virtual void writeFloatType() { - signature_.append("d"); - } - virtual void writeDoubleType() { - signature_.append("d"); - } - - virtual void writeStringType() { - signature_.append("s"); - } - virtual void writeByteBufferType() { - signature_.append("ay"); - } - virtual void writeVersionType() { - signature_.append("(uu)"); - } - - virtual void beginWriteStructType() { - signature_.append("("); - } - virtual void endWriteStructType() { - signature_.append(")"); - } - - virtual void beginWriteMapType() { - signature_.append("a{"); - } - virtual void endWriteMapType() { - signature_.append("}"); - } - - virtual void beginWriteVectorType() { - signature_.append("a"); - } - - virtual void endWriteVectorType() { - } - - virtual void writeVariantType() { - signature_.append("(yv)"); - } - - void writeLegacyVariantType() { - signature_.append("v"); - } - - virtual std::string retrieveSignature() { - return std::move(signature_); - } - -private: - std::string signature_; -}; - -/** - * Used to mark the position of a pointer within an array of bytes. - */ -typedef uint32_t position_t; - -/** - * @class DBusOutputMessageStream - * - * Used to serialize and write data into a #DBusMessage. For all data types that may be written to a #DBusMessage, a "<<"-operator should be defined to handle the writing - * (this operator is predefined for all basic data types and for vectors). The signature that has to be written to the #DBusMessage separately is assumed - * to match the actual data that is inserted via the #DBusOutputMessageStream. - */ -class DBusOutputStream: public OutputStream { -public: - - /** - * Creates a #DBusOutputMessageStream which can be used to serialize and write data into the given #DBusMessage. Any data written is buffered within the stream. - * Remember to call flush() when you are done with writing: Only then the data actually is written to the #DBusMessage. - * - * @param dbusMessage The #DBusMessage any data pushed into this stream should be written to. - */ - DBusOutputStream(DBusMessage dbusMessage); - - /** - * Destructor; does not call the destructor of the referred #DBusMessage. Make sure to maintain a reference to the - * #DBusMessage outside of the stream if you intend to make further use of the message, e.g. in order to send it, - * now that you have written some payload into it. - */ - virtual ~DBusOutputStream(); - - virtual OutputStream& writeValue(const bool& boolValue); - - virtual OutputStream& writeValue(const int8_t& int8Value); - virtual OutputStream& writeValue(const int16_t& int16Value); - virtual OutputStream& writeValue(const int32_t& int32Value); - virtual OutputStream& writeValue(const int64_t& int64Value); - - virtual OutputStream& writeValue(const uint8_t& uint8Value); - virtual OutputStream& writeValue(const uint16_t& uint16Value); - virtual OutputStream& writeValue(const uint32_t& uint32Value); - virtual OutputStream& writeValue(const uint64_t& uint64Value); - - virtual OutputStream& writeValue(const float& floatValue); - virtual OutputStream& writeValue(const double& doubleValue); - - virtual OutputStream& writeValue(const std::string& stringValue); - - virtual OutputStream& writeValue(const ByteBuffer& byteBufferValue); - - virtual OutputStream& writeEnumValue(const int8_t& int8BackingTypeValue); - virtual OutputStream& writeEnumValue(const int16_t& int16BackingTypeValue); - virtual OutputStream& writeEnumValue(const int32_t& int32BackingTypeValue); - virtual OutputStream& writeEnumValue(const int64_t& int64BackingTypeValue); - virtual OutputStream& writeEnumValue(const uint8_t& uint8BackingTypeValue); - virtual OutputStream& writeEnumValue(const uint16_t& uint16BackingTypeValue); - virtual OutputStream& writeEnumValue(const uint32_t& uint32BackingTypeValue); - virtual OutputStream& writeEnumValue(const uint64_t& uint64BackingTypeValue); - - virtual void beginWriteBoolVector(uint32_t sizeOfVector); - virtual void beginWriteInt8Vector(uint32_t sizeOfVector); - virtual void beginWriteInt16Vector(uint32_t sizeOfVector); - virtual void beginWriteInt32Vector(uint32_t sizeOfVector); - virtual void beginWriteInt64Vector(uint32_t sizeOfVector); - virtual void beginWriteUInt8Vector(uint32_t sizeOfVector); - virtual void beginWriteUInt16Vector(uint32_t sizeOfVector); - virtual void beginWriteUInt32Vector(uint32_t sizeOfVector); - virtual void beginWriteUInt64Vector(uint32_t sizeOfVector); - virtual void beginWriteFloatVector(uint32_t sizeOfVector); - virtual void beginWriteDoubleVector(uint32_t sizeOfVector); - virtual void beginWriteStringVector(uint32_t sizeOfVector); - virtual void beginWriteByteBufferVector(uint32_t sizeOfVector); - virtual void beginWriteVersionVector(uint32_t sizeOfVector); - - virtual void beginWriteInt8EnumVector(uint32_t sizeOfVector); - virtual void beginWriteInt16EnumVector(uint32_t sizeOfVector); - virtual void beginWriteInt32EnumVector(uint32_t sizeOfVector); - virtual void beginWriteInt64EnumVector(uint32_t sizeOfVector); - virtual void beginWriteUInt8EnumVector(uint32_t sizeOfVector); - virtual void beginWriteUInt16EnumVector(uint32_t sizeOfVector); - virtual void beginWriteUInt32EnumVector(uint32_t sizeOfVector); - virtual void beginWriteUInt64EnumVector(uint32_t sizeOfVector); - - virtual void beginWriteVectorOfSerializableStructs(uint32_t sizeOfVector); - virtual void beginWriteVectorOfSerializableVariants(uint32_t sizeOfVector); - virtual void beginWriteVectorOfVectors(uint32_t sizeOfVector); - virtual void beginWriteVectorOfMaps(uint32_t sizeOfVector); - - virtual void beginWriteVectorOfSerializablePolymorphicStructs(uint32_t sizeOfVector); - - virtual void endWriteVector(); - - virtual OutputStream& writeVersionValue(const Version& versionValue); - - virtual void beginWriteSerializableStruct(const SerializableStruct& serializableStruct); - virtual void endWriteSerializableStruct(const SerializableStruct& serializableStruct); - - virtual void beginWriteSerializablePolymorphicStruct(const std::shared_ptr<SerializablePolymorphicStruct>& serializableStruct); - virtual void endWriteSerializablePolymorphicStruct(const std::shared_ptr<SerializablePolymorphicStruct>& serializableStruct); - - virtual void beginWriteMap(size_t elementCount); - virtual void endWriteMap(); - virtual void beginWriteMapElement(); - virtual void endWriteMapElement(); - - virtual void beginWriteSerializableVariant(const SerializableVariant& serializableVariant); - - virtual void endWriteSerializableVariant(const SerializableVariant& serializableVariant); - - virtual bool hasError() const; - - /** - * Writes the data that was buffered within this #DBusOutputMessageStream to the #DBusMessage that was given to the constructor. Each call to flush() - * will completely override the data that currently is contained in the #DBusMessage. The data that is buffered in this #DBusOutputMessageStream is - * not deleted by calling flush(). - */ - void flush(); - - void setError(); - - /** - * Reserves the given number of bytes for writing, thereby negating the need to dynamically allocate memory while writing. - * Use this method for optimization: If possible, reserve as many bytes as you need for your data before doing any writing. - * - * @param numOfBytes The number of bytes that should be reserved for writing. - */ - void reserveMemory(size_t numOfBytes); - - template<typename _BasicType> - DBusOutputStream& writeBasicTypeValue(const _BasicType& basicValue) { - if (sizeof(_BasicType) > 1) - alignToBoundary(sizeof(_BasicType)); - - writeRawData(reinterpret_cast<const char*>(&basicValue), sizeof(_BasicType)); - - return *this; - } - - template<typename _BasicType> - bool writeBasicTypeValueAtPosition(size_t position, const _BasicType& basicValue) { - assert(position + sizeof(_BasicType) <= payload_.size()); - - return writeRawDataAtPosition(position, reinterpret_cast<const char*>(&basicValue), sizeof(_BasicType)); - } - - DBusOutputStream& writeString(const char* cString, const uint32_t& length); - - /** - * Fills the stream with 0-bytes to make the next value be aligned to the boundary given. - * This means that as many 0-bytes are written to the buffer as are necessary - * to make the next value start with the given alignment. - * - * @param alignBoundary The byte-boundary to which the next value should be aligned. - */ - virtual void alignToBoundary(const size_t alignBoundary); - - /** - * Takes sizeInByte characters, starting from the character which val points to, and stores them for later writing. - * When calling flush(), all values that were written to this stream are copied into the payload of the #DBusMessage. - * - * The array of characters might be created from a pointer to a given value by using a reinterpret_cast. Example: - * @code - * ... - * int32_t val = 15; - * outputMessageStream.alignForBasicType(sizeof(int32_t)); - * const char* const reinterpreted = reinterpret_cast<const char*>(&val); - * outputMessageStream.writeValue(reinterpreted, sizeof(int32_t)); - * ... - * @endcode - * - * @param val The array of chars that should serve as input - * @param sizeInByte The number of bytes that should be written - * @return true if writing was successful, false otherwise. - * - * @see DBusOutputMessageStream() - * @see flush() - */ - bool writeRawData(const char* rawDataPtr, const size_t sizeInByte); - - bool writeRawDataAtPosition(size_t position, const char* rawDataPtr, const size_t sizeInByte); - -protected: - std::string payload_; - -private: - void beginWriteGenericVector(); - - void writeSignature(const std::string& signature); - - void rememberCurrentStreamPosition(); - - size_t popRememberedStreamPosition(); - - size_t getCurrentStreamPosition(); - - DBusError dbusError_; - DBusMessage dbusMessage_; - - std::stack<position_t> savedStreamPositions_; -}; - -} // namespace DBus -} // namespace CommonAPI - -#endif // COMMONAPI_DBUS_DBUS_OUTPUT_MESSAGE_STREAM_H_ diff --git a/src/CommonAPI/DBus/DBusProxy.cpp b/src/CommonAPI/DBus/DBusProxy.cpp index 73fc54a..a28abff 100644 --- a/src/CommonAPI/DBus/DBusProxy.cpp +++ b/src/CommonAPI/DBus/DBusProxy.cpp @@ -1,64 +1,46 @@ -/* Copyright (C) 2013 BMW Group - * Author: Manfred Bathelt (manfred.bathelt@bmw.de) - * Author: Juergen Gehring (juergen.gehring@bmw.de) - * 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/. */ -// Workaround for libstdc++ bug -#ifndef _GLIBCXX_USE_NANOSLEEP -#define _GLIBCXX_USE_NANOSLEEP -#endif - -#include "DBusProxy.h" -#include "DBusUtils.h" +// 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/. #include <cassert> #include <sstream> +#include <CommonAPI/Utils.hpp> +#include <CommonAPI/DBus/DBusProxy.hpp> +#include <CommonAPI/DBus/DBusUtils.hpp> namespace CommonAPI { namespace DBus { -DBusProxyStatusEvent::DBusProxyStatusEvent(DBusProxy* dbusProxy) : - dbusProxy_(dbusProxy) { +DBusProxyStatusEvent::DBusProxyStatusEvent(DBusProxy *_dbusProxy) + : dbusProxy_(_dbusProxy) { } -void DBusProxyStatusEvent::onListenerAdded(const CancellableListener& listener) { +void DBusProxyStatusEvent::onListenerAdded(const Listener& listener) { if (dbusProxy_->isAvailable()) listener(AvailabilityStatus::AVAILABLE); } - -DBusProxy::DBusProxy(const std::shared_ptr<DBusFactory>& factory, - const std::string& commonApiAddress, - const std::string& dbusInterfaceName, - const std::string& dbusBusName, - const std::string& dbusObjectPath, - const std::shared_ptr<DBusProxyConnection>& dbusConnection): - DBusProxyBase(dbusConnection), +DBusProxy::DBusProxy(const DBusAddress &_dbusAddress, + const std::shared_ptr<DBusProxyConnection> &_connection): + DBusProxyBase(_dbusAddress, _connection), dbusProxyStatusEvent_(this), availabilityStatus_(AvailabilityStatus::UNKNOWN), interfaceVersionAttribute_(*this, "uu", "getInterfaceVersion"), - dbusServiceRegistry_(dbusConnection->getDBusServiceRegistry()), - commonApiServiceId_(split(commonApiAddress, ':')[1]), - commonApiParticipantId_(split(commonApiAddress, ':')[2]), - dbusBusName_(dbusBusName), - dbusObjectPath_(dbusObjectPath), - dbusInterfaceName_(dbusInterfaceName), - factory_(factory) { + dbusServiceRegistry_(DBusServiceRegistry::get(_connection)) +{ } void DBusProxy::init() { - std::stringstream ss; - ss << "local:" << commonApiServiceId_ << ":" << commonApiParticipantId_; dbusServiceRegistrySubscription_ = dbusServiceRegistry_->subscribeAvailabilityListener( - ss.str(), + getAddress().getAddress(), std::bind(&DBusProxy::onDBusServiceInstanceStatus, this, std::placeholders::_1)); } DBusProxy::~DBusProxy() { dbusServiceRegistry_->unsubscribeAvailabilityListener( - getAddress(), + getAddress().getAddress(), dbusServiceRegistrySubscription_); } @@ -87,38 +69,9 @@ InterfaceVersionAttribute& DBusProxy::getInterfaceVersionAttribute() { return interfaceVersionAttribute_; } -SubscriptionStatus DBusProxy::onDBusServiceInstanceStatus(const AvailabilityStatus& availabilityStatus) { +void DBusProxy::onDBusServiceInstanceStatus(const AvailabilityStatus& availabilityStatus) { availabilityStatus_ = availabilityStatus; dbusProxyStatusEvent_.notifyListeners(availabilityStatus); - return SubscriptionStatus::RETAIN; -} - -const std::string& DBusProxy::getDBusBusName() const { - return dbusBusName_; -} - -const std::string& DBusProxy::getDBusObjectPath() const { - return dbusObjectPath_; -} - -const std::string& DBusProxy::getInterfaceName() const { - return dbusInterfaceName_; -} - -const std::string& DBusProxy::getDomain() const { - return commonApiDomain_; -} - -const std::string& DBusProxy::getServiceId() const { - return commonApiServiceId_; -} - -const std::string& DBusProxy::getInstanceId() const { - return commonApiParticipantId_; -} - -std::string DBusProxy::getAddress() const { - return commonApiDomain_ + ":" + commonApiServiceId_ + ":" + commonApiParticipantId_; } DBusProxyConnection::DBusSignalHandlerToken DBusProxy::subscribeForSelectiveBroadcastOnConnection( diff --git a/src/CommonAPI/DBus/DBusProxy.h b/src/CommonAPI/DBus/DBusProxy.h deleted file mode 100644 index 81b97ea..0000000 --- a/src/CommonAPI/DBus/DBusProxy.h +++ /dev/null @@ -1,106 +0,0 @@ -/* Copyright (C) 2013 BMW Group - * Author: Manfred Bathelt (manfred.bathelt@bmw.de) - * Author: Juergen Gehring (juergen.gehring@bmw.de) - * 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/. */ - -#if !defined (COMMONAPI_INTERNAL_COMPILATION) -#error "Only <CommonAPI/CommonAPI.h> can be included directly, this file may disappear or change contents." -#endif - -#ifndef COMMONAPI_DBUS_DBUS_PROXY_H_ -#define COMMONAPI_DBUS_DBUS_PROXY_H_ - -#include "DBusProxyBase.h" -#include "DBusAttribute.h" -#include "DBusServiceRegistry.h" -#include "DBusFactory.h" - -#include <functional> -#include <memory> -#include <string> - - -namespace CommonAPI { -namespace DBus { - -class DBusProxyStatusEvent: public ProxyStatusEvent { - friend class DBusProxy; - - public: - DBusProxyStatusEvent(DBusProxy* dbusProxy); - - protected: - virtual void onListenerAdded(const CancellableListener& listener); - - DBusProxy* dbusProxy_; -}; - - -class DBusProxy: public DBusProxyBase { - public: - DBusProxy(const std::shared_ptr<DBusFactory>& factory, - const std::string& commonApiAddress, - const std::string& dbusInterfaceName, - const std::string& dbusBusName, - const std::string& dbusObjectPath, - const std::shared_ptr<DBusProxyConnection>& dbusConnection); - - virtual ~DBusProxy(); - - virtual bool isAvailable() const; - virtual ProxyStatusEvent& getProxyStatusEvent(); - virtual InterfaceVersionAttribute& getInterfaceVersionAttribute(); - - virtual bool isAvailableBlocking() const; - - virtual std::string getAddress() const; - virtual const std::string& getDomain() const; - virtual const std::string& getServiceId() const; - virtual const std::string& getInstanceId() const; - - virtual const std::string& getDBusBusName() const; - virtual const std::string& getDBusObjectPath() const; - virtual const std::string& getInterfaceName() const; - DBusProxyConnection::DBusSignalHandlerToken subscribeForSelectiveBroadcastOnConnection( - bool& subscriptionAccepted, - const std::string& objectPath, - const std::string& interfaceName, - const std::string& interfaceMemberName, - const std::string& interfaceMemberSignature, - DBusProxyConnection::DBusSignalHandler* dbusSignalHandler); - void unsubscribeFromSelectiveBroadcast(const std::string& eventName, - DBusProxyConnection::DBusSignalHandlerToken subscription, - const DBusProxyConnection::DBusSignalHandler* dbusSignalHandler); - - void init(); - private: - DBusProxy(const DBusProxy&) = delete; - - SubscriptionStatus onDBusServiceInstanceStatus(const AvailabilityStatus& availabilityStatus); - - DBusProxyStatusEvent dbusProxyStatusEvent_; - DBusServiceRegistry::DBusServiceSubscription dbusServiceRegistrySubscription_; - AvailabilityStatus availabilityStatus_; - - DBusReadonlyAttribute<InterfaceVersionAttribute> interfaceVersionAttribute_; - - std::shared_ptr<DBusServiceRegistry> dbusServiceRegistry_; - - const std::string commonApiServiceId_; - const std::string commonApiParticipantId_; - - const std::string dbusBusName_; - const std::string dbusObjectPath_; - const std::string dbusInterfaceName_; - - const std::shared_ptr<DBusFactory>& factory_; -}; - - -} // namespace DBus -} // namespace CommonAPI - -#endif // COMMONAPI_DBUS_DBUS_PROXY_H_ - diff --git a/src/CommonAPI/DBus/DBusProxyAsyncCallbackHandler.h b/src/CommonAPI/DBus/DBusProxyAsyncCallbackHandler.h deleted file mode 100644 index 66a78f1..0000000 --- a/src/CommonAPI/DBus/DBusProxyAsyncCallbackHandler.h +++ /dev/null @@ -1,79 +0,0 @@ -/* Copyright (C) 2013 BMW Group - * Author: Manfred Bathelt (manfred.bathelt@bmw.de) - * Author: Juergen Gehring (juergen.gehring@bmw.de) - * 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/. */ - -#if !defined (COMMONAPI_INTERNAL_COMPILATION) -#error "Only <CommonAPI/CommonAPI.h> can be included directly, this file may disappear or change contents." -#endif - -#ifndef COMMONAPI_DBUS_DBUS_PROXY_ASYNC_CALLBACK_HANDLER_H_ -#define COMMONAPI_DBUS_DBUS_PROXY_ASYNC_CALLBACK_HANDLER_H_ - -#include "DBusProxyConnection.h" -#include "DBusMessage.h" -#include "DBusSerializableArguments.h" -#include "DBusHelper.h" - -#include <functional> -#include <future> -#include <memory> - -namespace CommonAPI { -namespace DBus { - -template<typename ... _ArgTypes> -class DBusProxyAsyncCallbackHandler: public DBusProxyConnection::DBusMessageReplyAsyncHandler { - public: - typedef std::function<void(CallStatus, _ArgTypes...)> FunctionType; - - static std::unique_ptr<DBusProxyConnection::DBusMessageReplyAsyncHandler> create( - FunctionType&& callback) { - return std::unique_ptr<DBusProxyConnection::DBusMessageReplyAsyncHandler>( - new DBusProxyAsyncCallbackHandler(std::move(callback))); - } - - DBusProxyAsyncCallbackHandler() = delete; - DBusProxyAsyncCallbackHandler(FunctionType&& callback): - callback_(std::move(callback)) { - } - - virtual std::future<CallStatus> getFuture() { - return promise_.get_future(); - } - - virtual void onDBusMessageReply(const CallStatus& dbusMessageCallStatus, const DBusMessage& dbusMessage) { - std::tuple<_ArgTypes...> argTuple; - promise_.set_value(handleDBusMessageReply(dbusMessageCallStatus, dbusMessage, typename make_sequence<sizeof...(_ArgTypes)>::type(), argTuple)); - } - - private: - template <int... _ArgIndices> - inline CallStatus handleDBusMessageReply(const CallStatus dbusMessageCallStatus, const DBusMessage& dbusMessage, index_sequence<_ArgIndices...>, std::tuple<_ArgTypes...> argTuple) const { - CallStatus callStatus = dbusMessageCallStatus; - - if (dbusMessageCallStatus == CallStatus::SUCCESS) { - if (!dbusMessage.isErrorType()) { - DBusInputStream dbusInputStream(dbusMessage); - const bool success = DBusSerializableArguments<_ArgTypes...>::deserialize(dbusInputStream, std::get<_ArgIndices>(argTuple)...); - if (!success) - callStatus = CallStatus::REMOTE_ERROR; - } else { - callStatus = CallStatus::REMOTE_ERROR; - } - } - - callback_(callStatus, std::move(std::get<_ArgIndices>(argTuple))...); - return callStatus; - } - - std::promise<CallStatus> promise_; - const FunctionType callback_; -}; - -} // namespace DBus -} // namespace CommonAPI - -#endif // COMMONAPI_DBUS_DBUS_PROXY_ASYNC_CALLBACK_HANDLER_H_ diff --git a/src/CommonAPI/DBus/DBusProxyBase.cpp b/src/CommonAPI/DBus/DBusProxyBase.cpp index a493606..56d5717 100644 --- a/src/CommonAPI/DBus/DBusProxyBase.cpp +++ b/src/CommonAPI/DBus/DBusProxyBase.cpp @@ -1,32 +1,38 @@ -/* Copyright (C) 2013 BMW Group - * Author: Manfred Bathelt (manfred.bathelt@bmw.de) - * Author: Juergen Gehring (juergen.gehring@bmw.de) - * 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 "DBusProxyBase.h" -#include "DBusMessage.h" +// 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/. + +#include <CommonAPI/DBus/DBusAddress.hpp> +#include <CommonAPI/DBus/DBusAddressTranslator.hpp> +#include <CommonAPI/DBus/DBusProxyBase.hpp> +#include <CommonAPI/DBus/DBusMessage.hpp> namespace CommonAPI { namespace DBus { -DBusProxyBase::DBusProxyBase(const std::shared_ptr<DBusProxyConnection>& dbusConnection) : - commonApiDomain_("local"), - dbusConnection_(dbusConnection){ +DBusProxyBase::DBusProxyBase( + const DBusAddress &_dbusAddress, + const std::shared_ptr<DBusProxyConnection> &_connection) + : dbusAddress_(_dbusAddress), + connection_(_connection) { + DBusAddressTranslator::get()->translate(dbusAddress_, address_); +} + +DBusMessage +DBusProxyBase::createMethodCall(const std::string &_method, const std::string &_signature) const { + return DBusMessage::createMethodCall(getDBusAddress(), _method, _signature); } -DBusMessage DBusProxyBase::createMethodCall(const char* methodName, - const char* methodSignature) const { - return DBusMessage::createMethodCall( - getDBusBusName().c_str(), - getDBusObjectPath().c_str(), - getInterfaceName().c_str(), - methodName, - methodSignature); + +const DBusAddress & +DBusProxyBase::getDBusAddress() const { + return dbusAddress_; } -const std::shared_ptr<DBusProxyConnection>& DBusProxyBase::getDBusConnection() const { - return dbusConnection_; +const std::shared_ptr<DBusProxyConnection> & +DBusProxyBase::getDBusConnection() const { + return connection_; } DBusProxyConnection::DBusSignalHandlerToken DBusProxyBase::addSignalMemberHandler( @@ -35,8 +41,8 @@ DBusProxyConnection::DBusSignalHandlerToken DBusProxyBase::addSignalMemberHandle DBusProxyConnection::DBusSignalHandler* dbusSignalHandler, const bool justAddFilter) { return addSignalMemberHandler( - getDBusObjectPath(), - getInterfaceName(), + getDBusAddress().getObjectPath(), + getDBusAddress().getInterface(), signalName, signalSignature, dbusSignalHandler, @@ -50,7 +56,7 @@ DBusProxyConnection::DBusSignalHandlerToken DBusProxyBase::addSignalMemberHandle const std::string& signalSignature, DBusProxyConnection::DBusSignalHandler* dbusSignalHandler, const bool justAddFilter) { - return dbusConnection_->addSignalMemberHandler( + return connection_->addSignalMemberHandler( objectPath, interfaceName, signalName, @@ -60,7 +66,7 @@ DBusProxyConnection::DBusSignalHandlerToken DBusProxyBase::addSignalMemberHandle } bool DBusProxyBase::removeSignalMemberHandler(const DBusProxyConnection::DBusSignalHandlerToken& dbusSignalHandlerToken, const DBusProxyConnection::DBusSignalHandler* dbusSignalHandler) { - return dbusConnection_->removeSignalMemberHandler(dbusSignalHandlerToken, dbusSignalHandler); + return connection_->removeSignalMemberHandler(dbusSignalHandlerToken, dbusSignalHandler); } } // namespace DBus diff --git a/src/CommonAPI/DBus/DBusProxyBase.h b/src/CommonAPI/DBus/DBusProxyBase.h deleted file mode 100644 index d1a3a51..0000000 --- a/src/CommonAPI/DBus/DBusProxyBase.h +++ /dev/null @@ -1,75 +0,0 @@ -/* Copyright (C) 2013 BMW Group - * Author: Manfred Bathelt (manfred.bathelt@bmw.de) - * Author: Juergen Gehring (juergen.gehring@bmw.de) - * 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/. */ - -#if !defined (COMMONAPI_INTERNAL_COMPILATION) -#error "Only <CommonAPI/CommonAPI.h> can be included directly, this file may disappear or change contents." -#endif - -#ifndef COMMONAPI_DBUS_DBUS_PROXY_BASE_H_ -#define COMMONAPI_DBUS_DBUS_PROXY_BASE_H_ - -#include "DBusProxyConnection.h" - -#include <CommonAPI/Proxy.h> -#include <CommonAPI/types.h> - -#include <functional> -#include <memory> -#include <string> - -namespace CommonAPI { -namespace DBus { - -class DBusProxyBase: public virtual CommonAPI::Proxy { - public: - DBusProxyBase(const std::shared_ptr<DBusProxyConnection>& dbusProxyConnection); - - virtual std::string getAddress() const = 0; - virtual const std::string& getDomain() const = 0; - virtual const std::string& getServiceId() const = 0; - virtual const std::string& getInstanceId() const = 0; - - virtual const std::string& getDBusBusName() const = 0; - virtual const std::string& getDBusObjectPath() const = 0; - virtual const std::string& getInterfaceName() const = 0; - const std::shared_ptr<DBusProxyConnection>& getDBusConnection() const; - - DBusMessage createMethodCall(const char* methodName, - const char* methodSignature = NULL) const; - - DBusProxyConnection::DBusSignalHandlerToken addSignalMemberHandler( - const std::string& signalName, - const std::string& signalSignature, - DBusProxyConnection::DBusSignalHandler* dbusSignalHandler, - const bool justAddFilter = false); - - DBusProxyConnection::DBusSignalHandlerToken addSignalMemberHandler( - const std::string& objectPath, - const std::string& interfaceName, - const std::string& signalName, - const std::string& signalSignature, - DBusProxyConnection::DBusSignalHandler* dbusSignalHandler, - const bool justAddFilter = false); - - bool removeSignalMemberHandler(const DBusProxyConnection::DBusSignalHandlerToken& dbusSignalHandlerToken, const DBusProxyConnection::DBusSignalHandler* dbusSignalHandler = NULL); - - virtual void init() = 0; - - protected: - const std::string commonApiDomain_; - - private: - DBusProxyBase(const DBusProxyBase&) = delete; - - std::shared_ptr<DBusProxyConnection> dbusConnection_; -}; - -} // namespace DBus -} // namespace CommonAPI - -#endif // COMMONAPI_DBUS_DBUS_PROXY_BASE_H_ - diff --git a/src/CommonAPI/DBus/DBusProxyConnection.h b/src/CommonAPI/DBus/DBusProxyConnection.h deleted file mode 100644 index d7c88d8..0000000 --- a/src/CommonAPI/DBus/DBusProxyConnection.h +++ /dev/null @@ -1,135 +0,0 @@ -/* Copyright (C) 2013 BMW Group - * Author: Manfred Bathelt (manfred.bathelt@bmw.de) - * Author: Juergen Gehring (juergen.gehring@bmw.de) - * 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/. */ - -#if !defined (COMMONAPI_INTERNAL_COMPILATION) -#error "Only <CommonAPI/CommonAPI.h> can be included directly, this file may disappear or change contents." -#endif - -#ifndef COMMONAPI_DBUS_DBUS_PROXY_CONNECTION_H_ -#define COMMONAPI_DBUS_DBUS_PROXY_CONNECTION_H_ - -#include "DBusError.h" -#include "DBusMessage.h" - -#include "DBusFunctionalHash.h" - -#include <CommonAPI/types.h> -#include <CommonAPI/Attribute.h> -#include <CommonAPI/Event.h> - -#include <cstdint> -#include <functional> -#include <future> -#include <memory> -#include <tuple> -#include <unordered_map> -#include <utility> -#include <vector> - -namespace CommonAPI { -namespace DBus { - - -typedef std::function<void(const DBusMessage&)> DBusMessageHandler; - -class DBusDaemonProxy; -class DBusServiceRegistry; -class DBusObjectManager; -class DBusProxy; - - -class DBusProxyConnection { - public: - class DBusMessageReplyAsyncHandler { - public: - virtual ~DBusMessageReplyAsyncHandler() { } - virtual std::future<CallStatus> getFuture() = 0; - virtual void onDBusMessageReply(const CallStatus&, const DBusMessage&) = 0; - }; - - class DBusSignalHandler { - public: - virtual ~DBusSignalHandler() { } - virtual SubscriptionStatus onSignalDBusMessage(const DBusMessage&) = 0; - }; - - // objectPath, interfaceName, interfaceMemberName, interfaceMemberSignature - typedef std::tuple<std::string, std::string, std::string, std::string> DBusSignalHandlerPath; - typedef std::unordered_multimap<DBusSignalHandlerPath, DBusSignalHandler*> DBusSignalHandlerTable; - typedef DBusSignalHandlerPath DBusSignalHandlerToken; - - typedef Event<AvailabilityStatus> ConnectionStatusEvent; - - virtual ~DBusProxyConnection() { } - - virtual bool isConnected() const = 0; - - virtual ConnectionStatusEvent& getConnectionStatusEvent() = 0; - - virtual bool sendDBusMessage(const DBusMessage& dbusMessage, uint32_t* allocatedSerial = NULL) const = 0; - - static const int kDefaultSendTimeoutMs = 100 * 1000; - - virtual std::future<CallStatus> sendDBusMessageWithReplyAsync( - const DBusMessage& dbusMessage, - std::unique_ptr<DBusMessageReplyAsyncHandler> dbusMessageReplyAsyncHandler, - int timeoutMilliseconds = kDefaultSendTimeoutMs) const = 0; - - virtual DBusMessage sendDBusMessageWithReplyAndBlock( - const DBusMessage& dbusMessage, - DBusError& dbusError, - int timeoutMilliseconds = kDefaultSendTimeoutMs) const = 0; - - virtual DBusSignalHandlerToken addSignalMemberHandler( - const std::string& objectPath, - const std::string& interfaceName, - const std::string& interfaceMemberName, - const std::string& interfaceMemberSignature, - DBusSignalHandler* dbusSignalHandler, - const bool justAddFilter = false) = 0; - - virtual DBusSignalHandlerToken subscribeForSelectiveBroadcast(bool& subscriptionAccepted, - const std::string& objectPath, - const std::string& interfaceName, - const std::string& interfaceMemberName, - const std::string& interfaceMemberSignature, - DBusSignalHandler* dbusSignalHandler, - DBusProxy* callingProxy) = 0; - - virtual void unsubscribeFromSelectiveBroadcast(const std::string& eventName, - DBusProxyConnection::DBusSignalHandlerToken subscription, - DBusProxy* callingProxy, - const DBusSignalHandler* dbusSignalHandler) = 0; - - virtual bool removeSignalMemberHandler(const DBusSignalHandlerToken& dbusSignalHandlerToken, - const DBusSignalHandler* dbusSignalHandler = NULL) = 0; - - virtual bool addObjectManagerSignalMemberHandler(const std::string& dbusBusName, - DBusSignalHandler* dbusSignalHandler) = 0; - virtual bool removeObjectManagerSignalMemberHandler(const std::string& dbusBusName, - DBusSignalHandler* dbusSignalHandler) = 0; - - virtual const std::shared_ptr<DBusServiceRegistry> getDBusServiceRegistry() = 0; - virtual const std::shared_ptr<DBusObjectManager> getDBusObjectManager() = 0; - - virtual void registerObjectPath(const std::string& objectPath) = 0; - virtual void unregisterObjectPath(const std::string& objectPath) = 0; - - virtual bool requestServiceNameAndBlock(const std::string& serviceName) const = 0; - virtual bool releaseServiceName(const std::string& serviceName) const = 0; - - typedef std::function<bool(const DBusMessage&)> DBusObjectPathMessageHandler; - - virtual void setObjectPathMessageHandler(DBusObjectPathMessageHandler) = 0; - virtual bool isObjectPathMessageHandlerSet() = 0; -}; - - -} // namespace DBus -} // namespace CommonAPI - -#endif //COMMONAPI_DBUS_DBUS_PROXY_CONNECTION_H_ diff --git a/src/CommonAPI/DBus/DBusProxyHelper.h b/src/CommonAPI/DBus/DBusProxyHelper.h deleted file mode 100644 index 336810d..0000000 --- a/src/CommonAPI/DBus/DBusProxyHelper.h +++ /dev/null @@ -1,283 +0,0 @@ -/* Copyright (C) 2013 BMW Group - * Author: Manfred Bathelt (manfred.bathelt@bmw.de) - * Author: Juergen Gehring (juergen.gehring@bmw.de) - * 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/. */ - -#if !defined (COMMONAPI_INTERNAL_COMPILATION) -#error "Only <CommonAPI/CommonAPI.h> can be included directly, this file may disappear or change contents." -#endif - -#ifndef COMMONAPI_DBUS_DBUS_PROXY_HELPER_H_ -#define COMMONAPI_DBUS_DBUS_PROXY_HELPER_H_ - -#include "DBusMessage.h" -#include "DBusSerializableArguments.h" -#include "DBusProxyAsyncCallbackHandler.h" -#include "DBusProxyConnection.h" - -#include <functional> -#include <future> -#include <memory> -#include <string> - -namespace CommonAPI { -namespace DBus { - - -class DBusProxy; - - -template< class, class > -struct DBusProxyHelper; - -template< - template<class ...> class _In, class... _InArgs, - template <class...> class _Out, class... _OutArgs> - struct DBusProxyHelper<_In<_InArgs...>, _Out<_OutArgs...>> { - - template <typename _DBusProxy = DBusProxy> - static void callMethod(const _DBusProxy& dbusProxy, - const char* methodName, - const char* methodSignature, - const _InArgs&... inArgs, - CommonAPI::CallStatus& callStatus) { - - if (dbusProxy.isAvailableBlocking()) { - - DBusMessage dbusMessage = dbusProxy.createMethodCall(methodName, methodSignature); - - if (sizeof...(_InArgs) > 0) { - DBusOutputStream outputStream(dbusMessage); - const bool success = DBusSerializableArguments<_InArgs...>::serialize(outputStream,inArgs...); - if (!success) { - callStatus = CallStatus::OUT_OF_MEMORY; - return; - } - outputStream.flush(); - } - - const bool dbusMessageSent = dbusProxy.getDBusConnection()->sendDBusMessage(dbusMessage); - callStatus = dbusMessageSent ? CallStatus::SUCCESS : CallStatus::OUT_OF_MEMORY; - } else { - callStatus = CallStatus::NOT_AVAILABLE; - } - } - - template <typename _DBusProxy = DBusProxy> - static void callMethodWithReply( - const _DBusProxy& dbusProxy, - DBusMessage& dbusMethodCall, - const _InArgs&... inArgs, - CommonAPI::CallStatus& callStatus, - _OutArgs&... outArgs) { - - if (sizeof...(_InArgs) > 0) { - DBusOutputStream outputStream(dbusMethodCall); - const bool success = DBusSerializableArguments<_InArgs...>::serialize(outputStream, inArgs...); - if (!success) { - callStatus = CallStatus::OUT_OF_MEMORY; - return; - } - outputStream.flush(); - } - - DBusError dbusError; - DBusMessage dbusMessageReply = dbusProxy.getDBusConnection()->sendDBusMessageWithReplyAndBlock(dbusMethodCall, dbusError); - if (dbusError || !dbusMessageReply.isMethodReturnType()) { - callStatus = CallStatus::REMOTE_ERROR; - return; - } - - if (sizeof...(_OutArgs) > 0) { - DBusInputStream inputStream(dbusMessageReply); - const bool success = DBusSerializableArguments<_OutArgs...>::deserialize(inputStream, outArgs...); - if (!success) { - callStatus = CallStatus::REMOTE_ERROR; - return; - } - } - callStatus = CallStatus::SUCCESS; - } - - template <typename _DBusProxy = DBusProxy> - static void callMethodWithReply( - const _DBusProxy& dbusProxy, - const char* busName, - const char* objPath, - const char* interfaceName, - const char* methodName, - const char* methodSignature, - const _InArgs&... inArgs, - CommonAPI::CallStatus& callStatus, - _OutArgs&... outArgs) { - if (dbusProxy.isAvailableBlocking()) { - DBusMessage dbusMethodCall = DBusMessage::createMethodCall( - busName, - objPath, - interfaceName, - methodName, - methodSignature); - callMethodWithReply(dbusProxy, dbusMethodCall, inArgs..., callStatus, outArgs...); - } else { - callStatus = CallStatus::NOT_AVAILABLE; - } - } - - template <typename _DBusProxy = DBusProxy> - static void callMethodWithReply( - const _DBusProxy& dbusProxy, - const char* dbusInterfaceName, - const char* methodName, - const char* methodSignature, - const _InArgs&... inArgs, - CommonAPI::CallStatus& callStatus, - _OutArgs&... outArgs) { - callMethodWithReply( - dbusProxy, - dbusProxy.getDBusBusName().c_str(), - dbusProxy.getDBusObjectPath().c_str(), - dbusInterfaceName, - methodName, - methodSignature, - inArgs..., - callStatus, - outArgs...); - } - - template <typename _DBusProxy = DBusProxy> - static void callMethodWithReply( - const _DBusProxy& dbusProxy, - const char* methodName, - const char* methodSignature, - const _InArgs&... inArgs, - CommonAPI::CallStatus& callStatus, - _OutArgs&... outArgs) { - - if (dbusProxy.isAvailableBlocking()) { - - DBusMessage dbusMethodCall = dbusProxy.createMethodCall(methodName, methodSignature); - - callMethodWithReply(dbusProxy, dbusMethodCall, inArgs..., callStatus, outArgs...); - - } else { - callStatus = CallStatus::NOT_AVAILABLE; - } - } - - template <typename _DBusProxy = DBusProxy, typename _AsyncCallback> - static std::future<CallStatus> callMethodAsync( - const _DBusProxy& dbusProxy, - const char* methodName, - const char* methodSignature, - const _InArgs&... inArgs, - _AsyncCallback asyncCallback) { - if (dbusProxy.isAvailable()) { - DBusMessage dbusMethodCall = dbusProxy.createMethodCall(methodName, methodSignature); - - return callMethodAsync(dbusProxy, dbusMethodCall, inArgs..., asyncCallback); - - } else { - - CallStatus callStatus = CallStatus::NOT_AVAILABLE; - - std::tuple<_OutArgs...> argTuple; - callCallbackOnNotAvailable(asyncCallback, typename make_sequence<sizeof...(_OutArgs)>::type(), argTuple); - - std::promise<CallStatus> promise; - promise.set_value(callStatus); - return promise.get_future(); - } - - } - - template <typename _DBusProxy = DBusProxy, typename _AsyncCallback> - static std::future<CallStatus> callMethodAsync( - const _DBusProxy& dbusProxy, - const char* dbusInterfaceName, - const char* methodName, - const char* methodSignature, - const _InArgs&... inArgs, - _AsyncCallback asyncCallback) { - - return callMethodAsync( - dbusProxy, - dbusProxy.getDBusBusName().c_str(), - dbusProxy.getDBusObjectPath().c_str(), - dbusInterfaceName, - methodName, - methodSignature, - inArgs..., - asyncCallback); - } - - template <typename _DBusProxy = DBusProxy, typename _AsyncCallback> - static std::future<CallStatus> callMethodAsync( - const _DBusProxy& dbusProxy, - const char* busName, - const char* objPath, - const char* interfaceName, - const char* methodName, - const char* methodSignature, - const _InArgs&... inArgs, - _AsyncCallback asyncCallback) { - if (dbusProxy.isAvailable()) { - DBusMessage dbusMethodCall = DBusMessage::createMethodCall( - busName, - objPath, - interfaceName, - methodName, - methodSignature); - return callMethodAsync(dbusProxy, dbusMethodCall, inArgs..., asyncCallback); - } else { - - CallStatus callStatus = CallStatus::NOT_AVAILABLE; - - std::tuple<_OutArgs...> argTuple; - callCallbackOnNotAvailable(asyncCallback, typename make_sequence<sizeof...(_OutArgs)>::type(),argTuple); - - std::promise<CallStatus> promise; - promise.set_value(callStatus); - return promise.get_future(); - } - } - - - template <typename _DBusProxy = DBusProxy, typename _AsyncCallback> - static std::future<CallStatus> callMethodAsync( - const _DBusProxy& dbusProxy, - DBusMessage& dbusMessage, - const _InArgs&... inArgs, - _AsyncCallback asyncCallback) { - - if (sizeof...(_InArgs) > 0) { - DBusOutputStream outputStream(dbusMessage); - const bool success = DBusSerializableArguments<_InArgs...>::serialize(outputStream, inArgs...); - if (!success) { - std::promise<CallStatus> promise; - promise.set_value(CallStatus::OUT_OF_MEMORY); - return promise.get_future(); - } - outputStream.flush(); - } - - return dbusProxy.getDBusConnection()->sendDBusMessageWithReplyAsync( - dbusMessage, - DBusProxyAsyncCallbackHandler<_OutArgs...>::create(std::move(asyncCallback))); - - } - - template <int... _ArgIndices> - static void callCallbackOnNotAvailable(std::function<void(CallStatus, _OutArgs...)> callback, - index_sequence<_ArgIndices...>, std::tuple<_OutArgs...> argTuple) { - - const CallStatus callstatus = CallStatus::NOT_AVAILABLE; - callback(callstatus, std::move(std::get<_ArgIndices>(argTuple))...); - } -}; - -} // namespace DBus -} // namespace CommonAPI - -#endif // COMMONAPI_DBUS_DBUS_PROXY_HELPER_H_ diff --git a/src/CommonAPI/DBus/DBusProxyManager.cpp b/src/CommonAPI/DBus/DBusProxyManager.cpp index abbc491..5a69083 100644 --- a/src/CommonAPI/DBus/DBusProxyManager.cpp +++ b/src/CommonAPI/DBus/DBusProxyManager.cpp @@ -1,152 +1,177 @@ -/* Copyright (C) 2013 BMW Group - * Author: Manfred Bathelt (manfred.bathelt@bmw.de) - * Author: Juergen Gehring (juergen.gehring@bmw.de) - * 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 "DBusProxyManager.h" -#include "DBusAddressTranslator.h" +// 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/. +#include <CommonAPI/Runtime.hpp> +#include <CommonAPI/DBus/DBusAddressTranslator.hpp> +#include <CommonAPI/DBus/DBusProxyManager.hpp> namespace CommonAPI { namespace DBus { +DBusProxyManager::DBusProxyManager( + DBusProxy &_proxy, + const std::string &_interfaceId) + : proxy_(_proxy), + instanceAvailabilityStatusEvent_(_proxy, _interfaceId), + interfaceId_(_interfaceId), + registry_(DBusServiceRegistry::get(_proxy.getDBusConnection())) +{ +} -DBusProxyManager::DBusProxyManager(DBusProxy& dbusProxy, - const std::string& interfaceId, - const std::shared_ptr<DBusFactory> factory) : - dbusProxy_(dbusProxy), - dbusInstanceAvailabilityStatusEvent_(dbusProxy, interfaceId), - factory_(factory), - registry_(dbusProxy.getDBusConnection()->getDBusServiceRegistry()), - interfaceId_(interfaceId) - -{ } - -void DBusProxyManager::instancesAsyncCallback(const CommonAPI::CallStatus& status, - const DBusObjectManagerStub::DBusObjectPathAndInterfacesDict& dict, - GetAvailableInstancesCallback& call) { - std::vector<std::string> returnVec; - if (status == CommonAPI::CallStatus::SUCCESS) { - translateCommonApiAddresses(dict, returnVec); - } - call(status, returnVec); +const std::string & +DBusProxyManager::getDomain() const { + static std::string domain("local"); + return domain; } -void DBusProxyManager::getAvailableInstances(CommonAPI::CallStatus& callStatus, std::vector<std::string>& availableInstances) { - DBusObjectManagerStub::DBusObjectPathAndInterfacesDict dbusObjectPathAndInterfacesDict; +const std::string & +DBusProxyManager::getInterface() const { + return interfaceId_; +} - DBusProxyHelper<DBusSerializableArguments<>, - DBusSerializableArguments<DBusObjectManagerStub::DBusObjectPathAndInterfacesDict> >::callMethodWithReply( - dbusProxy_, - DBusObjectManagerStub::getInterfaceName(), - "GetManagedObjects", - "", - callStatus, - dbusObjectPathAndInterfacesDict); +const ConnectionId_t & +DBusProxyManager::getConnectionId() const { + return connectionId_; +} - if (callStatus == CallStatus::SUCCESS) { - translateCommonApiAddresses(dbusObjectPathAndInterfacesDict, availableInstances); +void +DBusProxyManager::instancesAsyncCallback( + const CommonAPI::CallStatus &_status, + const DBusObjectManagerStub::DBusObjectPathAndInterfacesDict &_dict, + GetAvailableInstancesCallback &_call) { + std::vector<std::string> result; + if (_status == CommonAPI::CallStatus::SUCCESS) { + translateCommonApiAddresses(_dict, result); } + _call(_status, result); } -std::future<CallStatus> DBusProxyManager::getAvailableInstancesAsync(GetAvailableInstancesCallback callback) { - return CommonAPI::DBus::DBusProxyHelper<CommonAPI::DBus::DBusSerializableArguments<>, - CommonAPI::DBus::DBusSerializableArguments< - DBusObjectManagerStub::DBusObjectPathAndInterfacesDict> >::callMethodAsync( - dbusProxy_, - DBusObjectManagerStub::getInterfaceName(), - "GetManagedObjects", - "a{oa{sa{sv}}}", - std::move( - std::bind( - &DBusProxyManager::instancesAsyncCallback, - this, - std::placeholders::_1, - std::placeholders::_2, - callback))); +void +DBusProxyManager::getAvailableInstances( + CommonAPI::CallStatus &_status, + std::vector<std::string> &_availableInstances) { + DBusObjectManagerStub::DBusObjectPathAndInterfacesDict dict; + + DBusProxyHelper< + DBusSerializableArguments<>, + DBusSerializableArguments< + DBusObjectManagerStub::DBusObjectPathAndInterfacesDict + > + >::callMethodWithReply(proxy_, + DBusObjectManagerStub::getInterfaceName(), + "GetManagedObjects", + "", + &defaultCallInfo, + _status, + dict); + + if (_status == CallStatus::SUCCESS) { + translateCommonApiAddresses(dict, _availableInstances); + } +} +std::future<CallStatus> +DBusProxyManager::getAvailableInstancesAsync( + 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>()); } -void DBusProxyManager::getInstanceAvailabilityStatus(const std::string& instanceAddress, - CallStatus& callStatus, - AvailabilityStatus& availabilityStatus) { - - std::stringstream ss; - ss << "local:" << interfaceId_ << ":" << instanceAddress; - - std::string interfaceName; - std::string connectionName; - std::string objectPath; - DBusAddressTranslator::getInstance().searchForDBusAddress( - ss.str(), - interfaceName, - connectionName, - objectPath); - availabilityStatus = AvailabilityStatus::NOT_AVAILABLE; - if (registry_->isServiceInstanceAlive(interfaceName, connectionName, objectPath)) { - availabilityStatus = AvailabilityStatus::AVAILABLE; +void +DBusProxyManager::getInstanceAvailabilityStatus( + const std::string &_address, + CallStatus &_callStatus, + AvailabilityStatus &_availabilityStatus) { + + CommonAPI::Address itsAddress("local", interfaceId_, _address); + DBusAddress itsDBusAddress; + DBusAddressTranslator::get()->translate(itsAddress, itsDBusAddress); + + _availabilityStatus = AvailabilityStatus::NOT_AVAILABLE; + if (registry_->isServiceInstanceAlive( + itsDBusAddress.getInterface(), + itsDBusAddress.getService(), + itsDBusAddress.getObjectPath())) { + _availabilityStatus = AvailabilityStatus::AVAILABLE; } - callStatus = CallStatus::SUCCESS; + _callStatus = CallStatus::SUCCESS; } -SubscriptionStatus DBusProxyManager::instanceAliveAsyncCallback(const AvailabilityStatus& alive, GetInstanceAvailabilityStatusCallback& call, std::shared_ptr<std::promise<CallStatus> >& callStatus) { - call(CallStatus::SUCCESS, alive); - callStatus->set_value(CallStatus::SUCCESS); - return SubscriptionStatus::CANCEL; +void +DBusProxyManager::instanceAliveAsyncCallback( + 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& instanceAddress, - GetInstanceAvailabilityStatusCallback callback) { - std::stringstream ss; - ss << "local:" << interfaceId_ << ":" << instanceAddress; +std::future<CallStatus> +DBusProxyManager::getInstanceAvailabilityStatusAsync( + const std::string &_instance, + GetInstanceAvailabilityStatusCallback _callback) { + CommonAPI::Address itsAddress("local", interfaceId_, _instance); std::shared_ptr<std::promise<CallStatus> > promise = std::make_shared<std::promise<CallStatus>>(); registry_->subscribeAvailabilityListener( - ss.str(), + itsAddress.getAddress(), std::bind(&DBusProxyManager::instanceAliveAsyncCallback, this, std::placeholders::_1, - callback, + _callback, promise) ); return promise->get_future(); } -DBusProxyManager::InstanceAvailabilityStatusChangedEvent& DBusProxyManager::getInstanceAvailabilityStatusChangedEvent() { - return dbusInstanceAvailabilityStatusEvent_; +DBusProxyManager::InstanceAvailabilityStatusChangedEvent & +DBusProxyManager::getInstanceAvailabilityStatusChangedEvent() { + return instanceAvailabilityStatusEvent_; } -void DBusProxyManager::translateCommonApiAddresses(const DBusObjectManagerStub::DBusObjectPathAndInterfacesDict& dbusObjectPathAndInterfacesDict, - std::vector<std::string>& instanceIds) { - for (const auto& dbusObjectPathIter : dbusObjectPathAndInterfacesDict) { - const std::string& dbusObjectPath = dbusObjectPathIter.first; - const auto& dbusInterfacesDict = dbusObjectPathIter.second; +void +DBusProxyManager::translateCommonApiAddresses( + const DBusObjectManagerStub::DBusObjectPathAndInterfacesDict &_dict, + std::vector<std::string> &_instances) { + + CommonAPI::Address itsAddress; + DBusAddress itsDBusAddress; - for (const auto& dbusInterfaceIter : dbusInterfacesDict) { - const std::string dbusInterfaceName = dbusInterfaceIter.first; - std::string instanceId; + for (const auto &objectPathIter : _dict) { + itsDBusAddress.setObjectPath(objectPathIter.first); - DBusAddressTranslator::getInstance().searchForCommonAddress( - dbusInterfaceName, - dbusProxy_.getDBusBusName(), - dbusObjectPath, - instanceId); + const auto &interfacesDict = objectPathIter.second; + for (const auto &interfaceIter : interfacesDict) { + itsDBusAddress.setInterface(interfaceIter.first); - auto pos = instanceId.find_last_of(':'); - instanceId = instanceId.substr(pos + 1, instanceId.size()); + DBusAddressTranslator::get()->translate(itsDBusAddress, itsAddress); - instanceIds.push_back(instanceId); + _instances.push_back(itsAddress.getInstance()); } } } -std::shared_ptr<Proxy> DBusProxyManager::createProxy(const std::string& instanceId) { - return factory_->createProxy(interfaceId_.c_str(), instanceId, interfaceId_, "local"); -} - - } // namespace DBus }// namespace CommonAPI diff --git a/src/CommonAPI/DBus/DBusProxyManager.h b/src/CommonAPI/DBus/DBusProxyManager.h deleted file mode 100644 index 73f612f..0000000 --- a/src/CommonAPI/DBus/DBusProxyManager.h +++ /dev/null @@ -1,74 +0,0 @@ -/* Copyright (C) 2013 BMW Group - * Author: Manfred Bathelt (manfred.bathelt@bmw.de) - * Author: Juergen Gehring (juergen.gehring@bmw.de) - * 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/. */ - -#if !defined (COMMONAPI_INTERNAL_COMPILATION) -#error "Only <CommonAPI/CommonAPI.h> can be included directly, this file may disappear or change contents." -#endif - -#ifndef COMMONAPI_DBUS_DBUS_PROXY_MANAGER_H_ -#define COMMONAPI_DBUS_DBUS_PROXY_MANAGER_H_ - -#include <CommonAPI/ProxyManager.h> - -#include "DBusProxy.h" -#include "DBusFactory.h" -#include "DBusObjectManagerStub.h" -#include "DBusInstanceAvailabilityStatusChangedEvent.h" - -#include <functional> -#include <future> -#include <string> -#include <vector> - - -namespace CommonAPI { -namespace DBus { - -class DBusProxyManager: public ProxyManager { - public: - DBusProxyManager(DBusProxy& dbusProxy, - const std::string& interfaceName, - const std::shared_ptr<DBusFactory> factory); - - virtual void getAvailableInstances(CommonAPI::CallStatus&, std::vector<std::string>& availableInstances); - virtual std::future<CallStatus> getAvailableInstancesAsync(GetAvailableInstancesCallback callback); - - virtual void getInstanceAvailabilityStatus(const std::string& instanceAddress, - CallStatus& callStatus, - AvailabilityStatus& availabilityStatus); - - virtual std::future<CallStatus> getInstanceAvailabilityStatusAsync(const std::string&, - GetInstanceAvailabilityStatusCallback callback); - - virtual InstanceAvailabilityStatusChangedEvent& getInstanceAvailabilityStatusChangedEvent(); - protected: - virtual std::shared_ptr<Proxy> createProxy(const std::string& instanceId); - private: - - void instancesAsyncCallback(const CommonAPI::CallStatus& status, - const DBusObjectManagerStub::DBusObjectPathAndInterfacesDict& dict, - GetAvailableInstancesCallback& call); - - SubscriptionStatus instanceAliveAsyncCallback(const AvailabilityStatus& alive, - GetInstanceAvailabilityStatusCallback& call, - std::shared_ptr<std::promise<CallStatus> >& callStatus); - - void translateCommonApiAddresses(const DBusObjectManagerStub::DBusObjectPathAndInterfacesDict& dbusObjectPathAndInterfacesDict, - std::vector<std::string>& instanceIds); - - DBusProxy& dbusProxy_; - DBusInstanceAvailabilityStatusChangedEvent dbusInstanceAvailabilityStatusEvent_; - const std::shared_ptr<DBusFactory> factory_; - const std::shared_ptr<DBusServiceRegistry> registry_; - - const std::string interfaceId_; -}; - -} // namespace DBus -} // namespace CommonAPI - -#endif // COMMONAPI_DBUS_DBUS_PROXY_MANAGER_H_ diff --git a/src/CommonAPI/DBus/DBusRuntime.cpp b/src/CommonAPI/DBus/DBusRuntime.cpp deleted file mode 100644 index bddd91b..0000000 --- a/src/CommonAPI/DBus/DBusRuntime.cpp +++ /dev/null @@ -1,86 +0,0 @@ -/* Copyright (C) 2013 BMW Group - * Author: Manfred Bathelt (manfred.bathelt@bmw.de) - * Author: Juergen Gehring (juergen.gehring@bmw.de) - * 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/Configuration.h> -#include <CommonAPI/utils.h> - -#include "DBusRuntime.h" -#include "DBusAddressTranslator.h" - - -const char middlewareIdentifier[] = "DBus"; - -namespace CommonAPI { -namespace DBus { - -INITIALIZER(registerDBusMiddleware) { - Runtime::registerRuntimeLoader(middlewareIdentifier, &DBusRuntime::getInstance); -} - -const CommonAPI::MiddlewareInfo DBusRuntime::middlewareInfo_(middlewareIdentifier, - &CommonAPI::DBus::DBusRuntime::getInstance, - {COMMONAPI_DBUS_VERSION_MAJOR, - COMMONAPI_DBUS_VERSION_MINOR} -); - - - - -std::shared_ptr<Runtime> DBusRuntime::getInstance() { - static std::shared_ptr<Runtime> dbusRuntimeSingleton_; - if (!dbusRuntimeSingleton_) { - dbusRuntimeSingleton_ = std::make_shared<DBusRuntime>(); -#ifndef WIN32 - for (const auto& genericLibraryPath : Configuration::getInstance().getGenericLibraryPaths(middlewareIdentifier)) { - if (!loadGenericLibrary(middlewareIdentifier, genericLibraryPath, false)) { - return std::shared_ptr<Runtime>(NULL); - } - } - findAndLoadGenericLibraries(middlewareIdentifier, Configuration::getInstance().getLibrarySearchPaths()); -#endif - } - return dbusRuntimeSingleton_; -} - - -std::shared_ptr<Factory> DBusRuntime::doCreateFactory(std::shared_ptr<MainLoopContext> mainLoopContext, - const std::string& factoryName, - const bool nullOnInvalidName) { - auto factory = std::shared_ptr<DBusFactory>(NULL); - - if (factoryName == "") { - factory = std::make_shared<DBusFactory>(this->shared_from_this(), &middlewareInfo_, mainLoopContext); - } else { - const DBusFactoryConfig* dbusFactoryConfig = DBusConfiguration::getInstance().getFactoryConfiguration(factoryName); - - if (dbusFactoryConfig == NULL) { - if (nullOnInvalidName) { - return std::shared_ptr<Factory>(NULL); - } else { - dbusFactoryConfig = new DBusFactoryConfig(); - } - } - - factory = std::make_shared<DBusFactory>( - this->shared_from_this(), - &middlewareInfo_, - mainLoopContext, - *dbusFactoryConfig); - } - - return factory; -} - -std::shared_ptr<ServicePublisher> DBusRuntime::getServicePublisher() { - return DBusServicePublisher::getInstance(); -} - -} // namespace DBus -} // namespace CommonAPI - -extern "C" { - CommonAPI::MiddlewareInfo middlewareInfo = CommonAPI::DBus::DBusRuntime::middlewareInfo_; -} diff --git a/src/CommonAPI/DBus/DBusRuntime.h b/src/CommonAPI/DBus/DBusRuntime.h deleted file mode 100644 index ee7e689..0000000 --- a/src/CommonAPI/DBus/DBusRuntime.h +++ /dev/null @@ -1,39 +0,0 @@ -/* Copyright (C) 2013 BMW Group - * Author: Manfred Bathelt (manfred.bathelt@bmw.de) - * Author: Juergen Gehring (juergen.gehring@bmw.de) - * 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/. */ - -#if !defined (COMMONAPI_INTERNAL_COMPILATION) -#error "Only <CommonAPI/CommonAPI.h> can be included directly, this file may disappear or change contents." -#endif - -#ifndef COMMONAPI_DBUS_DBUS_RUNTIME_H_ -#define COMMONAPI_DBUS_DBUS_RUNTIME_H_ - -#include "CommonAPI/Runtime.h" - -#include "DBusFactory.h" -#include "DBusServicePublisher.h" - -namespace CommonAPI { -namespace DBus { - -class DBusRuntime: public Runtime, public std::enable_shared_from_this<DBusRuntime> { -public: - static std::shared_ptr<Runtime> getInstance(); - std::shared_ptr<ServicePublisher> getServicePublisher(); - static const MiddlewareInfo middlewareInfo_; -protected: - std::shared_ptr<Factory> doCreateFactory(std::shared_ptr<MainLoopContext> mainLoopContext, - const std::string& factoryName, - const bool nullOnInvalidName); -private: - static std::unordered_map<std::string, DBusRuntime> registeredRuntimes; -}; - -} // namespace DBus -} // namespace CommonAPI - -#endif // COMMONAPI_DBUS_DBUS_RUNTIME_H_ diff --git a/src/CommonAPI/DBus/DBusSelectiveEvent.h b/src/CommonAPI/DBus/DBusSelectiveEvent.h deleted file mode 100644 index 313ad9c..0000000 --- a/src/CommonAPI/DBus/DBusSelectiveEvent.h +++ /dev/null @@ -1,101 +0,0 @@ -/* Copyright (C) 2013 BMW Group - * Author: Manfred Bathelt (manfred.bathelt@bmw.de) - * Author: Juergen Gehring (juergen.gehring@bmw.de) - * 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/. */ - -#if !defined (COMMONAPI_INTERNAL_COMPILATION) -#error "Only <CommonAPI/CommonAPI.h> can be included directly, this file may disappear or change contents." -#endif - -#ifndef COMMONAPI_DBUS_DBUS_SELECTIVE_EVENT_H_ -#define COMMONAPI_DBUS_DBUS_SELECTIVE_EVENT_H_ - -#include "DBusEvent.h" - -namespace CommonAPI { -namespace DBus { - -template<typename _EventType, typename _DBusProxy = DBusProxyBase> -class DBusSelectiveEvent: public DBusEvent<_EventType, _DBusProxy> { -public: - typedef typename DBusEvent<_EventType, _DBusProxy>::CancellableListener CancellableListener; - typedef DBusEvent<_EventType, _DBusProxy> DBusEventBase; - - DBusSelectiveEvent(DBusProxy& associatedDbusProxy, - const char* eventName, - const char* eventSignature) : - DBusEventBase(associatedDbusProxy, eventName, eventSignature), - associatedDbusProxy_(associatedDbusProxy) { - } - - DBusSelectiveEvent(DBusProxy& associatedDbusProxy, const char* eventName, - const char* eventSignature, - const char* objPath, - const char* interfaceName) : - - DBusEvent<_EventType, _DBusProxy>( - associatedDbusProxy, - eventName, - eventSignature, - objPath, - interfaceName), - associatedDbusProxy_(associatedDbusProxy) { - } - - virtual ~DBusSelectiveEvent() { } - - typename _EventType::Subscription subscribe(typename _EventType::Listener listener, bool& success) { - - DBusEventBase::listenerListMutex_.lock(); - const bool firstListenerAdded = DBusEventBase::listenersList_.empty(); - - typename _EventType::CancellableListenerWrapper wrappedListener(std::move(listener)); - DBusEventBase::listenersList_.emplace_front(std::move(wrappedListener)); - typename _EventType::Subscription listenerSubscription = DBusEventBase::listenersList_.begin(); - - success = true; - DBusProxyConnection::DBusSignalHandlerToken dbusSignalHandlerToken; - - if (firstListenerAdded) { - dbusSignalHandlerToken = associatedDbusProxy_.subscribeForSelectiveBroadcastOnConnection( - success, - DBusEventBase::objectPath_, - DBusEventBase::interfaceName_, - DBusEventBase::eventName_, - DBusEventBase::eventSignature_, - this - ); - } - - if (success) { - // actually add subscription - DBusEventBase::subscription_ = dbusSignalHandlerToken; - this->onListenerAdded(*listenerSubscription); - } - else { - DBusEventBase::listenersList_.erase(listenerSubscription); - listenerSubscription = DBusEventBase::listenersList_.end(); - } - DBusEventBase::listenerListMutex_.unlock(); - - return listenerSubscription; - } - -protected: - virtual void onLastListenerRemoved(const CancellableListener&) { - associatedDbusProxy_.unsubscribeFromSelectiveBroadcast( - DBusEventBase::eventName_, - DBusEventBase::subscription_, - this); - } - -private: - DBusProxy& associatedDbusProxy_; -}; - -} // namespace DBus -} // namespace CommonAPI - -#endif // COMMONAPI_DBUS_DBUS_SELECTIVE_EVENT_H_ diff --git a/src/CommonAPI/DBus/DBusSerializableArguments.h b/src/CommonAPI/DBus/DBusSerializableArguments.h deleted file mode 100644 index e859602..0000000 --- a/src/CommonAPI/DBus/DBusSerializableArguments.h +++ /dev/null @@ -1,66 +0,0 @@ -/* Copyright (C) 2013 BMW Group - * Author: Manfred Bathelt (manfred.bathelt@bmw.de) - * Author: Juergen Gehring (juergen.gehring@bmw.de) - * 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/. */ - -#if !defined (COMMONAPI_INTERNAL_COMPILATION) -#error "Only <CommonAPI/CommonAPI.h> can be included directly, this file may disappear or change contents." -#endif - -#ifndef COMMONAPI_DBUS_SERIALIZABLE_ARGUMENTS_H_ -#define COMMONAPI_DBUS_SERIALIZABLE_ARGUMENTS_H_ - -#include "DBusInputStream.h" -#include "DBusOutputStream.h" - -namespace CommonAPI { -namespace DBus { - -template <typename... _Arguments> -struct DBusSerializableArguments; - -template <> -struct DBusSerializableArguments<> { - static bool serialize(OutputStream& outputStream) { - return true; - } - - static bool deserialize(DBusInputStream& inputStream) { - return true; - } -}; - -template <typename _ArgumentType> -struct DBusSerializableArguments<_ArgumentType> { - static bool serialize(OutputStream& outputStream, const _ArgumentType& argument) { - outputStream << argument; - return !outputStream.hasError(); - } - - static bool deserialize(DBusInputStream& inputStream, _ArgumentType& argument) { - inputStream >> argument; - return !inputStream.hasError(); - } -}; - -template <typename _ArgumentType, typename ... _Rest> -struct DBusSerializableArguments<_ArgumentType, _Rest...> { - static bool serialize(OutputStream& outputStream, const _ArgumentType& argument, const _Rest&... rest) { - outputStream << argument; - const bool success = !outputStream.hasError(); - return success ? DBusSerializableArguments<_Rest...>::serialize(outputStream, rest...) : false; - } - - static bool deserialize(DBusInputStream& inputStream, _ArgumentType& argument, _Rest&... rest) { - inputStream >> argument; - const bool success = !inputStream.hasError(); - return success ? DBusSerializableArguments<_Rest...>::deserialize(inputStream, rest...) : false; - } -}; - -} // namespace DBus -} // namespace CommonAPI - -#endif // COMMONAPI_DBUS_SERIALIZABLE_ARGUMENTS_H_ diff --git a/src/CommonAPI/DBus/DBusServicePublisher.cpp b/src/CommonAPI/DBus/DBusServicePublisher.cpp deleted file mode 100644 index 6f6a4c7..0000000 --- a/src/CommonAPI/DBus/DBusServicePublisher.cpp +++ /dev/null @@ -1,155 +0,0 @@ -/* Copyright (C) 2013 BMW Group - * Author: Manfred Bathelt (manfred.bathelt@bmw.de) - * Author: Juergen Gehring (juergen.gehring@bmw.de) - * 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 "DBusServicePublisher.h" -#include "DBusFactory.h" - -#include <cassert> - - -namespace CommonAPI { -namespace DBus { - - -std::shared_ptr<DBusServicePublisher> DBusServicePublisher::getInstance() { - static std::shared_ptr<DBusServicePublisher> instance; - if(!instance) { - instance = std::make_shared<DBusServicePublisher>(); - } - return instance; -} - -bool DBusServicePublisher::registerService(const std::shared_ptr<DBusStubAdapter>& dbusStubAdapter) { - auto serviceAddress = dbusStubAdapter->getAddress(); - const auto& dbusConnection = dbusStubAdapter->getDBusConnection(); - std::shared_ptr<DBusObjectManagerStub> rootDBusObjectManagerStub = dbusConnection->getDBusObjectManager()->getRootDBusObjectManagerStub(); - const bool isRegistrationAtManagerSuccessfull = registerManagedService(dbusStubAdapter); - - if (!isRegistrationAtManagerSuccessfull) { - return false; - } - - const bool isServiceExportSuccessful = rootDBusObjectManagerStub->exportManagedDBusStubAdapter(dbusStubAdapter); - if (!isServiceExportSuccessful) { - const bool isManagedDeregistrationSuccessfull = unregisterManagedService(serviceAddress); - assert(isManagedDeregistrationSuccessfull); - } - - return isServiceExportSuccessful; -} - -std::shared_ptr<DBusStubAdapter> DBusServicePublisher::getRegisteredService(const std::string& serviceAddress) { - auto registeredServiceIterator = registeredServices_.find(serviceAddress); - if (registeredServiceIterator != registeredServices_.end()) { - return registeredServiceIterator->second; - } - return nullptr; -} - -bool DBusServicePublisher::registerService(const std::shared_ptr<StubBase>& stubBase, - const char* interfaceId, - const std::string& participantId, - const std::string& serviceName, - const std::string& domain, - const std::shared_ptr<Factory>& factory) { - auto dbusFactory = std::dynamic_pointer_cast<DBusFactory>(factory); - if (!dbusFactory) { - return false; - } - - auto dbusStubAdapter = dbusFactory->createDBusStubAdapter(stubBase, interfaceId, participantId, serviceName, domain); - if (!dbusStubAdapter) { - return false; - } - - const bool isRegistrationSuccessful = registerService(dbusStubAdapter); - return isRegistrationSuccessful; -} - - -bool DBusServicePublisher::unregisterService(const std::string& serviceAddress) { - auto registeredServiceIterator = registeredServices_.find(serviceAddress); - const bool isServiceAddressRegistered = (registeredServiceIterator != registeredServices_.end()); - - if (!isServiceAddressRegistered) { - return false; - } - - const auto& registeredDBusStubAdapter = registeredServiceIterator->second; - const auto& dbusConnection = registeredDBusStubAdapter->getDBusConnection(); - std::shared_ptr<DBusObjectManagerStub> rootDBusObjectManagerStub = dbusConnection->getDBusObjectManager()->getRootDBusObjectManagerStub(); - const bool isRootService = rootDBusObjectManagerStub->isDBusStubAdapterExported(registeredDBusStubAdapter); - registeredDBusStubAdapter->deactivateManagedInstances(); - if (isRootService) { - const bool isUnexportSuccessfull = rootDBusObjectManagerStub->unexportManagedDBusStubAdapter(registeredDBusStubAdapter); - assert(isUnexportSuccessfull); - - unregisterManagedService(registeredServiceIterator); - } - - return isRootService; -} - - -bool DBusServicePublisher::registerManagedService(const std::shared_ptr<DBusStubAdapter>& managedDBusStubAdapter) { - auto serviceAddress = managedDBusStubAdapter->getAddress(); - const auto& insertResult = registeredServices_.insert( {serviceAddress, managedDBusStubAdapter} ); - const auto& insertIter = insertResult.first; - const bool& isInsertSuccessful = insertResult.second; - - if (!isInsertSuccessful) { - return false; - } - - const auto& dbusConnection = managedDBusStubAdapter->getDBusConnection(); - const auto dbusObjectManager = dbusConnection->getDBusObjectManager(); - const bool isDBusObjectRegistrationSuccessful = dbusObjectManager->registerDBusStubAdapter(managedDBusStubAdapter); - if (!isDBusObjectRegistrationSuccessful) { - registeredServices_.erase(insertIter); - return false; - } - - const auto& dbusServiceName = managedDBusStubAdapter->getDBusName(); - const bool isServiceNameAcquired = dbusConnection->requestServiceNameAndBlock(dbusServiceName); - if (!isServiceNameAcquired) { - const bool isDBusObjectDeregistrationSuccessful = dbusObjectManager->unregisterDBusStubAdapter(managedDBusStubAdapter); - assert(isDBusObjectDeregistrationSuccessful); - - registeredServices_.erase(insertIter); - } - - return isServiceNameAcquired; -} - - -bool DBusServicePublisher::unregisterManagedService(const std::string& serviceAddress) { - auto registeredServiceIterator = registeredServices_.find(serviceAddress); - const bool isServiceAddressRegistered = (registeredServiceIterator != registeredServices_.end()); - - if (isServiceAddressRegistered) { - unregisterManagedService(registeredServiceIterator); - } - - return isServiceAddressRegistered; -} - -void DBusServicePublisher::unregisterManagedService(DBusServicesMap::iterator& managedServiceIterator) { - const auto& registeredDbusStubAdapter = managedServiceIterator->second; - const auto& dbusConnection = registeredDbusStubAdapter->getDBusConnection(); - const auto dbusObjectManager = dbusConnection->getDBusObjectManager(); - const auto& dbusServiceName = registeredDbusStubAdapter->getDBusName(); - - const bool isDBusStubAdapterUnregistered = dbusObjectManager->unregisterDBusStubAdapter(registeredDbusStubAdapter); - assert(isDBusStubAdapterUnregistered); - - dbusConnection->releaseServiceName(dbusServiceName); - - registeredServices_.erase(managedServiceIterator); -} - -} // namespace DBus -} // namespace CommonAPI diff --git a/src/CommonAPI/DBus/DBusServicePublisher.h b/src/CommonAPI/DBus/DBusServicePublisher.h deleted file mode 100644 index 7df44d7..0000000 --- a/src/CommonAPI/DBus/DBusServicePublisher.h +++ /dev/null @@ -1,61 +0,0 @@ -/* Copyright (C) 2013 BMW Group - * Author: Manfred Bathelt (manfred.bathelt@bmw.de) - * Author: Juergen Gehring (juergen.gehring@bmw.de) - * 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/. */ - -#if !defined (COMMONAPI_INTERNAL_COMPILATION) -#error "Only <CommonAPI/CommonAPI.h> can be included directly, this file may disappear or change contents." -#endif - -#ifndef COMMONAPI_DBUS_DBUS_SERVICE_PUBLISHER_H_ -#define COMMONAPI_DBUS_DBUS_SERVICE_PUBLISHER_H_ - - -#include <CommonAPI/ServicePublisher.h> -#include "DBusStubAdapter.h" - - -namespace CommonAPI { -namespace DBus { - -class DBusFactory; -class DBusObjectManagerStub; - -class DBusServicePublisher: public ServicePublisher { - public: - DBusServicePublisher() {} - - static std::shared_ptr<DBusServicePublisher> getInstance(); - - bool registerService(const std::shared_ptr<DBusStubAdapter>& dbusStubAdapter); - virtual bool unregisterService(const std::string& serviceAddress); - - bool registerManagedService(const std::shared_ptr<DBusStubAdapter>& managedDBusStubAdapter); - bool unregisterManagedService(const std::string& serviceAddress); - - std::shared_ptr<DBusStubAdapter> getRegisteredService(const std::string&); - - protected: - virtual bool registerService(const std::shared_ptr<StubBase>& stubBase, - const char* interfaceId, - const std::string& participantId, - const std::string& serviceName, - const std::string& domain, - const std::shared_ptr<Factory>& factory); - - private: - typedef std::unordered_map<std::string, std::shared_ptr<DBusStubAdapter>> DBusServicesMap; - - void unregisterManagedService(DBusServicesMap::iterator& managedServiceIterator); - - DBusServicesMap registeredServices_; - - friend class DBusFactory; -}; - -} // namespace DBus -} // namespace CommonAPI - -#endif /* COMMONAPI_DBUS_DBUS_SERVICE_PUBLISHER_H_ */ diff --git a/src/CommonAPI/DBus/DBusServiceRegistry.cpp b/src/CommonAPI/DBus/DBusServiceRegistry.cpp index 236dc5b..7d12878 100644 --- a/src/CommonAPI/DBus/DBusServiceRegistry.cpp +++ b/src/CommonAPI/DBus/DBusServiceRegistry.cpp @@ -1,20 +1,42 @@ -/* Copyright (C) 2013 BMW Group - * Author: Manfred Bathelt (manfred.bathelt@bmw.de) - * Author: Juergen Gehring (juergen.gehring@bmw.de) - * 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 "DBusFunctionalHash.h" -#include "DBusServiceRegistry.h" -#include "DBusDaemonProxy.h" -#include "DBusProxyAsyncCallbackHandler.h" -#include "DBusUtils.h" +// 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/. #include <iterator> +#include <CommonAPI/Logger.hpp> +#include <CommonAPI/DBus/DBusAddressTranslator.hpp> +#include <CommonAPI/DBus/DBusDaemonProxy.hpp> +#include <CommonAPI/DBus/DBusFunctionalHash.hpp> +#include <CommonAPI/DBus/DBusProxyAsyncCallbackHandler.hpp> +#include <CommonAPI/DBus/DBusServiceRegistry.hpp> +#include <CommonAPI/DBus/DBusTypes.hpp> +#include <CommonAPI/DBus/DBusUtils.hpp> + namespace CommonAPI { namespace DBus { +DBusServiceRegistry::RegistryMap_t DBusServiceRegistry::registries_; +std::mutex DBusServiceRegistry::registriesMutex_; +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; +} + DBusServiceRegistry::DBusServiceRegistry(std::shared_ptr<DBusProxyConnection> dbusProxyConnection) : dbusDaemonProxy_(std::make_shared<CommonAPI::DBus::DBusDaemonProxy>(dbusProxyConnection)), initialized_(false), @@ -24,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) @@ -53,12 +75,14 @@ DBusServiceRegistry::~DBusServiceRegistry() { } void DBusServiceRegistry::init() { + translator_ = DBusAddressTranslator::get(); + dbusDaemonProxyStatusEventSubscription_ = - dbusDaemonProxy_->getProxyStatusEvent().subscribeCancellableListener( + dbusDaemonProxy_->getProxyStatusEvent().subscribe( std::bind(&DBusServiceRegistry::onDBusDaemonProxyStatusEvent, this, std::placeholders::_1)); dbusDaemonProxyNameOwnerChangedEventSubscription_ = - dbusDaemonProxy_->getNameOwnerChangedEvent().subscribeCancellableListener( + dbusDaemonProxy_->getNameOwnerChangedEvent().subscribe( std::bind(&DBusServiceRegistry::onDBusDaemonProxyNameOwnerChangedEvent, this, std::placeholders::_1, @@ -70,46 +94,38 @@ void DBusServiceRegistry::init() { initialized_ = true; } -DBusServiceRegistry::DBusServiceSubscription DBusServiceRegistry::subscribeAvailabilityListener(const std::string& commonApiAddress, - DBusServiceListener serviceListener) { - std::string dbusInterfaceName; - std::string dbusServiceName; - std::string dbusObjectPath; - - DBusAddressTranslator::getInstance().searchForDBusAddress( - commonApiAddress, - dbusInterfaceName, - dbusServiceName, - dbusObjectPath); +DBusServiceRegistry::DBusServiceSubscription +DBusServiceRegistry::subscribeAvailabilityListener( + const std::string &_address, DBusServiceListener serviceListener) { + DBusAddress dbusAddress; + translator_->translate(_address, dbusAddress); if (notificationThread_ == std::this_thread::get_id()) { - std::cerr << "ERROR: You must not build proxies in callbacks of ProxyStatusEvent." - << " Refer to the documentation for suggestions how to avoid this.\n"; + COMMONAPI_ERROR( + "You must not build proxies in callbacks of ProxyStatusEvent.", + " Please refer to the documentation for suggestions how to avoid this."); assert(false); } std::lock_guard<std::mutex> dbusServicesLock(dbusServicesMutex_); - auto& dbusServiceListenersRecord = dbusServiceListenersMap[dbusServiceName]; + auto& dbusServiceListenersRecord = dbusServiceListenersMap[dbusAddress.getService()]; assert(dbusServiceListenersRecord.uniqueBusNameState != DBusRecordState::AVAILABLE); - auto& dbusInterfaceNameListenersMap = dbusServiceListenersRecord.dbusObjectPathListenersMap[dbusObjectPath]; - auto& dbusInterfaceNameListenersRecord = dbusInterfaceNameListenersMap[dbusInterfaceName]; + auto& dbusInterfaceNameListenersMap = dbusServiceListenersRecord.dbusObjectPathListenersMap[dbusAddress.getObjectPath()]; + auto& dbusInterfaceNameListenersRecord = dbusInterfaceNameListenersMap[dbusAddress.getInterface()]; AvailabilityStatus availabilityStatus = AvailabilityStatus::UNKNOWN; if (dbusServiceListenersRecord.uniqueBusNameState == DBusRecordState::UNKNOWN) { dbusInterfaceNameListenersRecord.state = DBusRecordState::UNKNOWN; if (dbusServiceListenersRecord.uniqueBusNameState == DBusRecordState::UNKNOWN) { - resolveDBusServiceName(dbusServiceName, dbusServiceListenersRecord); + resolveDBusServiceName(dbusAddress.getService(), dbusServiceListenersRecord); } } else if (dbusServiceListenersRecord.uniqueBusNameState == DBusRecordState::NOT_AVAILABLE) { availabilityStatus = AvailabilityStatus::NOT_AVAILABLE; - } else if (dbusServiceListenersRecord.uniqueBusNameState != DBusRecordState::RESOLVING && dbusInterfaceNameListenersRecord.state == DBusRecordState::UNKNOWN) { - dbusInterfaceNameListenersRecord.state = resolveDBusInterfaceNameState( - dbusInterfaceName, - dbusObjectPath, - dbusServiceName, - dbusServiceListenersRecord); + } else if (dbusServiceListenersRecord.uniqueBusNameState != DBusRecordState::RESOLVING && + dbusInterfaceNameListenersRecord.state == DBusRecordState::UNKNOWN) { + dbusInterfaceNameListenersRecord.state = resolveDBusInterfaceNameState(dbusAddress, dbusServiceListenersRecord); } if(availabilityStatus == AvailabilityStatus::UNKNOWN) { @@ -126,21 +142,11 @@ DBusServiceRegistry::DBusServiceSubscription DBusServiceRegistry::subscribeAvail } } + // LB TODO: check this as it looks STRANGE!!! if (availabilityStatus != AvailabilityStatus::UNKNOWN) { notificationThread_ = std::this_thread::get_id(); - SubscriptionStatus subscriptionStatus = serviceListener(availabilityStatus); + serviceListener(availabilityStatus); notificationThread_ = std::thread::id(); - - if (subscriptionStatus == SubscriptionStatus::CANCEL) { - if (dbusInterfaceNameListenersRecord.listenerList.empty()) { - dbusInterfaceNameListenersMap.erase(dbusInterfaceName); - if (dbusInterfaceNameListenersMap.empty()) { - dbusServiceListenersRecord.dbusObjectPathListenersMap.erase(dbusObjectPath); - } - } - - return DBusServiceSubscription(); - } } dbusInterfaceNameListenersRecord.listenerList.push_front(std::move(serviceListener)); @@ -148,20 +154,14 @@ DBusServiceRegistry::DBusServiceSubscription DBusServiceRegistry::subscribeAvail return dbusInterfaceNameListenersRecord.listenerList.begin(); } -void DBusServiceRegistry::unsubscribeAvailabilityListener(const std::string& commonApiAddress, - DBusServiceSubscription& listenerSubscription) { - std::string dbusInterfaceName; - std::string dbusServiceName; - std::string dbusObjectPath; - - DBusAddressTranslator::getInstance().searchForDBusAddress( - commonApiAddress, - dbusInterfaceName, - dbusServiceName, - dbusObjectPath); +void +DBusServiceRegistry::unsubscribeAvailabilityListener( + const std::string &_address, DBusServiceSubscription& listenerSubscription) { + DBusAddress dbusAddress; + translator_->translate(_address, dbusAddress); std::lock_guard<std::mutex> dbusServicesLock(dbusServicesMutex_); - auto dbusServiceListenersIterator = dbusServiceListenersMap.find(dbusServiceName); + auto dbusServiceListenersIterator = dbusServiceListenersMap.find(dbusAddress.getService()); const bool isDBusServiceListenersRecordFound = (dbusServiceListenersIterator != dbusServiceListenersMap.end()); if (!isDBusServiceListenersRecordFound) { @@ -170,7 +170,7 @@ void DBusServiceRegistry::unsubscribeAvailabilityListener(const std::string& com auto& dbusServiceListenersRecord = dbusServiceListenersIterator->second; auto dbusObjectPathListenersIterator = - dbusServiceListenersRecord.dbusObjectPathListenersMap.find(dbusObjectPath); + dbusServiceListenersRecord.dbusObjectPathListenersMap.find(dbusAddress.getObjectPath()); const bool isDBusObjectPathListenersRecordFound = (dbusObjectPathListenersIterator != dbusServiceListenersRecord.dbusObjectPathListenersMap.end()); @@ -179,7 +179,7 @@ void DBusServiceRegistry::unsubscribeAvailabilityListener(const std::string& com } auto& dbusInterfaceNameListenersMap = dbusObjectPathListenersIterator->second; - auto dbusInterfaceNameListenersIterator = dbusInterfaceNameListenersMap.find(dbusInterfaceName); + auto dbusInterfaceNameListenersIterator = dbusInterfaceNameListenersMap.find(dbusAddress.getInterface()); const bool isDBusInterfaceNameListenersRecordFound = (dbusInterfaceNameListenersIterator != dbusInterfaceNameListenersMap.end()); @@ -314,16 +314,16 @@ 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); - if(callStatus == CallStatus::SUCCESS) { + if (callStatus == CallStatus::SUCCESS) { for(std::string serviceName : availableServiceNames) { if(isDBusServiceName(serviceName)) { dbusServiceNameMap_[serviceName]; @@ -386,7 +386,7 @@ std::vector<std::string> DBusServiceRegistry::getAvailableServiceInstances(const std::mutex mutexResolveAllObjectPaths; std::unique_lock<std::mutex> lockResolveAllObjectPaths(mutexResolveAllObjectPaths); - // TODO: should use the remaining timeout not "used" during wait before + // TODO: Check if should use the remaining timeout not "used" during wait before monitorResolveAllObjectPaths_.wait_for(lockResolveAllObjectPaths, timeout, [&] { mutexServiceResolveCount.lock(); bool finished = objectPathsToResolve == 0; @@ -395,8 +395,6 @@ std::vector<std::string> DBusServiceRegistry::getAvailableServiceInstances(const return finished; }); - DBusAddressTranslator& dbusAddressTranslator = DBusAddressTranslator::getInstance(); - for (auto serviceNameIterator = dbusServiceNameMap_.begin(); serviceNameIterator != dbusServiceNameMap_.end(); serviceNameIterator++) { @@ -413,7 +411,8 @@ std::vector<std::string> DBusServiceRegistry::getAvailableServiceInstances(const if (dbusObjectPathCacheIterator->second.dbusInterfaceNamesCache.find(interfaceName) != dbusObjectPathCacheIterator->second.dbusInterfaceNamesCache.end()) { std::string commonApiAddress; - dbusAddressTranslator.searchForCommonAddress(interfaceName, serviceName, dbusObjectPathCacheIterator->first, commonApiAddress); + translator_->translate( + dbusObjectPathCacheIterator->first + "/" + interfaceName + "/" + serviceName, commonApiAddress); availableServiceInstances.push_back(commonApiAddress); } } @@ -426,53 +425,36 @@ std::vector<std::string> DBusServiceRegistry::getAvailableServiceInstances(const return availableServiceInstances; } -//std::vector<std::string> DBusServiceRegistry::getManagedObjects(const std::string& connectionName, const std::string& objectpath) { -// if (auto iter = dbusServiceNameMap_.find(connectionName) != dbusServiceNameMap_.end()) { -// DBusUniqueNameRecord* rec = iter->second; -// if (rec->uniqueName != DBusRecordState::RESOLVED) { -// return std::vector<std::string>(); -// } else { -// rec->dbusObjectPathsCache -// } -// -// } else { -// return std::vector<std::string>(); -// } -//} - -void DBusServiceRegistry::getAvailableServiceInstancesAsync(Factory::GetAvailableServiceInstancesCallback callback, - const std::string& interfaceName, - const std::string& domainName) { +void DBusServiceRegistry::getAvailableServiceInstancesAsync(CommonAPI::Factory::AvailableInstancesCbk_t _cbk, + const std::string &_interface, + const std::string &_domain) { //Necessary as service discovery might need some time, but the async version of "getAvailableServiceInstances" //shall return without delay. std::thread( - [this, callback, interfaceName, domainName](std::shared_ptr<DBusServiceRegistry> selfRef) { - auto availableServiceInstances = getAvailableServiceInstances(interfaceName, domainName); - callback(availableServiceInstances); + [this, _cbk, _interface, _domain](std::shared_ptr<DBusServiceRegistry> selfRef) { + auto instances = getAvailableServiceInstances(_interface, _domain); + _cbk(instances); }, this->shared_from_this() ).detach(); } -SubscriptionStatus DBusServiceRegistry::onSignalDBusMessage(const DBusMessage& dbusMessage) { - const std::string& dbusServiceUniqueName = dbusMessage.getSenderName(); +void DBusServiceRegistry::onSignalDBusMessage(const DBusMessage &_dbusMessage) { + const std::string& dbusServiceUniqueName = _dbusMessage.getSender(); - assert(dbusMessage.isSignalType()); - assert(dbusMessage.hasInterfaceName("org.freedesktop.DBus.ObjectManager")); - assert(dbusMessage.hasMemberName("InterfacesAdded") || dbusMessage.hasMemberName("InterfacesRemoved")); + assert(_dbusMessage.isSignalType()); + assert(_dbusMessage.hasInterfaceName("org.freedesktop.DBus.ObjectManager")); + assert(_dbusMessage.hasMemberName("InterfacesAdded") || _dbusMessage.hasMemberName("InterfacesRemoved")); - DBusInputStream dbusInputStream(dbusMessage); + DBusInputStream dbusInputStream(_dbusMessage); std::string dbusObjectPath; std::unordered_set<std::string> dbusInterfaceNames; DBusRecordState dbusInterfaceNameState; dbusInputStream >> dbusObjectPath; - if (dbusMessage.hasMemberName("InterfacesAdded")) { + if (_dbusMessage.hasMemberName("InterfacesAdded")) { dbusInterfaceNameState = DBusRecordState::AVAILABLE; - typedef std::unordered_map<std::string, bool> DBusPropertiesChangedDict; - typedef std::unordered_map<std::string, DBusPropertiesChangedDict> DBusInterfacesAndPropertiesDict; - typedef std::unordered_map<std::string, DBusInterfacesAndPropertiesDict> DBusObjectPathAndInterfacesDict; DBusObjectPathAndInterfacesDict dbusObjectPathAndInterfacesDict; dbusInputStream >> dbusObjectPathAndInterfacesDict; @@ -485,6 +467,7 @@ SubscriptionStatus DBusServiceRegistry::onSignalDBusMessage(const DBusMessage& d dbusInterfaceNameState = DBusRecordState::NOT_AVAILABLE; dbusInputStream >> removedDBusInterfaceNames; + std::move( removedDBusInterfaceNames.begin(), removedDBusInterfaceNames.end(), @@ -492,11 +475,11 @@ SubscriptionStatus DBusServiceRegistry::onSignalDBusMessage(const DBusMessage& d } if (dbusInputStream.hasError()) { - return SubscriptionStatus::RETAIN; + return; } if (dbusInterfaceNames.empty()) { - return SubscriptionStatus::RETAIN; + return; } std::lock_guard<std::mutex> dbusServicesLock(dbusServicesMutex_); @@ -505,7 +488,9 @@ SubscriptionStatus DBusServiceRegistry::onSignalDBusMessage(const DBusMessage& d const bool isDBusServiceUniqueNameFound = (dbusServiceUniqueNameIterator != dbusUniqueNamesMap_.end()); if (!isDBusServiceUniqueNameFound) { - return SubscriptionStatus::CANCEL; + // LB TODO: unsubscribe here! + // Needs to be reworked in order to store the subscription identifier! + return; } auto& dbusUniqueNameRecord = dbusServiceUniqueNameIterator->second; @@ -513,7 +498,7 @@ SubscriptionStatus DBusServiceRegistry::onSignalDBusMessage(const DBusMessage& d DBusObjectPathCache& dbusObjectPathRecord = dbusUniqueNameRecord.dbusObjectPathsCache[dbusObjectPath]; if (dbusObjectPathRecord.state != DBusRecordState::RESOLVED) { - return SubscriptionStatus::RETAIN; + return; } for (const auto& dbusInterfaceName : dbusInterfaceNames) { @@ -525,8 +510,6 @@ SubscriptionStatus DBusServiceRegistry::onSignalDBusMessage(const DBusMessage& d } notifyDBusServiceListeners(dbusUniqueNameRecord, dbusObjectPath, dbusInterfaceNames, dbusInterfaceNameState); - - return SubscriptionStatus::RETAIN; } @@ -578,7 +561,7 @@ void DBusServiceRegistry::onGetNameOwnerCallback(const CallStatus& status, dbusServiceListenersRecord.promiseOnResolve.set_value(DBusRecordState::NOT_AVAILABLE); } - onDBusServiceNotAvailable(dbusServiceListenersRecord); + onDBusServiceNotAvailable(dbusServiceListenersRecord, dbusServiceName); } mutexServiceResolveCount.lock(); @@ -587,10 +570,9 @@ void DBusServiceRegistry::onGetNameOwnerCallback(const CallStatus& status, monitorResolveAllServices_.notify_all(); } -DBusServiceRegistry::DBusRecordState DBusServiceRegistry::resolveDBusInterfaceNameState(const std::string& dbusInterfaceName, - const std::string& dbusObjectPath, - const std::string& dbusServiceName, - DBusServiceListenersRecord& dbusServiceListenersRecord) { +DBusServiceRegistry::DBusRecordState +DBusServiceRegistry::resolveDBusInterfaceNameState( + const DBusAddress &_dbusAddress, DBusServiceListenersRecord &dbusServiceListenersRecord) { assert(dbusServiceListenersRecord.uniqueBusNameState == DBusRecordState::RESOLVED); assert(!dbusServiceListenersRecord.uniqueBusName.empty()); @@ -598,7 +580,7 @@ DBusServiceRegistry::DBusRecordState DBusServiceRegistry::resolveDBusInterfaceNa assert(!dbusServiceUniqueNameRecord.ownedBusNames.empty()); auto& dbusObjectPathRecord = getDBusObjectPathCacheReference( - dbusObjectPath, + _dbusAddress.getObjectPath(), dbusServiceListenersRecord.uniqueBusName, dbusServiceUniqueNameRecord); @@ -606,7 +588,8 @@ DBusServiceRegistry::DBusRecordState DBusServiceRegistry::resolveDBusInterfaceNa return dbusObjectPathRecord.state; } - auto dbusInterfaceNameIterator = dbusObjectPathRecord.dbusInterfaceNamesCache.find(dbusInterfaceName); + auto dbusInterfaceNameIterator + = dbusObjectPathRecord.dbusInterfaceNamesCache.find(_dbusAddress.getInterface()); const bool isDBusInterfaceNameFound = (dbusInterfaceNameIterator != dbusObjectPathRecord.dbusInterfaceNamesCache.end()); @@ -614,9 +597,11 @@ DBusServiceRegistry::DBusRecordState DBusServiceRegistry::resolveDBusInterfaceNa } -DBusServiceRegistry::DBusObjectPathCache& DBusServiceRegistry::getDBusObjectPathCacheReference(const std::string& dbusObjectPath, - const std::string& dbusServiceUniqueName, - DBusUniqueNameRecord& dbusUniqueNameRecord) { +DBusServiceRegistry::DBusObjectPathCache & +DBusServiceRegistry::getDBusObjectPathCacheReference( + const std::string& dbusObjectPath, + const std::string& dbusServiceUniqueName, + DBusUniqueNameRecord& dbusUniqueNameRecord) { const bool isFirstDBusObjectPathCache = dbusUniqueNameRecord.dbusObjectPathsCache.empty(); auto dbusObjectPathCacheIterator = dbusUniqueNameRecord.dbusObjectPathsCache.find(dbusObjectPath); @@ -694,10 +679,9 @@ bool DBusServiceRegistry::introspectDBusObjectPath(const std::string& dbusServic objectPathsToResolve++; mutexObjectPathsResolveCount.unlock(); + DBusAddress dbusAddress(dbusServiceUniqueName, dbusObjectPath, "org.freedesktop.DBus.Introspectable"); DBusMessage dbusMessageCall = DBusMessage::createMethodCall( - dbusServiceUniqueName, - dbusObjectPath, - "org.freedesktop.DBus.Introspectable", + dbusAddress, "Introspect"); auto instrospectAsyncCallback = std::bind( &DBusServiceRegistry::onIntrospectCallback, @@ -709,7 +693,10 @@ bool DBusServiceRegistry::introspectDBusObjectPath(const std::string& dbusServic dbusConnection->sendDBusMessageWithReplyAsync( dbusMessageCall, - DBusProxyAsyncCallbackHandler<std::string>::create(instrospectAsyncCallback)); + DBusProxyAsyncCallbackHandler< + std::string + >::create(instrospectAsyncCallback, std::tuple<std::string>()), + &serviceRegistryInfo); isResolvingInProgress = true; } @@ -775,7 +762,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()); @@ -848,7 +835,7 @@ void DBusServiceRegistry::parseIntrospectionData(const std::string& xmlData, } -SubscriptionStatus DBusServiceRegistry::onDBusDaemonProxyStatusEvent(const AvailabilityStatus& availabilityStatus) { +void DBusServiceRegistry::onDBusDaemonProxyStatusEvent(const AvailabilityStatus& availabilityStatus) { assert(availabilityStatus != AvailabilityStatus::UNKNOWN); std::lock_guard<std::mutex> dbusServicesLock(dbusServicesMutex_); @@ -860,32 +847,28 @@ SubscriptionStatus DBusServiceRegistry::onDBusDaemonProxyStatusEvent(const Avail if (availabilityStatus == AvailabilityStatus::AVAILABLE) { resolveDBusServiceName(dbusServiceName, dbusServiceListenersRecord); } else { - onDBusServiceNotAvailable(dbusServiceListenersRecord); + onDBusServiceNotAvailable(dbusServiceListenersRecord, dbusServiceName); } } - - return SubscriptionStatus::RETAIN; } void DBusServiceRegistry::checkDBusServiceWasAvailable(const std::string& dbusServiceName, const std::string& dbusServiceUniqueName) { - auto dbusUniqueNameIterator = dbusUniqueNamesMap_.find(dbusServiceUniqueName); const bool isDBusUniqueNameFound = (dbusUniqueNameIterator != dbusUniqueNamesMap_.end()); if (isDBusUniqueNameFound) { auto& dbusServiceListenersRecord = dbusServiceListenersMap[dbusServiceName]; - onDBusServiceNotAvailable(dbusServiceListenersRecord); + onDBusServiceNotAvailable(dbusServiceListenersRecord, dbusServiceName); } } -SubscriptionStatus DBusServiceRegistry::onDBusDaemonProxyNameOwnerChangedEvent(const std::string& affectedName, - const std::string& oldOwner, - const std::string& newOwner) { +void DBusServiceRegistry::onDBusDaemonProxyNameOwnerChangedEvent(const std::string& affectedName, + const std::string& oldOwner, + const std::string& newOwner) { if (!isDBusServiceName(affectedName)) { - return SubscriptionStatus::RETAIN; + return; } - const bool isDBusServiceNameLost = newOwner.empty(); const std::string& dbusServiceUniqueName = (isDBusServiceNameLost ? oldOwner : newOwner); @@ -897,7 +880,7 @@ SubscriptionStatus DBusServiceRegistry::onDBusDaemonProxyNameOwnerChangedEvent(c onDBusServiceAvailable(affectedName, dbusServiceUniqueName); } - return SubscriptionStatus::RETAIN; + return; } @@ -946,13 +929,13 @@ void DBusServiceRegistry::onDBusServiceAvailable(const std::string& dbusServiceN } } -void DBusServiceRegistry::onDBusServiceNotAvailable(DBusServiceListenersRecord& dbusServiceListenersRecord) { +void DBusServiceRegistry::onDBusServiceNotAvailable(DBusServiceListenersRecord& dbusServiceListenersRecord, const std::string &_serviceName) { const std::unordered_set<std::string> dbusInterfaceNamesCache; const DBusUniqueNamesMapIterator dbusUniqueNameRecordIterator = dbusUniqueNamesMap_.find(dbusServiceListenersRecord.uniqueBusName); if (dbusUniqueNameRecordIterator != dbusUniqueNamesMap_.end()) { - removeUniqueName(dbusUniqueNameRecordIterator); + removeUniqueName(dbusUniqueNameRecordIterator, _serviceName); } dbusServiceListenersRecord.uniqueBusName.clear(); @@ -1059,7 +1042,6 @@ void DBusServiceRegistry::notifyDBusObjectPathChanged(DBusInterfaceNameListeners void DBusServiceRegistry::notifyDBusInterfaceNameListeners(DBusInterfaceNameListenersRecord& dbusInterfaceNameListenersRecord, const bool& isDBusInterfaceNameAvailable) { - const AvailabilityStatus availabilityStatus = (isDBusInterfaceNameAvailable ? AvailabilityStatus::AVAILABLE : AvailabilityStatus::NOT_AVAILABLE); const DBusRecordState notifyState = (isDBusInterfaceNameAvailable ? @@ -1071,31 +1053,28 @@ void DBusServiceRegistry::notifyDBusInterfaceNameListeners(DBusInterfaceNameList dbusInterfaceNameListenersRecord.state = notifyState; for (auto dbusServiceListenerIterator = dbusInterfaceNameListenersRecord.listenerList.begin(); - dbusServiceListenerIterator != dbusInterfaceNameListenersRecord.listenerList.end();) { - const auto& dbusServiceListener = *dbusServiceListenerIterator; - - if (dbusServiceListener(availabilityStatus) != SubscriptionStatus::RETAIN) { - dbusServiceListenerIterator = dbusInterfaceNameListenersRecord.listenerList.erase( - dbusServiceListenerIterator); - } else { - dbusServiceListenerIterator++; - } + dbusServiceListenerIterator != dbusInterfaceNameListenersRecord.listenerList.end(); + dbusServiceListenerIterator++) { + (*dbusServiceListenerIterator)(availabilityStatus); } } -void DBusServiceRegistry::removeUniqueName(const DBusUniqueNamesMapIterator& dbusUniqueNamesIterator) { +void DBusServiceRegistry::removeUniqueName(const DBusUniqueNamesMapIterator& dbusUniqueNamesIterator, const std::string &_serviceName) { const bool isSubscriptionCancelled = dbusDaemonProxy_->getDBusConnection()->removeObjectManagerSignalMemberHandler( dbusUniqueNamesIterator->first, this); assert(isSubscriptionCancelled); - for (auto dbusServiceNamesIterator = dbusUniqueNamesIterator->second.ownedBusNames.begin(); - dbusServiceNamesIterator != dbusUniqueNamesIterator->second.ownedBusNames.end(); - dbusServiceNamesIterator++) { - dbusServiceNameMap_.erase(*dbusServiceNamesIterator); + if ("" != _serviceName) { + auto findServiceName = dbusUniqueNamesIterator->second.ownedBusNames.find(_serviceName); + if (findServiceName != dbusUniqueNamesIterator->second.ownedBusNames.end()) + dbusUniqueNamesIterator->second.ownedBusNames.erase(findServiceName); + } else { + dbusUniqueNamesIterator->second.ownedBusNames.clear(); } - dbusUniqueNamesMap_.erase(dbusUniqueNamesIterator); + if (dbusUniqueNamesIterator->second.ownedBusNames.size() == 0) + dbusUniqueNamesMap_.erase(dbusUniqueNamesIterator); } DBusServiceRegistry::DBusUniqueNameRecord* DBusServiceRegistry::insertServiceNameMapping(const std::string& dbusUniqueName, diff --git a/src/CommonAPI/DBus/DBusServiceRegistry.h b/src/CommonAPI/DBus/DBusServiceRegistry.h deleted file mode 100644 index 4c90091..0000000 --- a/src/CommonAPI/DBus/DBusServiceRegistry.h +++ /dev/null @@ -1,319 +0,0 @@ -/* Copyright (C) 2013 BMW Group - * Author: Manfred Bathelt (manfred.bathelt@bmw.de) - * Author: Juergen Gehring (juergen.gehring@bmw.de) - * 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/. */ - -#if !defined (COMMONAPI_INTERNAL_COMPILATION) -#error "Only <CommonAPI/CommonAPI.h> can be included directly, this file may disappear or change contents." -#endif - -#ifndef COMMONAPI_DBUS_DBUS_SERVICE_REGISTRY_H_ -#define COMMONAPI_DBUS_DBUS_SERVICE_REGISTRY_H_ - -#include <CommonAPI/types.h> -#include <CommonAPI/Attribute.h> -#include <CommonAPI/Proxy.h> -#include <CommonAPI/Factory.h> - -#include "DBusProxyConnection.h" -#include "DBusAddressTranslator.h" -#include "DBusDaemonProxy.h" - -#include "pugixml/pugixml.hpp" - -#include <unordered_map> -#include <unordered_set> -#include <utility> -#include <map> -#include <unordered_set> -#include <string> -#include <vector> -#include <memory> -#include <list> -#include <algorithm> -#include <set> - -#include <condition_variable> -#include <mutex> -#include <future> - -namespace CommonAPI { -namespace DBus { - -typedef Event<std::string, std::string, std::string> NameOwnerChangedEvent; -typedef Event<std::string, std::string, std::string>::Subscription NameOwnerChangedEventSubscription; - -//connectionName, objectPath -typedef std::pair<std::string, std::string> DBusInstanceId; - -class DBusProxyConnection; -class DBusDaemonProxy; - -class DBusServiceRegistry: public std::enable_shared_from_this<DBusServiceRegistry>, - public DBusProxyConnection::DBusSignalHandler { - public: - enum class DBusRecordState { - UNKNOWN, - AVAILABLE, - RESOLVING, - RESOLVED, - NOT_AVAILABLE - }; - - // template class DBusServiceListener<> { typedef functor; typedef list; typedef subscription } - typedef std::function<SubscriptionStatus(const AvailabilityStatus& availabilityStatus)> DBusServiceListener; - typedef std::list<DBusServiceListener> DBusServiceListenerList; - typedef DBusServiceListenerList::iterator DBusServiceSubscription; - - - typedef std::function<SubscriptionStatus(const std::vector<std::string>& interfaces, - const AvailabilityStatus& availabilityStatus)> DBusManagedInterfaceListener; - typedef std::list<DBusManagedInterfaceListener> DBusManagedInterfaceListenerList; - typedef DBusManagedInterfaceListenerList::iterator DBusManagedInterfaceSubscription; - - - DBusServiceRegistry(std::shared_ptr<DBusProxyConnection> dbusProxyConnection); - - DBusServiceRegistry(const DBusServiceRegistry&) = delete; - DBusServiceRegistry& operator=(const DBusServiceRegistry&) = delete; - - virtual ~DBusServiceRegistry(); - - void init(); - - - DBusServiceSubscription subscribeAvailabilityListener(const std::string& commonApiAddress, - DBusServiceListener serviceListener); - - void unsubscribeAvailabilityListener(const std::string& commonApiAddress, - DBusServiceSubscription& listenerSubscription); - - - bool isServiceInstanceAlive(const std::string& dbusInterfaceName, - const std::string& dbusConnectionName, - const std::string& dbusObjectPath); - - - virtual std::vector<std::string> getAvailableServiceInstances(const std::string& interfaceName, - const std::string& domainName = "local"); - - virtual void getAvailableServiceInstancesAsync(Factory::GetAvailableServiceInstancesCallback callback, - const std::string& interfaceName, - const std::string& domainName = "local"); - - - virtual SubscriptionStatus onSignalDBusMessage(const DBusMessage&); - - private: - struct DBusInterfaceNameListenersRecord { - DBusInterfaceNameListenersRecord(): state(DBusRecordState::UNKNOWN) { - } - - DBusInterfaceNameListenersRecord(DBusInterfaceNameListenersRecord&& other): - state(other.state), - listenerList(std::move(other.listenerList)) - { - } - - DBusRecordState state; - DBusServiceListenerList listenerList; - }; - - typedef std::unordered_map<std::string, DBusInterfaceNameListenersRecord> DBusInterfaceNameListenersMap; - - struct DBusServiceListenersRecord { - DBusServiceListenersRecord(): uniqueBusNameState(DBusRecordState::UNKNOWN), - mutexOnResolve() { - } - - DBusServiceListenersRecord(DBusServiceListenersRecord&& other): - uniqueBusNameState(other.uniqueBusNameState), - uniqueBusName(std::move(other.uniqueBusName)), - promiseOnResolve(std::move(other.promiseOnResolve)), - futureOnResolve(std::move(other.futureOnResolve)), - mutexOnResolve(std::move(other.mutexOnResolve)), - dbusObjectPathListenersMap(std::move(other.dbusObjectPathListenersMap)) - {} - - ~DBusServiceListenersRecord() {}; - - DBusRecordState uniqueBusNameState; - std::string uniqueBusName; - - std::promise<DBusRecordState> promiseOnResolve; - std::shared_future<DBusRecordState> futureOnResolve; - std::unique_lock<std::mutex>* mutexOnResolve; - - std::unordered_map<std::string, DBusInterfaceNameListenersMap> dbusObjectPathListenersMap; - }; - - std::unordered_map<std::string, DBusServiceListenersRecord> dbusServiceListenersMap; - - - struct DBusObjectPathCache { - DBusObjectPathCache(): referenceCount(0), state(DBusRecordState::UNKNOWN) { - } - - DBusObjectPathCache(DBusObjectPathCache&& other): - referenceCount(other.referenceCount), - state(other.state), - promiseOnResolve(std::move(other.promiseOnResolve)), - dbusInterfaceNamesCache(std::move(other.dbusInterfaceNamesCache)) - { - /*other.promiseOnResolve = NULL; - other.dbusInterfaceNamesCache = NULL;*/ - } - - ~DBusObjectPathCache() {} - - size_t referenceCount; - DBusRecordState state; - std::promise<DBusRecordState> promiseOnResolve; - - std::unordered_set<std::string> dbusInterfaceNamesCache; - }; - - struct DBusUniqueNameRecord { - DBusUniqueNameRecord(): objectPathsState(DBusRecordState::UNKNOWN) { - } - - DBusUniqueNameRecord(DBusUniqueNameRecord&& other) : - uniqueName(std::move(other.uniqueName)), - objectPathsState(other.objectPathsState), - ownedBusNames(std::move(other.ownedBusNames)), - dbusObjectPathsCache(std::move(other.dbusObjectPathsCache)) - {} - - std::string uniqueName; - DBusRecordState objectPathsState; - std::unordered_set<std::string> ownedBusNames; - std::unordered_map<std::string, DBusObjectPathCache> dbusObjectPathsCache; - }; - - std::unordered_map<std::string, DBusUniqueNameRecord> dbusUniqueNamesMap_; - typedef std::unordered_map<std::string, DBusUniqueNameRecord>::iterator DBusUniqueNamesMapIterator; - - // mapping service names (well-known names) to service instances - std::unordered_map<std::string, DBusUniqueNameRecord*> dbusServiceNameMap_; - - - // protects the dbus service maps - std::mutex dbusServicesMutex_; - - - void resolveDBusServiceName(const std::string& dbusServiceName, - DBusServiceListenersRecord& dbusServiceListenersRecord); - - void onGetNameOwnerCallback(const CallStatus& status, std::string dbusServiceUniqueName, const std::string& dbusServiceName); - - - DBusRecordState resolveDBusInterfaceNameState(const std::string& dbusInterfaceName, - const std::string& dbusObjectPath, - const std::string& dbusServiceName, - DBusServiceListenersRecord& dbusServiceListenersRecord); - - - DBusObjectPathCache& getDBusObjectPathCacheReference(const std::string& dbusObjectPath, - const std::string& dbusServiceUniqueName, - DBusUniqueNameRecord& dbusUniqueNameRecord); - - void releaseDBusObjectPathCacheReference(const std::string& dbusObjectPath, - const DBusServiceListenersRecord& dbusServiceListenersRecord); - - - bool introspectDBusObjectPath(const std::string& dbusServiceUniqueName, const std::string& dbusObjectPath); - - void onIntrospectCallback(const CallStatus& status, - std::string xmlData, - const std::string& dbusServiceName, - const std::string& dbusObjectPath); - - void parseIntrospectionData(const std::string& xmlData, - const std::string& rootObjectPath, - const std::string& dbusServiceUniqueName); - - void parseIntrospectionNode(const pugi::xml_node& node, - const std::string& rootObjectPath, - const std::string& fullObjectPath, - const std::string& dbusServiceUniqueName); - - void processIntrospectionObjectPath(const pugi::xml_node& node, - const std::string& rootObjectPath, - const std::string& dbusServiceUniqueName); - - void processIntrospectionInterface(const pugi::xml_node& node, - const std::string& rootObjectPath, - const std::string& fullObjectPath, - const std::string& dbusServiceUniqueName); - - SubscriptionStatus onDBusDaemonProxyStatusEvent(const AvailabilityStatus& availabilityStatus); - - SubscriptionStatus onDBusDaemonProxyNameOwnerChangedEvent(const std::string& name, - const std::string& oldOwner, - const std::string& newOwner); - - std::shared_ptr<DBusDaemonProxy> dbusDaemonProxy_; - bool initialized_; - - ProxyStatusEvent::Subscription dbusDaemonProxyStatusEventSubscription_; - NameOwnerChangedEvent::Subscription dbusDaemonProxyNameOwnerChangedEventSubscription_; - - - void checkDBusServiceWasAvailable(const std::string& dbusServiceName, const std::string& dbusServiceUniqueName); - - void onDBusServiceAvailable(const std::string& dbusServiceName, const std::string& dbusServiceUniqueName); - - void onDBusServiceNotAvailable(DBusServiceListenersRecord& dbusServiceListenersRecord); - - - void notifyDBusServiceListeners(const DBusUniqueNameRecord& dbusUniqueNameRecord, - const std::string& dbusObjectPath, - const std::unordered_set<std::string>& dbusInterfaceNames, - const DBusRecordState& dbusInterfaceNamesState); - - void notifyDBusObjectPathResolved(DBusInterfaceNameListenersMap& dbusInterfaceNameListenersMap, - const std::unordered_set<std::string>& dbusInterfaceNames); - - void notifyDBusObjectPathChanged(DBusInterfaceNameListenersMap& dbusInterfaceNameListenersMap, - const std::unordered_set<std::string>& dbusInterfaceNames, - const DBusRecordState& dbusInterfaceNamesState); - - void notifyDBusInterfaceNameListeners(DBusInterfaceNameListenersRecord& dbusInterfaceNameListenersRecord, - const bool& isDBusInterfaceNameAvailable); - - - void removeUniqueName(const DBusUniqueNamesMapIterator& dbusUniqueName); - DBusUniqueNameRecord* insertServiceNameMapping(const std::string& dbusUniqueName, const std::string& dbusServiceName); - bool findCachedDbusService(const std::string& dbusServiceName, DBusUniqueNameRecord** uniqueNameRecord); - bool findCachedObjectPath(const std::string& dbusObjectPathName, const DBusUniqueNameRecord* uniqueNameRecord, DBusObjectPathCache* objectPathCache); - - std::condition_variable monitorResolveAllServices_; - std::mutex mutexServiceResolveCount; - int servicesToResolve; - - std::condition_variable monitorResolveAllObjectPaths_; - std::mutex mutexObjectPathsResolveCount; - int objectPathsToResolve; - - - void fetchAllServiceNames(); - - inline const bool isDBusServiceName(const std::string& serviceName) { - return (serviceName.length() > 0 && serviceName[0] != ':'); - }; - - - inline const bool isOrgFreedesktopDBusInterface(const std::string& dbusInterfaceName) { - return dbusInterfaceName.find("org.freedesktop.DBus.") == 0; - } - - std::thread::id notificationThread_; -}; - - -} // namespace DBus -} // namespace CommonAPI - -#endif // COMMONAPI_DBUS_DBUS_SERVICE_REGISTRY_H_ diff --git a/src/CommonAPI/DBus/DBusStubAdapter.cpp b/src/CommonAPI/DBus/DBusStubAdapter.cpp index a27bf40..03fa6c3 100644 --- a/src/CommonAPI/DBus/DBusStubAdapter.cpp +++ b/src/CommonAPI/DBus/DBusStubAdapter.cpp @@ -1,97 +1,48 @@ -/* Copyright (C) 2013 BMW Group - * Author: Manfred Bathelt (manfred.bathelt@bmw.de) - * Author: Juergen Gehring (juergen.gehring@bmw.de) - * 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 "DBusStubAdapter.h" -#include "DBusUtils.h" +// 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/. -#include <CommonAPI/utils.h> - -#include <cassert> -#include <functional> -#include <sstream> +#include <CommonAPI/DBus/DBusAddressTranslator.hpp> +#include <CommonAPI/DBus/DBusStubAdapter.hpp> namespace CommonAPI { namespace DBus { -const std::string DBusStubAdapter::domain_ = "local"; - -DBusStubAdapter::DBusStubAdapter(const std::shared_ptr<DBusFactory>& factory, - const std::string& commonApiAddress, - const std::string& dbusInterfaceName, - const std::string& dbusBusName, - const std::string& dbusObjectPath, - const std::shared_ptr<DBusProxyConnection>& dbusConnection, - const bool isManagingInterface) : - commonApiDomain_(split(commonApiAddress, ':')[0]), - commonApiServiceId_(split(commonApiAddress, ':')[1]), - commonApiParticipantId_(split(commonApiAddress, ':')[2]), - dbusBusName_(dbusBusName), - dbusObjectPath_(dbusObjectPath), - dbusInterfaceName_(dbusInterfaceName), - dbusConnection_(dbusConnection), - factory_(factory), - isManagingInterface_(isManagingInterface) { - - assert(!dbusBusName_.empty()); - assert(!dbusInterfaceName_.empty()); - assert(!dbusObjectPath_.empty()); - assert(dbusObjectPath_[0] == '/'); - assert(!dbusInterfaceName_.empty()); - assert(dbusConnection_); +DBusStubAdapter::DBusStubAdapter(const DBusAddress &_dbusAddress, + const std::shared_ptr<DBusProxyConnection> &_connection, + const bool _isManaging) + : dbusAddress_(_dbusAddress), + connection_(_connection), + isManaging_(_isManaging) { } DBusStubAdapter::~DBusStubAdapter() { deinit(); } -void DBusStubAdapter::init(std::shared_ptr<DBusStubAdapter> instance) { +void DBusStubAdapter::init(std::shared_ptr<DBusStubAdapter> _instance) { + DBusAddressTranslator::get()->translate(dbusAddress_, address_); } void DBusStubAdapter::deinit() { } -const std::string DBusStubAdapter::getAddress() const { - return commonApiDomain_ + ":" + commonApiServiceId_ + ":" + commonApiParticipantId_; -} - -const std::string& DBusStubAdapter::getDomain() const { - return commonApiDomain_; +const DBusAddress &DBusStubAdapter::getDBusAddress() const { + return dbusAddress_; } -const std::string& DBusStubAdapter::getServiceId() const { - return commonApiServiceId_; +const std::shared_ptr<DBusProxyConnection> &DBusStubAdapter::getDBusConnection() const { + return connection_; } -const std::string& DBusStubAdapter::getInstanceId() const { - return commonApiParticipantId_; +const bool DBusStubAdapter::isManaging() const { + return isManaging_; } const bool DBusStubAdapter::hasFreedesktopProperties() { return false; } -const bool DBusStubAdapter::isManagingInterface() { - return isManagingInterface_; -} - -const std::string& DBusStubAdapter::getDBusName() const { - return dbusBusName_; -} - -const std::string& DBusStubAdapter::getObjectPath() const { - return dbusObjectPath_; -} - -const std::string& DBusStubAdapter::getInterfaceName() const { - return dbusInterfaceName_; -} - -const std::shared_ptr<DBusProxyConnection>& DBusStubAdapter::getDBusConnection() const { - return dbusConnection_; -} - -} // namespace dbus +} // namespace DBus } // namespace CommonAPI diff --git a/src/CommonAPI/DBus/DBusStubAdapter.h b/src/CommonAPI/DBus/DBusStubAdapter.h deleted file mode 100644 index 3b6bfb6..0000000 --- a/src/CommonAPI/DBus/DBusStubAdapter.h +++ /dev/null @@ -1,86 +0,0 @@ -/* Copyright (C) 2013 BMW Group - * Author: Manfred Bathelt (manfred.bathelt@bmw.de) - * Author: Juergen Gehring (juergen.gehring@bmw.de) - * 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/. */ - -#if !defined (COMMONAPI_INTERNAL_COMPILATION) -#error "Only <CommonAPI/CommonAPI.h> can be included directly, this file may disappear or change contents." -#endif - -#ifndef COMMONAPI_DBUS_DBUS_STUB_ADAPTER_H_ -#define COMMONAPI_DBUS_DBUS_STUB_ADAPTER_H_ - -#include "DBusProxyConnection.h" -#include "DBusInterfaceHandler.h" -#include "DBusMessage.h" - -#include <CommonAPI/Stub.h> - -#include <string> -#include <memory> - -namespace CommonAPI { -namespace DBus { - -class DBusObjectManagerStub; -class DBusFactory; - -class DBusStubAdapter: virtual public CommonAPI::StubAdapter, public DBusInterfaceHandler { - public: - DBusStubAdapter(const std::shared_ptr<DBusFactory>& factory, - const std::string& commonApiAddress, - const std::string& dbusInterfaceName, - const std::string& dbusBusName, - const std::string& dbusObjectPath, - const std::shared_ptr<DBusProxyConnection>& dbusConnection, - const bool isManagingInterface); - - virtual ~DBusStubAdapter(); - - virtual void init(std::shared_ptr<DBusStubAdapter> instance); - virtual void deinit(); - - virtual const std::string getAddress() const; - virtual const std::string& getDomain() const; - virtual const std::string& getServiceId() const; - virtual const std::string& getInstanceId() const; - - const std::string& getDBusName() const; - const std::string& getObjectPath() const; - const std::string& getInterfaceName() const; - - const std::shared_ptr<DBusProxyConnection>& getDBusConnection() const; - - const bool isManagingInterface(); - - virtual const char* getMethodsDBusIntrospectionXmlData() const = 0; - virtual bool onInterfaceDBusMessage(const DBusMessage& dbusMessage) = 0; - - virtual void deactivateManagedInstances() = 0; - virtual const bool hasFreedesktopProperties(); - virtual bool onInterfaceDBusFreedesktopPropertiesMessage(const DBusMessage& dbusMessage) = 0; - protected: - - const std::string commonApiDomain_; - const std::string commonApiServiceId_; - const std::string commonApiParticipantId_; - - const std::string dbusBusName_; - const std::string dbusObjectPath_; - const std::string dbusInterfaceName_; - const std::shared_ptr<DBusProxyConnection> dbusConnection_; - - static const std::string domain_; - - const std::shared_ptr<DBusFactory> factory_; - - const bool isManagingInterface_; -}; - - -} // namespace dbus -} // namespace CommonAPI - -#endif // COMMONAPI_DBUS_DBUS_STUB_ADAPTER_H_ diff --git a/src/CommonAPI/DBus/DBusStubAdapterHelper.h b/src/CommonAPI/DBus/DBusStubAdapterHelper.h deleted file mode 100644 index dbac232..0000000 --- a/src/CommonAPI/DBus/DBusStubAdapterHelper.h +++ /dev/null @@ -1,838 +0,0 @@ -/* Copyright (C) 2013 BMW Group - * Author: Manfred Bathelt (manfred.bathelt@bmw.de) - * Author: Juergen Gehring (juergen.gehring@bmw.de) - * 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/. */ - -#if !defined (COMMONAPI_INTERNAL_COMPILATION) -#error "Only <CommonAPI/CommonAPI.h> can be included directly, this file may disappear or change contents." -#endif - -#ifndef COMMONAPI_DBUS_DBUS_STUB_ADAPTER_HELPER_H_ -#define COMMONAPI_DBUS_DBUS_STUB_ADAPTER_HELPER_H_ - -#include <CommonAPI/SerializableVariant.h> - -#include "DBusStubAdapter.h" -#include "DBusInputStream.h" -#include "DBusOutputStream.h" -#include "DBusHelper.h" -#include "DBusSerializableArguments.h" -#include "DBusClientId.h" -#include "DBusLegacyVariant.h" - -#include <memory> -#include <initializer_list> -#include <tuple> -#include <unordered_map> - -namespace CommonAPI { -namespace DBus { - -class StubDispatcherBase { -public: - virtual ~StubDispatcherBase() { } -}; - -template <typename _StubClass> -class DBusGetFreedesktopAttributeStubDispatcherBase; - -struct DBusAttributeDispatcherStruct { - StubDispatcherBase* getter; - StubDispatcherBase* setter; - - DBusAttributeDispatcherStruct(StubDispatcherBase* g, StubDispatcherBase* s) { - getter = g; - setter = s; - } -}; - -typedef std::unordered_map<std::string, DBusAttributeDispatcherStruct> StubAttributeTable; - -template <typename _StubClass> -class DBusStubAdapterHelper: public virtual DBusStubAdapter { - public: - typedef typename _StubClass::StubAdapterType StubAdapterType; - typedef typename _StubClass::RemoteEventHandlerType RemoteEventHandlerType; - - class StubDispatcher: public StubDispatcherBase { - public: - virtual bool dispatchDBusMessage(const DBusMessage& dbusMessage, - const std::shared_ptr<_StubClass>& stub, - DBusStubAdapterHelper<_StubClass>& dbusStubAdapterHelper) = 0; - }; - // interfaceMemberName, interfaceMemberSignature - typedef std::pair<const char*, const char*> DBusInterfaceMemberPath; - typedef std::unordered_map<DBusInterfaceMemberPath, StubDispatcherBase*> StubDispatcherTable; - - DBusStubAdapterHelper(const std::shared_ptr<DBusFactory>& factory, - const std::string& commonApiAddress, - const std::string& dbusInterfaceName, - const std::string& dbusBusName, - const std::string& dbusObjectPath, - const std::shared_ptr<DBusProxyConnection>& dbusConnection, - const std::shared_ptr<_StubClass>& stub, - const bool isManagingInterface): - DBusStubAdapter(factory, commonApiAddress, dbusInterfaceName, dbusBusName, dbusObjectPath, dbusConnection, isManagingInterface), - stub_(stub), - remoteEventHandler_(NULL) { - } - - virtual ~DBusStubAdapterHelper() { - DBusStubAdapter::deinit(); - stub_.reset(); - } - - virtual void init(std::shared_ptr<DBusStubAdapter> instance) { - DBusStubAdapter::init(instance); - std::shared_ptr<StubAdapterType> stubAdapter = std::dynamic_pointer_cast<StubAdapterType>(instance); - remoteEventHandler_ = stub_.lock()->initStubAdapter(stubAdapter); - } - - virtual void deinit() { - DBusStubAdapter::deinit(); - stub_.reset(); - } - - inline RemoteEventHandlerType* getRemoteEventHandler() { - return remoteEventHandler_; - } - - protected: - - virtual bool onInterfaceDBusMessage(const DBusMessage& dbusMessage) { - const char* interfaceMemberName = dbusMessage.getMemberName(); - const char* interfaceMemberSignature = dbusMessage.getSignatureString(); - - assert(interfaceMemberName); - assert(interfaceMemberSignature); - - DBusInterfaceMemberPath dbusInterfaceMemberPath(interfaceMemberName, interfaceMemberSignature); - auto findIterator = getStubDispatcherTable().find(dbusInterfaceMemberPath); - const bool foundInterfaceMemberHandler = (findIterator != getStubDispatcherTable().end()); - bool dbusMessageHandled = false; - - //To prevent the destruction of the stub whilst still handling a message - auto stubSafety = stub_.lock(); - if (stubSafety && foundInterfaceMemberHandler) { - StubDispatcher* stubDispatcher = static_cast<StubDispatcher*>(findIterator->second); - dbusMessageHandled = stubDispatcher->dispatchDBusMessage(dbusMessage, stubSafety, *this); - } - - return dbusMessageHandled; - } - - virtual bool onInterfaceDBusFreedesktopPropertiesMessage(const DBusMessage& dbusMessage) { - DBusInputStream dbusInputStream(dbusMessage); - - if(dbusMessage.hasMemberName("Get")) { - return handleFreedesktopGet(dbusMessage, dbusInputStream); - } else if(dbusMessage.hasMemberName("Set")) { - return handleFreedesktopSet(dbusMessage, dbusInputStream); - } else if(dbusMessage.hasMemberName("GetAll")) { - return handleFreedesktopGetAll(dbusMessage, dbusInputStream); - } - - return false; - } - - virtual const StubDispatcherTable& getStubDispatcherTable() = 0; - virtual const StubAttributeTable& getStubAttributeTable() = 0; - - std::weak_ptr<_StubClass> stub_; - RemoteEventHandlerType* remoteEventHandler_; - private: - bool handleFreedesktopGet(const DBusMessage& dbusMessage, DBusInputStream& dbusInputStream) { - std::string interfaceName; - std::string attributeName; - dbusInputStream >> interfaceName; - dbusInputStream >> attributeName; - - if (dbusInputStream.hasError()) { - return false; - } - - auto attributeDispatcherIterator = getStubAttributeTable().find(attributeName); - // check, if we want to access with a valid attribute name - if (attributeDispatcherIterator == getStubAttributeTable().end()) { - return false; - } - - //To prevent the destruction of the stub whilst still handling a message - auto stubSafety = stub_.lock(); - if (stubSafety) { - StubDispatcher* getterDispatcher = static_cast<StubDispatcher*>(attributeDispatcherIterator->second.getter); - assert(getterDispatcher != NULL); // all attributes have at least a getter - return (getterDispatcher->dispatchDBusMessage(dbusMessage, stubSafety, *this)); - } - - return false; - } - - bool handleFreedesktopSet(const DBusMessage& dbusMessage, DBusInputStream& dbusInputStream) { - std::string interfaceName; - std::string attributeName; - dbusInputStream >> interfaceName; - dbusInputStream >> attributeName; - - if(dbusInputStream.hasError()) { - return false; - } - - auto attributeDispatcherIterator = getStubAttributeTable().find(attributeName); - // check, if we want to access with a valid attribute name - if(attributeDispatcherIterator == getStubAttributeTable().end()) { - return false; - } - - //To prevent the destruction of the stub whilst still handling a message - auto stubSafety = stub_.lock(); - if (stubSafety) { - StubDispatcher* setterDispatcher = static_cast<StubDispatcher*>(attributeDispatcherIterator->second.setter); - - if(setterDispatcher == NULL) { // readonly attributes do not have a setter - return false; - } - - return(setterDispatcher->dispatchDBusMessage(dbusMessage, stubSafety, *this)); - } - - return false; - } - - bool handleFreedesktopGetAll(const DBusMessage& dbusMessage, DBusInputStream& dbusInputStream) { - std::string interfaceName; - dbusInputStream >> interfaceName; - - if(dbusInputStream.hasError()) { - return false; - } - - DBusMessage dbusMessageReply = dbusMessage.createMethodReturn("a{sv}"); - DBusOutputStream dbusOutputStream(dbusMessageReply); - dbusOutputStream.beginWriteVectorOfSerializableStructs(getStubAttributeTable().size()); - - std::shared_ptr<DBusClientId> clientId = std::make_shared<DBusClientId>(std::string(dbusMessage.getSenderName())); - - auto stubSafety = stub_.lock(); - - for(auto attributeDispatcherIterator = getStubAttributeTable().begin(); attributeDispatcherIterator != getStubAttributeTable().end(); attributeDispatcherIterator++) { - //To prevent the destruction of the stub whilst still handling a message - if (stubSafety) { - DBusGetFreedesktopAttributeStubDispatcherBase<_StubClass>* const getterDispatcher = dynamic_cast<DBusGetFreedesktopAttributeStubDispatcherBase<_StubClass>*>(attributeDispatcherIterator->second.getter); - - if(getterDispatcher == NULL) { // readonly attributes do not have a setter - return false; - } - - dbusOutputStream << attributeDispatcherIterator->first; - getterDispatcher->dispatchDBusMessageAndAppendReply(dbusMessage, stubSafety, dbusOutputStream, clientId); - } - } - - dbusOutputStream.endWriteVector(); - dbusOutputStream.flush(); - return getDBusConnection()->sendDBusMessage(dbusMessageReply); - } -}; - -template< class > -struct DBusStubSignalHelper; - -template<template<class ...> class _In, class... _InArgs> -struct DBusStubSignalHelper<_In<_InArgs...>> { - - static inline bool sendSignal(const char* objectPath, - const char* interfaceName, - const char* signalName, - const char* signalSignature, - const std::shared_ptr<DBusProxyConnection>& dbusConnection, - const _InArgs&... inArgs) { - DBusMessage dbusMessage = DBusMessage::createSignal( - objectPath, - interfaceName, - signalName, - signalSignature); - - if (sizeof...(_InArgs) > 0) { - DBusOutputStream outputStream(dbusMessage); - const bool success = DBusSerializableArguments<_InArgs...>::serialize(outputStream, inArgs...); - if (!success) { - return false; - } - outputStream.flush(); - } - - const bool dbusMessageSent = dbusConnection->sendDBusMessage(dbusMessage); - return dbusMessageSent; - } - - template <typename _DBusStub = DBusStubAdapter> - static bool sendSignal(const _DBusStub& dbusStub, - const char* signalName, - const char* signalSignature, - const _InArgs&... inArgs) { - return(sendSignal(dbusStub.getObjectPath().c_str(), - dbusStub.getInterfaceName().c_str(), - signalName, - signalSignature, - dbusStub.getDBusConnection(), - inArgs...)); - } - - - template <typename _DBusStub = DBusStubAdapter> - static bool sendSignal( const char* target, - const _DBusStub& dbusStub, - const char* signalName, - const char* signalSignature, - const _InArgs&... inArgs) { - DBusMessage dbusMessage = DBusMessage::createSignal( - dbusStub.getObjectPath().c_str(), - dbusStub.getInterfaceName(), - signalName, - signalSignature); - - dbusMessage.setDestination(target); - - if (sizeof...(_InArgs) > 0) { - DBusOutputStream outputStream(dbusMessage); - const bool success = DBusSerializableArguments<_InArgs...>::serialize(outputStream, inArgs...); - if (!success) { - return false; - } - outputStream.flush(); - } - - const bool dbusMessageSent = dbusStub.getDBusConnection()->sendDBusMessage(dbusMessage); - return dbusMessageSent; - } -}; - -template< class > -struct DBusStubFreedesktopPropertiesSignalHelper; - -template<template<class ...> class _In, class _InArg> -struct DBusStubFreedesktopPropertiesSignalHelper<_In<_InArg>> { - template <typename _ValueType> - struct DBusPropertiesEntry: public CommonAPI::SerializableStruct { - std::string propertyName_; - DBusLegacyVariantWrapper<CommonAPI::Variant<_ValueType>> propertyValue_; - - DBusPropertiesEntry() = default; - DBusPropertiesEntry(const std::string& propertyName, - const DBusLegacyVariantWrapper<CommonAPI::Variant<_ValueType>>& propertyValue): - propertyName_(propertyName), - propertyValue_(propertyValue) { - }; - - virtual void readFromInputStream(CommonAPI::InputStream& inputStream) { - inputStream >> propertyName_; - inputStream >> propertyValue_; - } - - virtual void writeToOutputStream(CommonAPI::OutputStream& outputStream) const { - outputStream << propertyName_; - outputStream << propertyValue_; - } - - static inline void writeToTypeOutputStream(CommonAPI::TypeOutputStream& typeOutputStream) { - typeOutputStream.writeStringType(); - typeOutputStream.writeVariantType(); - } - - }; - - template <typename _DBusStub = DBusStubAdapter> - static bool sendPropertiesChangedSignal(const _DBusStub& dbusStub, const std::string& propertyName, const _InArg& inArg) { - const std::vector<std::string> invalidatedProperties; - const std::vector<DBusPropertiesEntry<_InArg>> changedProperties = {wrapValue(propertyName, inArg)}; - - return DBusStubSignalHelper<_In<const std::string, std::vector<DBusPropertiesEntry<_InArg>>, std::vector<std::string>>>:: - sendSignal(dbusStub.getObjectPath().c_str(), - "org.freedesktop.DBus.Properties", - "PropertiesChanged", - "sa{sv}as", - dbusStub.getDBusConnection(), - dbusStub.getInterfaceName(), - changedProperties, - invalidatedProperties); - } -private: - template <typename _ValueType> - static DBusPropertiesEntry<_ValueType> wrapValue(const std::string& propertyName, _ValueType value) { - CommonAPI::Variant<_ValueType> returnVariant(value); - - DBusLegacyVariantWrapper<CommonAPI::Variant<_ValueType>> wrappedReturnVariant; - wrappedReturnVariant.contained_ = returnVariant; - - DBusPropertiesEntry<_ValueType> returnEntry(propertyName, wrappedReturnVariant); - - return returnEntry; - } -}; - -template< class, class > -class DBusMethodStubDispatcher; - -template < - typename _StubClass, - template <class...> class _In, class... _InArgs> -class DBusMethodStubDispatcher<_StubClass, _In<_InArgs...> >: public DBusStubAdapterHelper<_StubClass>::StubDispatcher { - public: - typedef DBusStubAdapterHelper<_StubClass> DBusStubAdapterHelperType; - typedef void (_StubClass::*_StubFunctor)(std::shared_ptr<CommonAPI::ClientId>, _InArgs...); - - DBusMethodStubDispatcher(_StubFunctor stubFunctor): - stubFunctor_(stubFunctor) { - } - - bool dispatchDBusMessage(const DBusMessage& dbusMessage, const std::shared_ptr<_StubClass>& stub, DBusStubAdapterHelperType& dbusStubAdapterHelper) { - return handleDBusMessage(dbusMessage, stub, dbusStubAdapterHelper, typename make_sequence<sizeof...(_InArgs)>::type()); - } - - private: - template <int... _InArgIndices> - inline bool handleDBusMessage(const DBusMessage& dbusMessage, - const std::shared_ptr<_StubClass>& stub, - DBusStubAdapterHelperType& dbusStubAdapterHelper, - index_sequence<_InArgIndices...>) const { - std::tuple<_InArgs...> argTuple; - - if (sizeof...(_InArgs) > 0) { - DBusInputStream dbusInputStream(dbusMessage); - const bool success = DBusSerializableArguments<_InArgs...>::deserialize(dbusInputStream, std::get<_InArgIndices>(argTuple)...); - if (!success) - return false; - } - - std::shared_ptr<DBusClientId> clientId = std::make_shared<DBusClientId>(std::string(dbusMessage.getSenderName())); - - (stub.get()->*stubFunctor_)(clientId, std::move(std::get<_InArgIndices>(argTuple))...); - - return true; - } - - _StubFunctor stubFunctor_; -}; - - -template< class, class, class > -class DBusMethodWithReplyStubDispatcher; - -template < - typename _StubClass, - template <class...> class _In, class... _InArgs, - template <class...> class _Out, class... _OutArgs> -class DBusMethodWithReplyStubDispatcher<_StubClass, _In<_InArgs...>, _Out<_OutArgs...> >: - public DBusStubAdapterHelper<_StubClass>::StubDispatcher { - public: - typedef DBusStubAdapterHelper<_StubClass> DBusStubAdapterHelperType; - typedef void (_StubClass::*_StubFunctor)(std::shared_ptr<CommonAPI::ClientId>, _InArgs..., _OutArgs&...); - - DBusMethodWithReplyStubDispatcher(_StubFunctor stubFunctor, const char* dbusReplySignature): - stubFunctor_(stubFunctor), - dbusReplySignature_(dbusReplySignature) { - } - - bool dispatchDBusMessage(const DBusMessage& dbusMessage, const std::shared_ptr<_StubClass>& stub, DBusStubAdapterHelperType& dbusStubAdapterHelper) { - std::tuple<_InArgs..., _OutArgs...> argTuple; - return handleDBusMessage( - dbusMessage, - stub, - dbusStubAdapterHelper, - typename make_sequence_range<sizeof...(_InArgs), 0>::type(), - typename make_sequence_range<sizeof...(_OutArgs), sizeof...(_InArgs)>::type(),argTuple); - } - private: - template <int... _InArgIndices, int... _OutArgIndices> - inline bool handleDBusMessage(const DBusMessage& dbusMessage, - const std::shared_ptr<_StubClass>& stub, - DBusStubAdapterHelperType& dbusStubAdapterHelper, - index_sequence<_InArgIndices...>, - index_sequence<_OutArgIndices...>, - std::tuple<_InArgs..., _OutArgs...> argTuple) const { - - if (sizeof...(_InArgs) > 0) { - DBusInputStream dbusInputStream(dbusMessage); - const bool success = DBusSerializableArguments<_InArgs...>::deserialize(dbusInputStream, std::get<_InArgIndices>(argTuple)...); - if (!success) - return false; - } - - std::shared_ptr<DBusClientId> clientId = std::make_shared<DBusClientId>(std::string(dbusMessage.getSenderName())); - - (stub.get()->*stubFunctor_)(clientId, std::move(std::get<_InArgIndices>(argTuple))..., std::get<_OutArgIndices>(argTuple)...); - - DBusMessage dbusMessageReply = dbusMessage.createMethodReturn(dbusReplySignature_); - - if (sizeof...(_OutArgs) > 0) { - DBusOutputStream dbusOutputStream(dbusMessageReply); - const bool success = DBusSerializableArguments<_OutArgs...>::serialize(dbusOutputStream, std::get<_OutArgIndices>(argTuple)...); - if (!success) - return false; - - dbusOutputStream.flush(); - } - - return dbusStubAdapterHelper.getDBusConnection()->sendDBusMessage(dbusMessageReply); - } - - _StubFunctor stubFunctor_; - const char* dbusReplySignature_; -}; - -template< class, class, class, class > -class DBusMethodWithReplyAdapterDispatcher; - -template < - typename _StubClass, - typename _StubAdapterClass, - template <class...> class _In, class... _InArgs, - template <class...> class _Out, class... _OutArgs> -class DBusMethodWithReplyAdapterDispatcher<_StubClass, _StubAdapterClass, _In<_InArgs...>, _Out<_OutArgs...> >: - public DBusStubAdapterHelper<_StubClass>::StubDispatcher { - public: - typedef DBusStubAdapterHelper<_StubClass> DBusStubAdapterHelperType; - typedef void (_StubAdapterClass::*_StubFunctor)(std::shared_ptr<CommonAPI::ClientId>, _InArgs..., _OutArgs&...); - typedef typename CommonAPI::Stub<typename DBusStubAdapterHelperType::StubAdapterType, typename _StubClass::RemoteEventType> StubType; - - DBusMethodWithReplyAdapterDispatcher(_StubFunctor stubFunctor, const char* dbusReplySignature): - stubFunctor_(stubFunctor), - dbusReplySignature_(dbusReplySignature) { - } - - bool dispatchDBusMessage(const DBusMessage& dbusMessage, const std::shared_ptr<_StubClass>& stub, DBusStubAdapterHelperType& dbusStubAdapterHelper) { - std::tuple<_InArgs..., _OutArgs...> argTuple; - return handleDBusMessage( - dbusMessage, - stub, - dbusStubAdapterHelper, - typename make_sequence_range<sizeof...(_InArgs), 0>::type(), - typename make_sequence_range<sizeof...(_OutArgs), sizeof...(_InArgs)>::type(),argTuple); - } - - private: - template <int... _InArgIndices, int... _OutArgIndices> - inline bool handleDBusMessage(const DBusMessage& dbusMessage, - const std::shared_ptr<_StubClass>& stub, - DBusStubAdapterHelperType& dbusStubAdapterHelper, - index_sequence<_InArgIndices...>, - index_sequence<_OutArgIndices...>, - std::tuple<_InArgs..., _OutArgs...> argTuple) const { - - if (sizeof...(_InArgs) > 0) { - DBusInputStream dbusInputStream(dbusMessage); - const bool success = DBusSerializableArguments<_InArgs...>::deserialize(dbusInputStream, std::get<_InArgIndices>(argTuple)...); - if (!success) - return false; - } - - std::shared_ptr<DBusClientId> clientId = std::make_shared<DBusClientId>(std::string(dbusMessage.getSenderName())); - - (stub->StubType::getStubAdapter().get()->*stubFunctor_)(clientId, std::move(std::get<_InArgIndices>(argTuple))..., std::get<_OutArgIndices>(argTuple)...); - DBusMessage dbusMessageReply = dbusMessage.createMethodReturn(dbusReplySignature_); - - if (sizeof...(_OutArgs) > 0) { - DBusOutputStream dbusOutputStream(dbusMessageReply); - const bool success = DBusSerializableArguments<_OutArgs...>::serialize(dbusOutputStream, std::get<_OutArgIndices>(argTuple)...); - if (!success) - return false; - - dbusOutputStream.flush(); - } - - return dbusStubAdapterHelper.getDBusConnection()->sendDBusMessage(dbusMessageReply); - } - - _StubFunctor stubFunctor_; - const char* dbusReplySignature_; -}; - - -template <typename _StubClass, typename _AttributeType> -class DBusGetAttributeStubDispatcher: public virtual DBusStubAdapterHelper<_StubClass>::StubDispatcher { - public: - typedef DBusStubAdapterHelper<_StubClass> DBusStubAdapterHelperType; - typedef const _AttributeType& (_StubClass::*GetStubFunctor)(std::shared_ptr<CommonAPI::ClientId>); - - DBusGetAttributeStubDispatcher(GetStubFunctor getStubFunctor, const char* dbusSignature): - getStubFunctor_(getStubFunctor), - dbusSignature_(dbusSignature) { - } - - virtual ~DBusGetAttributeStubDispatcher() {}; - - bool dispatchDBusMessage(const DBusMessage& dbusMessage, const std::shared_ptr<_StubClass>& stub, DBusStubAdapterHelperType& dbusStubAdapterHelper) { - return sendAttributeValueReply(dbusMessage, stub, dbusStubAdapterHelper); - } - protected: - virtual bool sendAttributeValueReply(const DBusMessage& dbusMessage, const std::shared_ptr<_StubClass>& stub, DBusStubAdapterHelperType& dbusStubAdapterHelper) { - DBusMessage dbusMessageReply = dbusMessage.createMethodReturn(dbusSignature_); - DBusOutputStream dbusOutputStream(dbusMessageReply); - - std::shared_ptr<DBusClientId> clientId = std::make_shared<DBusClientId>(std::string(dbusMessage.getSenderName())); - - dbusOutputStream << (stub.get()->*getStubFunctor_)(clientId); - dbusOutputStream.flush(); - - return dbusStubAdapterHelper.getDBusConnection()->sendDBusMessage(dbusMessageReply); - } - - GetStubFunctor getStubFunctor_; - const char* dbusSignature_; -}; - -template <typename _StubClass> -class DBusGetFreedesktopAttributeStubDispatcherBase { -public: - virtual ~DBusGetFreedesktopAttributeStubDispatcherBase() {} - virtual void dispatchDBusMessageAndAppendReply(const DBusMessage& dbusMessage, const std::shared_ptr<_StubClass>& stub, DBusOutputStream& dbusOutputStream, const std::shared_ptr<DBusClientId>& clientId) = 0; -}; - -template <typename _StubClass, typename _AttributeType> -class DBusGetFreedesktopAttributeStubDispatcher: public virtual DBusGetAttributeStubDispatcher<_StubClass, _AttributeType>, public virtual DBusGetFreedesktopAttributeStubDispatcherBase<_StubClass> { -public: - typedef DBusStubAdapterHelper<_StubClass> DBusStubAdapterHelperType; - typedef typename DBusGetAttributeStubDispatcher<_StubClass, _AttributeType>::GetStubFunctor GetStubFunctor; - DBusGetFreedesktopAttributeStubDispatcher(GetStubFunctor getStubFunctor) : - DBusGetAttributeStubDispatcher<_StubClass, _AttributeType>(getStubFunctor, "v") { - } - - virtual ~DBusGetFreedesktopAttributeStubDispatcher() {}; - - void dispatchDBusMessageAndAppendReply(const DBusMessage& dbusMessage, const std::shared_ptr<_StubClass>& stub, DBusOutputStream& dbusOutputStream, const std::shared_ptr<DBusClientId>& clientId) { - CommonAPI::Variant<_AttributeType> returnVariant((stub.get()->*(DBusGetAttributeStubDispatcher<_StubClass, _AttributeType>::getStubFunctor_))(clientId)); - - DBusLegacyVariantWrapper<CommonAPI::Variant<_AttributeType>> wrappedReturnVariant; - wrappedReturnVariant.contained_ = returnVariant; - - dbusOutputStream << wrappedReturnVariant; - } -protected: - virtual bool sendAttributeValueReply(const DBusMessage& dbusMessage, const std::shared_ptr<_StubClass>& stub, DBusStubAdapterHelperType& dbusStubAdapterHelper) { - DBusMessage dbusMessageReply = dbusMessage.createMethodReturn(DBusGetAttributeStubDispatcher<_StubClass, _AttributeType>::dbusSignature_); - DBusOutputStream dbusOutputStream(dbusMessageReply); - - std::shared_ptr<DBusClientId> clientId = std::make_shared<DBusClientId>(std::string(dbusMessage.getSenderName())); - - CommonAPI::Variant<_AttributeType> returnVariant((stub.get()->*(DBusGetAttributeStubDispatcher<_StubClass, _AttributeType>::getStubFunctor_))(clientId)); - - DBusLegacyVariantWrapper<CommonAPI::Variant<_AttributeType>> wrappedReturnVariant; - wrappedReturnVariant.contained_ = returnVariant; - dbusOutputStream << wrappedReturnVariant; - dbusOutputStream.flush(); - - return dbusStubAdapterHelper.getDBusConnection()->sendDBusMessage(dbusMessageReply); - } -}; - - -template <typename _StubClass, typename _AttributeType> -class DBusSetAttributeStubDispatcher: public virtual DBusGetAttributeStubDispatcher<_StubClass, _AttributeType> { - public: - typedef typename DBusGetAttributeStubDispatcher<_StubClass, _AttributeType>::DBusStubAdapterHelperType DBusStubAdapterHelperType; - typedef typename DBusStubAdapterHelperType::RemoteEventHandlerType RemoteEventHandlerType; - - typedef typename DBusGetAttributeStubDispatcher<_StubClass, _AttributeType>::GetStubFunctor GetStubFunctor; - typedef bool (RemoteEventHandlerType::*OnRemoteSetFunctor)(std::shared_ptr<CommonAPI::ClientId>, _AttributeType); - typedef void (RemoteEventHandlerType::*OnRemoteChangedFunctor)(); - - DBusSetAttributeStubDispatcher(GetStubFunctor getStubFunctor, - OnRemoteSetFunctor onRemoteSetFunctor, - OnRemoteChangedFunctor onRemoteChangedFunctor, - const char* dbusSignature) : - DBusGetAttributeStubDispatcher<_StubClass, _AttributeType>(getStubFunctor, dbusSignature), - onRemoteSetFunctor_(onRemoteSetFunctor), - onRemoteChangedFunctor_(onRemoteChangedFunctor) { - } - - virtual ~DBusSetAttributeStubDispatcher() {}; - - bool dispatchDBusMessage(const DBusMessage& dbusMessage, const std::shared_ptr<_StubClass>& stub, DBusStubAdapterHelperType& dbusStubAdapterHelper) { - bool attributeValueChanged; - - if (!setAttributeValue(dbusMessage, stub, dbusStubAdapterHelper, attributeValueChanged)) - return false; - - if (attributeValueChanged) - notifyOnRemoteChanged(dbusStubAdapterHelper); - - return true; - } - - protected: - virtual _AttributeType retreiveAttributeValue(const DBusMessage& dbusMessage, bool& errorOccured) { - errorOccured = false; - - DBusInputStream dbusInputStream(dbusMessage); - _AttributeType attributeValue; - dbusInputStream >> attributeValue; - - if (dbusInputStream.hasError()) { - errorOccured = true; - } - - return attributeValue; - } - - inline bool setAttributeValue(const DBusMessage& dbusMessage, - const std::shared_ptr<_StubClass>& stub, - DBusStubAdapterHelperType& dbusStubAdapterHelper, - bool& attributeValueChanged) { - bool errorOccured; - _AttributeType attributeValue = retreiveAttributeValue(dbusMessage, errorOccured); - - if(errorOccured) { - return false; - } - - std::shared_ptr<DBusClientId> clientId = std::make_shared<DBusClientId>(std::string(dbusMessage.getSenderName())); - - attributeValueChanged = (dbusStubAdapterHelper.getRemoteEventHandler()->*onRemoteSetFunctor_)(clientId, std::move(attributeValue)); - - return this->sendAttributeValueReply(dbusMessage, stub, dbusStubAdapterHelper); - } - - inline void notifyOnRemoteChanged(DBusStubAdapterHelperType& dbusStubAdapterHelper) { - (dbusStubAdapterHelper.getRemoteEventHandler()->*onRemoteChangedFunctor_)(); - } - - inline const _AttributeType& getAttributeValue(std::shared_ptr<CommonAPI::ClientId> clientId, const std::shared_ptr<_StubClass>& stub) { - return (stub.get()->*(this->getStubFunctor_))(clientId); - } - - const OnRemoteSetFunctor onRemoteSetFunctor_; - const OnRemoteChangedFunctor onRemoteChangedFunctor_; -}; - -template <typename _StubClass, typename _AttributeType> -class DBusSetFreedesktopAttributeStubDispatcher: public virtual DBusGetFreedesktopAttributeStubDispatcher<_StubClass, _AttributeType>, public virtual DBusSetAttributeStubDispatcher<_StubClass, _AttributeType> { -public: - typedef typename DBusGetAttributeStubDispatcher<_StubClass, _AttributeType>::GetStubFunctor GetStubFunctor; - typedef typename DBusGetAttributeStubDispatcher<_StubClass, _AttributeType>::DBusStubAdapterHelperType DBusStubAdapterHelperType; - typedef typename DBusStubAdapterHelperType::RemoteEventHandlerType RemoteEventHandlerType; - typedef bool (RemoteEventHandlerType::*OnRemoteSetFunctor)(std::shared_ptr<CommonAPI::ClientId>, _AttributeType); - typedef void (RemoteEventHandlerType::*OnRemoteChangedFunctor)(); - - DBusSetFreedesktopAttributeStubDispatcher(GetStubFunctor getStubFunctor, - OnRemoteSetFunctor onRemoteSetFunctor, - OnRemoteChangedFunctor onRemoteChangedFunctor) : - DBusGetAttributeStubDispatcher<_StubClass, _AttributeType>( - getStubFunctor, - "v"), - DBusGetFreedesktopAttributeStubDispatcher<_StubClass, _AttributeType>( - getStubFunctor), - DBusSetAttributeStubDispatcher<_StubClass, _AttributeType>( - getStubFunctor, - onRemoteSetFunctor, - onRemoteChangedFunctor, - "v") { - } - - virtual ~DBusSetFreedesktopAttributeStubDispatcher() {}; -protected: - virtual _AttributeType retreiveAttributeValue(const DBusMessage& dbusMessage, bool& errorOccured) { - errorOccured = false; - std::string interfaceName; - std::string attributeName; - - DBusInputStream dbusInputStream(dbusMessage); - DBusLegacyVariantWrapper<CommonAPI::Variant<_AttributeType>> variantValue; - dbusInputStream >> interfaceName; // skip over interface and attribute name - dbusInputStream >> attributeName; - dbusInputStream >> variantValue; - _AttributeType attributeValue = variantValue.contained_.template get<_AttributeType>() ; - - if (dbusInputStream.hasError()) { - errorOccured = true; - } - - return attributeValue; - } -}; - -template <typename _StubClass, typename _AttributeType> -class DBusSetObservableAttributeStubDispatcher: public virtual DBusSetAttributeStubDispatcher<_StubClass, _AttributeType> { - public: - typedef typename DBusSetAttributeStubDispatcher<_StubClass, _AttributeType>::DBusStubAdapterHelperType DBusStubAdapterHelperType; - typedef typename DBusStubAdapterHelperType::StubAdapterType StubAdapterType; - typedef typename DBusSetAttributeStubDispatcher<_StubClass, _AttributeType>::GetStubFunctor GetStubFunctor; - typedef typename DBusSetAttributeStubDispatcher<_StubClass, _AttributeType>::OnRemoteSetFunctor OnRemoteSetFunctor; - typedef typename DBusSetAttributeStubDispatcher<_StubClass, _AttributeType>::OnRemoteChangedFunctor OnRemoteChangedFunctor; - typedef typename CommonAPI::Stub<StubAdapterType, typename _StubClass::RemoteEventType> StubType; - typedef void (StubAdapterType::*FireChangedFunctor)(const _AttributeType&); - - DBusSetObservableAttributeStubDispatcher(GetStubFunctor getStubFunctor, - OnRemoteSetFunctor onRemoteSetFunctor, - OnRemoteChangedFunctor onRemoteChangedFunctor, - FireChangedFunctor fireChangedFunctor, - const char* dbusSignature) : - DBusGetAttributeStubDispatcher<_StubClass, _AttributeType>(getStubFunctor, dbusSignature), - DBusSetAttributeStubDispatcher<_StubClass, _AttributeType>(getStubFunctor, - onRemoteSetFunctor, - onRemoteChangedFunctor, - dbusSignature), - fireChangedFunctor_(fireChangedFunctor) { - } - - virtual ~DBusSetObservableAttributeStubDispatcher() {}; - - bool dispatchDBusMessage(const DBusMessage& dbusMessage, const std::shared_ptr<_StubClass>& stub, DBusStubAdapterHelperType& dbusStubAdapterHelper) { - bool attributeValueChanged; - if (!this->setAttributeValue(dbusMessage, stub, dbusStubAdapterHelper, attributeValueChanged)) - return false; - - if (attributeValueChanged) { - std::shared_ptr<DBusClientId> clientId = std::make_shared<DBusClientId>(std::string(dbusMessage.getSenderName())); - fireAttributeValueChanged(clientId, dbusStubAdapterHelper, stub); - this->notifyOnRemoteChanged(dbusStubAdapterHelper); - } - return true; - } -protected: - virtual void fireAttributeValueChanged(std::shared_ptr<CommonAPI::ClientId> clientId, - DBusStubAdapterHelperType& dbusStubAdapterHelper, - const std::shared_ptr<_StubClass> stub) { - (stub->StubType::getStubAdapter().get()->*fireChangedFunctor_)(this->getAttributeValue(clientId, stub)); - } - - const FireChangedFunctor fireChangedFunctor_; -}; - -template <typename _StubClass, typename _AttributeType> -class DBusSetFreedesktopObservableAttributeStubDispatcher: public virtual DBusSetFreedesktopAttributeStubDispatcher<_StubClass, _AttributeType>, public virtual DBusSetObservableAttributeStubDispatcher<_StubClass, _AttributeType> { -public: - typedef typename DBusSetFreedesktopAttributeStubDispatcher<_StubClass, _AttributeType>::DBusStubAdapterHelperType DBusStubAdapterHelperType; - typedef typename DBusStubAdapterHelperType::StubAdapterType StubAdapterType; - typedef typename DBusSetFreedesktopAttributeStubDispatcher<_StubClass, _AttributeType>::GetStubFunctor GetStubFunctor; - typedef typename DBusSetFreedesktopAttributeStubDispatcher<_StubClass, _AttributeType>::OnRemoteSetFunctor OnRemoteSetFunctor; - typedef typename DBusSetFreedesktopAttributeStubDispatcher<_StubClass, _AttributeType>::OnRemoteChangedFunctor OnRemoteChangedFunctor; - typedef void (StubAdapterType::*FireChangedFunctor)(const _AttributeType&); - - DBusSetFreedesktopObservableAttributeStubDispatcher(GetStubFunctor getStubFunctor, - OnRemoteSetFunctor onRemoteSetFunctor, - OnRemoteChangedFunctor onRemoteChangedFunctor, - FireChangedFunctor fireChangedFunctor) : - DBusGetAttributeStubDispatcher<_StubClass, _AttributeType>(getStubFunctor, "v"), - DBusGetFreedesktopAttributeStubDispatcher<_StubClass, _AttributeType>(getStubFunctor), - DBusSetAttributeStubDispatcher<_StubClass, _AttributeType>(getStubFunctor, - onRemoteSetFunctor, - onRemoteChangedFunctor, - "v"), - DBusSetFreedesktopAttributeStubDispatcher<_StubClass, _AttributeType>(getStubFunctor, - onRemoteSetFunctor, - onRemoteChangedFunctor), - DBusSetObservableAttributeStubDispatcher<_StubClass, _AttributeType>(getStubFunctor, - onRemoteSetFunctor, - onRemoteChangedFunctor, - fireChangedFunctor, - "v") { - } -}; - -} // namespace DBus -} // namespace CommonAPI - -#endif // COMMONAPI_DBUS_DBUS_STUB_ADAPTER_HELPER_H_ diff --git a/src/CommonAPI/DBus/DBusUtils.h b/src/CommonAPI/DBus/DBusUtils.h deleted file mode 100644 index 3b74ef5..0000000 --- a/src/CommonAPI/DBus/DBusUtils.h +++ /dev/null @@ -1,39 +0,0 @@ -/* Copyright (C) 2013 BMW Group - * Author: Manfred Bathelt (manfred.bathelt@bmw.de) - * Author: Juergen Gehring (juergen.gehring@bmw.de) - * 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/. */ - -#if !defined (COMMONAPI_INTERNAL_COMPILATION) -#error "Only <CommonAPI/CommonAPI.h> can be included directly, this file may disappear or change contents." -#endif - -#ifndef DBUSUTILS_H_ -#define DBUSUTILS_H_ - -#include <future> - -namespace CommonAPI { -namespace DBus { - -//In gcc 4.4.1, the enumeration "std::future_status" is defined, but the return values of some functions -//are bool where the same functions in gcc 4.6. return a value from this enum. This template is a way -//to ensure compatibility for this issue. -template<typename _FutureWaitType> -inline bool checkReady(_FutureWaitType&); - -template<> -inline bool checkReady<bool>(bool& returnedValue) { - return returnedValue; -} - -template<> -inline bool checkReady<std::future_status>(std::future_status& returnedValue) { - return returnedValue == std::future_status::ready; -} - -} //namespace DBus -} //namespace CommonAPI - -#endif /* DBUSUTILS_H_ */ |