diff options
Diffstat (limited to 'src/CommonAPI/DBus/DBusFactory.cpp')
-rw-r--r-- | src/CommonAPI/DBus/DBusFactory.cpp | 459 |
1 files changed, 294 insertions, 165 deletions
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 |