* 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 "DBusServiceRegistry.h"
#include "DBusUtils.h"
-#include <algorithm>
#include <cassert>
-#include <iostream>
-#include <dbus/dbus.h>
-#include <functional>
-#include <CommonAPI/Event.h>
+
namespace CommonAPI {
namespace DBus {
dbusProxy_(dbusProxy) {
}
-void DBusProxyStatusEvent::onFirstListenerAdded(const Listener& listener) {
- auto serviceStatusListener = std::bind(
- &DBusProxyStatusEvent::onServiceAvailableSignalHandler,
- this,
- std::placeholders::_1,
- std::placeholders::_2);
-
- subscription_ = dbusProxy_->getDBusConnection()->getDBusServiceRegistry()->getServiceStatusEvent().subscribe(
- dbusProxy_->dbusBusName_ + ":" + dbusProxy_->dbusObjectPath_ + ":" + dbusProxy_->interfaceName_,
- serviceStatusListener);
+void DBusProxyStatusEvent::onListenerAdded(const CancellableListener& listener) {
+ if (dbusProxy_->isAvailable())
+ listener(AvailabilityStatus::AVAILABLE);
}
-void DBusProxyStatusEvent::onLastListenerRemoved(const Listener& listener) {
- dbusProxy_->getDBusConnection()->getDBusServiceRegistry()->getServiceStatusEvent().unsubscribe(subscription_);
+
+DBusProxy::DBusProxy(const std::string& commonApiAddress,
+ const std::string& dbusInterfaceName,
+ const std::string& dbusBusName,
+ const std::string& dbusObjectPath,
+ const std::shared_ptr<DBusProxyConnection>& dbusConnection):
+ DBusProxyBase(dbusConnection),
+ commonApiServiceId_(split(commonApiAddress, ':')[1]),
+ commonApiParticipantId_(split(commonApiAddress, ':')[2]),
+ dbusBusName_(dbusBusName),
+ dbusObjectPath_(dbusObjectPath),
+ dbusInterfaceName_(dbusInterfaceName),
+ dbusProxyStatusEvent_(this),
+ availabilityStatus_(AvailabilityStatus::UNKNOWN),
+ interfaceVersionAttribute_(*this, "getInterfaceVersion", "uu"),
+ dbusServiceRegistry_(dbusConnection->getDBusServiceRegistry()) {
+
+ const std::string commonApiDomain = split(commonApiAddress, ':')[0];
+ assert(commonApiDomain == "local");
+
+ dbusServiceRegistrySubscription_ = dbusServiceRegistry_->subscribeAvailabilityListener(
+ commonApiAddress,
+ std::bind(&DBusProxy::onDBusServiceInstanceStatus, this, std::placeholders::_1));
}
-SubscriptionStatus DBusProxyStatusEvent::onServiceAvailableSignalHandler(const std::string& name,
- const AvailabilityStatus& availabilityStatus) {
- AvailabilityStatus availability = availabilityStatus;
+DBusProxy::~DBusProxy() {
+ dbusServiceRegistry_->unsubscribeAvailabilityListener(
+ getAddress(),
+ dbusServiceRegistrySubscription_);
+}
- return notifyListeners(availability);
+bool DBusProxy::isAvailable() const {
+ return (availabilityStatus_ == AvailabilityStatus::AVAILABLE);
}
-const std::string DBusProxy::domain_ = "local";
+bool DBusProxy::isAvailableBlocking() const {
+ if (availabilityStatus_ == AvailabilityStatus::UNKNOWN) {
+ std::chrono::milliseconds singleWaitDuration(2);
-DBusProxy::DBusProxy(const std::string& dbusBusName,
- const std::string& dbusObjectPath,
- const std::string& interfaceName,
- const std::shared_ptr<DBusProxyConnection>& dbusProxyConnection) :
- dbusBusName_(dbusBusName),
- dbusObjectPath_(dbusObjectPath),
- interfaceName_(interfaceName),
- statusEvent_(this),
- interfaceVersionAttribute_(*this, "getInterfaceVersion"),
- available_(false),
- availableSet_(false),
- connection_(dbusProxyConnection) {
-}
-
-DBusProxy::DBusProxy(const std::string& dbusBusName,
- const std::string& dbusObjectPath,
- const std::string& interfaceName,
- const std::shared_ptr<DBusProxyConnection>& connection,
- const bool isAlwaysAvailable) :
- dbusBusName_(dbusBusName),
- dbusObjectPath_(dbusObjectPath),
- interfaceName_(interfaceName),
- statusEvent_(this),
- interfaceVersionAttribute_(*this, "getInterfaceVersion"),
- available_(isAlwaysAvailable),
- availableSet_(isAlwaysAvailable),
- connection_(connection) {
+ // Wait for the service registry
+ while (availabilityStatus_ == AvailabilityStatus::UNKNOWN) {
+ std::this_thread::sleep_for(singleWaitDuration);
+ }
+ }
+
+ return isAvailable();
}
-std::string DBusProxy::getAddress() const {
- return domain_ + ":" + interfaceName_ + ":" + dbusBusName_;
+ProxyStatusEvent& DBusProxy::getProxyStatusEvent() {
+ return dbusProxyStatusEvent_;
}
-const std::string& DBusProxy::getDomain() const {
- return domain_;
+InterfaceVersionAttribute& DBusProxy::getInterfaceVersionAttribute() {
+ return interfaceVersionAttribute_;
}
-const std::string& DBusProxy::getServiceId() const {
- return getInterfaceName();
+void DBusProxy::onDBusServiceInstanceStatus(const AvailabilityStatus& availabilityStatus) {
+ availabilityStatus_ = availabilityStatus;
+ dbusProxyStatusEvent_.notifyListeners(availabilityStatus);
}
-const std::string& DBusProxy::getInstanceId() const {
+const std::string& DBusProxy::getDBusBusName() const {
return dbusBusName_;
}
-
-bool DBusProxy::isAvailable() const {
- if (!availableSet_) {
- auto status = getDBusConnection()->getDBusServiceRegistry()->getReadyFuture().wait_for(std::chrono::milliseconds(1));
- if (checkReady(status)) {
- available_ = getDBusConnection()->getDBusServiceRegistry()->isServiceInstanceAlive(getAddress());
- availableSet_ = true;
- }
- }
- return available_;
+const std::string& DBusProxy::getDBusObjectPath() const {
+ return dbusObjectPath_;
}
-bool DBusProxy::isAvailableBlocking() const {
+const std::string& DBusProxy::getInterfaceName() const {
+ return dbusInterfaceName_;
+}
- if (!availableSet_) {
- getDBusConnection()->getDBusServiceRegistry()->getReadyFuture().wait();
- available_ = getDBusConnection()->getDBusServiceRegistry()->isServiceInstanceAlive(getAddress());
- availableSet_ = true;
- }
- return available_;
+const std::string& DBusProxy::getDomain() const {
+ return commonApiDomain_;
}
-ProxyStatusEvent& DBusProxy::getProxyStatusEvent() {
- return statusEvent_;
+const std::string& DBusProxy::getServiceId() const {
+ return commonApiServiceId_;
}
-InterfaceVersionAttribute& DBusProxy::getInterfaceVersionAttribute() {
- return interfaceVersionAttribute_;
+const std::string& DBusProxy::getInstanceId() const {
+ return commonApiParticipantId_;
}
-DBusMessage DBusProxy::createMethodCall(const char* methodName,
- const char* methodSignature) const {
- return DBusMessage::createMethodCall(
- dbusBusName_.c_str(),
- dbusObjectPath_.c_str(),
- getInterfaceName().c_str(),
- methodName,
- methodSignature);
+std::string DBusProxy::getAddress() const {
+ return commonApiDomain_ + ":" + commonApiServiceId_ + ":" + commonApiParticipantId_;
}
} // namespace DBus