2017-11-27 14:13:55 +01:00
|
|
|
/**
|
2022-07-05 17:08:35 +02:00
|
|
|
* (C) 2016 - 2021 KISTLER INSTRUMENTE AG, Winterthur, Switzerland
|
2024-04-16 22:48:34 +02:00
|
|
|
* (C) 2016 - 2024 Stanislav Angelovic <stanislav.angelovic@protonmail.com>
|
2017-11-27 14:13:55 +01:00
|
|
|
*
|
2019-04-09 21:28:07 +02:00
|
|
|
* @file Proxy.cpp
|
2017-11-27 14:13:55 +01:00
|
|
|
*
|
|
|
|
|
* Created on: Nov 8, 2016
|
|
|
|
|
* Project: sdbus-c++
|
|
|
|
|
* Description: High-level D-Bus IPC C++ library based on sd-bus
|
|
|
|
|
*
|
|
|
|
|
* This file is part of sdbus-c++.
|
|
|
|
|
*
|
|
|
|
|
* sdbus-c++ is free software; you can redistribute it and/or modify it
|
|
|
|
|
* under the terms of the GNU Lesser General Public License as published by
|
|
|
|
|
* the Free Software Foundation, either version 2.1 of the License, or
|
|
|
|
|
* (at your option) any later version.
|
|
|
|
|
*
|
|
|
|
|
* sdbus-c++ is distributed in the hope that it will be useful,
|
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
* GNU Lesser General Public License for more details.
|
|
|
|
|
*
|
|
|
|
|
* You should have received a copy of the GNU Lesser General Public License
|
|
|
|
|
* along with sdbus-c++. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
*/
|
|
|
|
|
|
2019-04-09 21:28:07 +02:00
|
|
|
#include "Proxy.h"
|
2017-11-27 14:13:55 +01:00
|
|
|
#include "IConnection.h"
|
2019-06-10 21:38:30 +02:00
|
|
|
#include "MessageUtils.h"
|
2022-02-11 21:53:37 +01:00
|
|
|
#include "Utils.h"
|
2019-04-09 21:28:07 +02:00
|
|
|
#include "sdbus-c++/Message.h"
|
|
|
|
|
#include "sdbus-c++/IConnection.h"
|
|
|
|
|
#include "sdbus-c++/Error.h"
|
2019-04-13 21:17:37 +02:00
|
|
|
#include "ScopeGuard.h"
|
2023-09-16 14:28:58 +00:00
|
|
|
#include SDBUS_HEADER
|
2017-11-27 14:13:55 +01:00
|
|
|
#include <cassert>
|
2019-03-25 16:28:31 +01:00
|
|
|
#include <chrono>
|
2021-06-03 18:53:38 +02:00
|
|
|
#include <utility>
|
2017-11-27 14:13:55 +01:00
|
|
|
|
2020-02-01 22:47:04 +01:00
|
|
|
namespace sdbus::internal {
|
2017-11-27 14:13:55 +01:00
|
|
|
|
2019-04-09 21:28:07 +02:00
|
|
|
Proxy::Proxy(sdbus::internal::IConnection& connection, std::string destination, std::string objectPath)
|
2017-11-27 14:13:55 +01:00
|
|
|
: connection_(&connection, [](sdbus::internal::IConnection *){ /* Intentionally left empty */ })
|
|
|
|
|
, destination_(std::move(destination))
|
|
|
|
|
, objectPath_(std::move(objectPath))
|
|
|
|
|
{
|
2022-02-11 21:53:37 +01:00
|
|
|
SDBUS_CHECK_SERVICE_NAME(destination_);
|
|
|
|
|
SDBUS_CHECK_OBJECT_PATH(objectPath_);
|
|
|
|
|
|
2019-04-13 21:17:37 +02:00
|
|
|
// The connection is not ours only, it is owned and managed by the user and we just reference
|
|
|
|
|
// it here, so we expect the client to manage the event loop upon this connection themselves.
|
2017-11-27 14:13:55 +01:00
|
|
|
}
|
|
|
|
|
|
2019-04-09 21:28:07 +02:00
|
|
|
Proxy::Proxy( std::unique_ptr<sdbus::internal::IConnection>&& connection
|
|
|
|
|
, std::string destination
|
|
|
|
|
, std::string objectPath )
|
2017-11-27 14:13:55 +01:00
|
|
|
: connection_(std::move(connection))
|
|
|
|
|
, destination_(std::move(destination))
|
|
|
|
|
, objectPath_(std::move(objectPath))
|
|
|
|
|
{
|
2022-02-11 21:53:37 +01:00
|
|
|
SDBUS_CHECK_SERVICE_NAME(destination_);
|
|
|
|
|
SDBUS_CHECK_OBJECT_PATH(objectPath_);
|
|
|
|
|
|
2019-04-13 21:17:37 +02:00
|
|
|
// The connection is ours only, i.e. it's us who has to manage the event loop upon this connection,
|
|
|
|
|
// in order that we get and process signals, async call replies, and other messages from D-Bus.
|
2020-02-02 22:22:26 +01:00
|
|
|
connection_->enterEventLoopAsync();
|
2017-11-27 14:13:55 +01:00
|
|
|
}
|
|
|
|
|
|
2022-08-03 00:38:34 +02:00
|
|
|
Proxy::Proxy( std::unique_ptr<sdbus::internal::IConnection>&& connection
|
|
|
|
|
, std::string destination
|
|
|
|
|
, std::string objectPath
|
|
|
|
|
, dont_run_event_loop_thread_t )
|
|
|
|
|
: connection_(std::move(connection))
|
|
|
|
|
, destination_(std::move(destination))
|
|
|
|
|
, objectPath_(std::move(objectPath))
|
|
|
|
|
{
|
|
|
|
|
SDBUS_CHECK_SERVICE_NAME(destination_);
|
|
|
|
|
SDBUS_CHECK_OBJECT_PATH(objectPath_);
|
|
|
|
|
|
|
|
|
|
// Even though the connection is ours only, we don't start an event loop thread.
|
|
|
|
|
// This proxy is meant to be created, used for simple synchronous D-Bus call(s) and then dismissed.
|
|
|
|
|
}
|
|
|
|
|
|
2019-04-09 21:28:07 +02:00
|
|
|
MethodCall Proxy::createMethodCall(const std::string& interfaceName, const std::string& methodName)
|
2017-11-27 14:13:55 +01:00
|
|
|
{
|
|
|
|
|
return connection_->createMethodCall(destination_, objectPath_, interfaceName, methodName);
|
|
|
|
|
}
|
|
|
|
|
|
2019-11-03 13:54:13 +01:00
|
|
|
MethodReply Proxy::callMethod(const MethodCall& message, uint64_t timeout)
|
2017-11-27 14:13:55 +01:00
|
|
|
{
|
2019-11-10 17:31:58 +01:00
|
|
|
SDBUS_THROW_ERROR_IF(!message.isValid(), "Invalid method call message provided", EINVAL);
|
|
|
|
|
|
2023-01-21 01:47:24 +01:00
|
|
|
return connection_->callMethod(message, timeout);
|
2017-11-27 14:13:55 +01:00
|
|
|
}
|
|
|
|
|
|
2020-03-29 21:43:20 +02:00
|
|
|
PendingAsyncCall Proxy::callMethod(const MethodCall& message, async_reply_handler asyncReplyCallback, uint64_t timeout)
|
2019-03-25 14:45:48 +01:00
|
|
|
{
|
2019-11-10 17:31:58 +01:00
|
|
|
SDBUS_THROW_ERROR_IF(!message.isValid(), "Invalid async method call message provided", EINVAL);
|
|
|
|
|
|
2019-04-09 21:28:07 +02:00
|
|
|
auto callback = (void*)&Proxy::sdbus_async_reply_handler;
|
2023-10-24 22:13:02 +02:00
|
|
|
auto callData = std::make_shared<AsyncCalls::CallData>(AsyncCalls::CallData{*this, std::move(asyncReplyCallback)});
|
2020-06-16 00:02:25 +02:00
|
|
|
auto weakData = std::weak_ptr<AsyncCalls::CallData>{callData};
|
2019-03-25 16:28:31 +01:00
|
|
|
|
2023-01-21 01:47:24 +01:00
|
|
|
callData->slot = connection_->callMethod(message, callback, callData.get(), timeout);
|
2019-04-13 21:17:37 +02:00
|
|
|
|
2023-02-01 11:52:21 +01:00
|
|
|
pendingAsyncCalls_.addCall(std::move(callData));
|
2020-03-29 21:43:20 +02:00
|
|
|
|
2023-01-21 01:47:24 +01:00
|
|
|
// TODO: Instead of PendingAsyncCall consider using Slot implementation for simplicity and consistency
|
2020-03-29 21:43:20 +02:00
|
|
|
return {weakData};
|
2019-03-25 14:45:48 +01:00
|
|
|
}
|
|
|
|
|
|
2023-01-29 22:12:10 +01:00
|
|
|
std::future<MethodReply> Proxy::callMethod(const MethodCall& message, with_future_t)
|
|
|
|
|
{
|
|
|
|
|
return Proxy::callMethod(message, {}, with_future);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::future<MethodReply> Proxy::callMethod(const MethodCall& message, uint64_t timeout, with_future_t)
|
|
|
|
|
{
|
|
|
|
|
auto promise = std::make_shared<std::promise<MethodReply>>();
|
|
|
|
|
auto future = promise->get_future();
|
|
|
|
|
|
2023-10-24 21:56:47 +02:00
|
|
|
async_reply_handler asyncReplyCallback = [promise = std::move(promise)](MethodReply reply, const Error* error) noexcept
|
2023-01-29 22:12:10 +01:00
|
|
|
{
|
|
|
|
|
if (error == nullptr)
|
2023-10-24 21:56:47 +02:00
|
|
|
promise->set_value(std::move(reply));
|
2023-01-29 22:12:10 +01:00
|
|
|
else
|
|
|
|
|
promise->set_exception(std::make_exception_ptr(*error));
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
(void)Proxy::callMethod(message, std::move(asyncReplyCallback), timeout);
|
|
|
|
|
|
|
|
|
|
return future;
|
|
|
|
|
}
|
|
|
|
|
|
2019-04-09 21:28:07 +02:00
|
|
|
void Proxy::registerSignalHandler( const std::string& interfaceName
|
|
|
|
|
, const std::string& signalName
|
|
|
|
|
, signal_handler signalHandler )
|
2017-11-27 14:13:55 +01:00
|
|
|
{
|
2023-12-30 19:22:45 +01:00
|
|
|
auto slot = Proxy::registerSignalHandler(interfaceName, signalName, std::move(signalHandler), return_slot);
|
2017-11-27 14:13:55 +01:00
|
|
|
|
2023-12-30 18:57:10 +01:00
|
|
|
floatingSignalSlots_.push_back(std::move(slot));
|
2017-11-27 14:13:55 +01:00
|
|
|
}
|
|
|
|
|
|
2023-12-30 18:57:10 +01:00
|
|
|
Slot Proxy::registerSignalHandler( const std::string& interfaceName
|
|
|
|
|
, const std::string& signalName
|
|
|
|
|
, signal_handler signalHandler
|
2023-12-30 19:22:45 +01:00
|
|
|
, return_slot_t )
|
2021-11-28 16:30:49 +02:00
|
|
|
{
|
2023-12-30 18:57:10 +01:00
|
|
|
SDBUS_CHECK_INTERFACE_NAME(interfaceName);
|
|
|
|
|
SDBUS_CHECK_MEMBER_NAME(signalName);
|
|
|
|
|
SDBUS_THROW_ERROR_IF(!signalHandler, "Invalid signal handler provided", EINVAL);
|
2021-11-28 16:30:49 +02:00
|
|
|
|
2023-12-30 18:57:10 +01:00
|
|
|
auto signalInfo = std::make_unique<SignalInfo>(SignalInfo{std::move(signalHandler), *this, {}});
|
2017-11-27 14:13:55 +01:00
|
|
|
|
2023-12-30 18:57:10 +01:00
|
|
|
signalInfo->slot = connection_->registerSignalHandler( destination_
|
|
|
|
|
, objectPath_
|
|
|
|
|
, interfaceName
|
|
|
|
|
, signalName
|
|
|
|
|
, &Proxy::sdbus_signal_handler
|
|
|
|
|
, signalInfo.get() );
|
2017-11-27 14:13:55 +01:00
|
|
|
|
2023-12-30 18:57:10 +01:00
|
|
|
return {signalInfo.release(), [](void *ptr){ delete static_cast<SignalInfo*>(ptr); }};
|
2017-11-27 14:13:55 +01:00
|
|
|
}
|
|
|
|
|
|
2019-04-13 21:17:37 +02:00
|
|
|
void Proxy::unregister()
|
|
|
|
|
{
|
|
|
|
|
pendingAsyncCalls_.clear();
|
2023-12-30 18:57:10 +01:00
|
|
|
floatingSignalSlots_.clear();
|
2019-04-13 21:17:37 +02:00
|
|
|
}
|
|
|
|
|
|
2021-05-06 07:52:02 -07:00
|
|
|
sdbus::IConnection& Proxy::getConnection() const
|
|
|
|
|
{
|
2022-06-15 15:42:24 +02:00
|
|
|
return *connection_;
|
2021-05-06 07:52:02 -07:00
|
|
|
}
|
|
|
|
|
|
2020-05-28 15:36:58 +02:00
|
|
|
const std::string& Proxy::getObjectPath() const
|
|
|
|
|
{
|
|
|
|
|
return objectPath_;
|
|
|
|
|
}
|
|
|
|
|
|
2023-02-02 21:51:09 +01:00
|
|
|
Message Proxy::getCurrentlyProcessedMessage() const
|
2021-06-02 15:17:20 +00:00
|
|
|
{
|
2023-02-02 21:51:09 +01:00
|
|
|
return connection_->getCurrentlyProcessedMessage();
|
2021-06-02 15:17:20 +00:00
|
|
|
}
|
|
|
|
|
|
2023-11-03 18:03:01 +01:00
|
|
|
int Proxy::sdbus_async_reply_handler(sd_bus_message *sdbusMessage, void *userData, sd_bus_error *retError)
|
2019-03-25 14:45:48 +01:00
|
|
|
{
|
2019-04-13 21:17:37 +02:00
|
|
|
auto* asyncCallData = static_cast<AsyncCalls::CallData*>(userData);
|
|
|
|
|
assert(asyncCallData != nullptr);
|
|
|
|
|
assert(asyncCallData->callback);
|
|
|
|
|
auto& proxy = asyncCallData->proxy;
|
|
|
|
|
|
2020-03-29 21:43:20 +02:00
|
|
|
// We are removing the CallData item at the complete scope exit, after the callback has been invoked.
|
|
|
|
|
// We can't do it earlier (before callback invocation for example), because CallBack data (slot release)
|
|
|
|
|
// is the synchronization point between callback invocation and Proxy::unregister.
|
2020-01-12 13:10:34 +01:00
|
|
|
SCOPE_EXIT
|
|
|
|
|
{
|
2023-10-24 22:13:02 +02:00
|
|
|
proxy.pendingAsyncCalls_.removeCall(asyncCallData);
|
2020-01-12 13:10:34 +01:00
|
|
|
};
|
2019-03-25 14:45:48 +01:00
|
|
|
|
2019-06-10 21:38:30 +02:00
|
|
|
auto message = Message::Factory::create<MethodReply>(sdbusMessage, &proxy.connection_->getSdBusInterface());
|
2019-03-25 16:28:31 +01:00
|
|
|
|
2023-11-03 18:03:01 +01:00
|
|
|
auto ok = invokeHandlerAndCatchErrors([&]
|
2019-03-25 14:45:48 +01:00
|
|
|
{
|
2021-07-22 14:33:38 +02:00
|
|
|
const auto* error = sd_bus_message_get_error(sdbusMessage);
|
|
|
|
|
if (error == nullptr)
|
|
|
|
|
{
|
2023-10-24 21:56:47 +02:00
|
|
|
asyncCallData->callback(std::move(message), nullptr);
|
2021-07-22 14:33:38 +02:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
Error exception(error->name, error->message);
|
2023-10-24 21:56:47 +02:00
|
|
|
asyncCallData->callback(std::move(message), &exception);
|
2021-07-22 14:33:38 +02:00
|
|
|
}
|
2023-11-03 18:03:01 +01:00
|
|
|
}, retError);
|
2019-04-12 22:39:14 +02:00
|
|
|
|
2023-11-03 18:03:01 +01:00
|
|
|
return ok ? 0 : -1;
|
2019-03-25 14:45:48 +01:00
|
|
|
}
|
|
|
|
|
|
2023-11-03 18:03:01 +01:00
|
|
|
int Proxy::sdbus_signal_handler(sd_bus_message *sdbusMessage, void *userData, sd_bus_error *retError)
|
2017-11-27 14:13:55 +01:00
|
|
|
{
|
2023-12-30 18:57:10 +01:00
|
|
|
auto* signalInfo = static_cast<SignalInfo*>(userData);
|
|
|
|
|
assert(signalInfo != nullptr);
|
|
|
|
|
assert(signalInfo->callback);
|
2017-11-27 14:13:55 +01:00
|
|
|
|
2023-12-30 18:57:10 +01:00
|
|
|
// TODO: Hide Message factory invocation under Connection API (tell, don't ask principle), then we can remove getSdBusInterface()
|
|
|
|
|
auto message = Message::Factory::create<Signal>(sdbusMessage, &signalInfo->proxy.connection_->getSdBusInterface());
|
2021-06-02 15:17:20 +00:00
|
|
|
|
2023-12-30 18:57:10 +01:00
|
|
|
auto ok = invokeHandlerAndCatchErrors([&](){ signalInfo->callback(std::move(message)); }, retError);
|
2021-07-22 14:33:38 +02:00
|
|
|
|
2023-11-03 18:03:01 +01:00
|
|
|
return ok ? 0 : -1;
|
2017-11-27 14:13:55 +01:00
|
|
|
}
|
|
|
|
|
|
2020-02-01 22:47:04 +01:00
|
|
|
}
|
2017-11-27 14:13:55 +01:00
|
|
|
|
|
|
|
|
namespace sdbus {
|
|
|
|
|
|
2020-03-29 21:43:20 +02:00
|
|
|
PendingAsyncCall::PendingAsyncCall(std::weak_ptr<void> callData)
|
|
|
|
|
: callData_(std::move(callData))
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void PendingAsyncCall::cancel()
|
|
|
|
|
{
|
|
|
|
|
if (auto ptr = callData_.lock(); ptr != nullptr)
|
|
|
|
|
{
|
|
|
|
|
auto* callData = static_cast<internal::Proxy::AsyncCalls::CallData*>(ptr.get());
|
2023-02-01 11:52:21 +01:00
|
|
|
callData->proxy.pendingAsyncCalls_.removeCall(callData);
|
2020-03-29 21:43:20 +02:00
|
|
|
|
|
|
|
|
// At this point, the callData item is being deleted, leading to the release of the
|
|
|
|
|
// sd-bus slot pointer. This release locks the global sd-bus mutex. If the async
|
|
|
|
|
// callback is currently being processed, the sd-bus mutex is locked by the event
|
|
|
|
|
// loop thread, thus access to the callData item is synchronized and thread-safe.
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool PendingAsyncCall::isPending() const
|
|
|
|
|
{
|
|
|
|
|
return !callData_.expired();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
namespace sdbus {
|
|
|
|
|
|
2019-04-09 21:28:07 +02:00
|
|
|
std::unique_ptr<sdbus::IProxy> createProxy( IConnection& connection
|
|
|
|
|
, std::string destination
|
|
|
|
|
, std::string objectPath )
|
2017-11-27 14:13:55 +01:00
|
|
|
{
|
|
|
|
|
auto* sdbusConnection = dynamic_cast<sdbus::internal::IConnection*>(&connection);
|
|
|
|
|
SDBUS_THROW_ERROR_IF(!sdbusConnection, "Connection is not a real sdbus-c++ connection", EINVAL);
|
|
|
|
|
|
2019-04-09 21:28:07 +02:00
|
|
|
return std::make_unique<sdbus::internal::Proxy>( *sdbusConnection
|
|
|
|
|
, std::move(destination)
|
|
|
|
|
, std::move(objectPath) );
|
2017-11-27 14:13:55 +01:00
|
|
|
}
|
|
|
|
|
|
2019-04-09 21:28:07 +02:00
|
|
|
std::unique_ptr<sdbus::IProxy> createProxy( std::unique_ptr<IConnection>&& connection
|
|
|
|
|
, std::string destination
|
|
|
|
|
, std::string objectPath )
|
2018-03-15 17:03:49 +01:00
|
|
|
{
|
|
|
|
|
auto* sdbusConnection = dynamic_cast<sdbus::internal::IConnection*>(connection.get());
|
|
|
|
|
SDBUS_THROW_ERROR_IF(!sdbusConnection, "Connection is not a real sdbus-c++ connection", EINVAL);
|
|
|
|
|
|
|
|
|
|
connection.release();
|
|
|
|
|
|
2019-04-09 21:28:07 +02:00
|
|
|
return std::make_unique<sdbus::internal::Proxy>( std::unique_ptr<sdbus::internal::IConnection>(sdbusConnection)
|
|
|
|
|
, std::move(destination)
|
|
|
|
|
, std::move(objectPath) );
|
2018-03-15 17:03:49 +01:00
|
|
|
}
|
|
|
|
|
|
2022-08-03 00:38:34 +02:00
|
|
|
std::unique_ptr<sdbus::IProxy> createProxy( std::unique_ptr<IConnection>&& connection
|
|
|
|
|
, std::string destination
|
|
|
|
|
, std::string objectPath
|
|
|
|
|
, dont_run_event_loop_thread_t )
|
|
|
|
|
{
|
|
|
|
|
auto* sdbusConnection = dynamic_cast<sdbus::internal::IConnection*>(connection.get());
|
|
|
|
|
SDBUS_THROW_ERROR_IF(!sdbusConnection, "Connection is not a real sdbus-c++ connection", EINVAL);
|
|
|
|
|
|
|
|
|
|
connection.release();
|
|
|
|
|
|
|
|
|
|
return std::make_unique<sdbus::internal::Proxy>( std::unique_ptr<sdbus::internal::IConnection>(sdbusConnection)
|
|
|
|
|
, std::move(destination)
|
|
|
|
|
, std::move(objectPath)
|
|
|
|
|
, dont_run_event_loop_thread );
|
|
|
|
|
}
|
|
|
|
|
|
2019-04-09 21:28:07 +02:00
|
|
|
std::unique_ptr<sdbus::IProxy> createProxy( std::string destination
|
|
|
|
|
, std::string objectPath )
|
2017-11-27 14:13:55 +01:00
|
|
|
{
|
|
|
|
|
auto connection = sdbus::createConnection();
|
|
|
|
|
|
|
|
|
|
auto sdbusConnection = std::unique_ptr<sdbus::internal::IConnection>(dynamic_cast<sdbus::internal::IConnection*>(connection.release()));
|
|
|
|
|
assert(sdbusConnection != nullptr);
|
|
|
|
|
|
2019-04-09 21:28:07 +02:00
|
|
|
return std::make_unique<sdbus::internal::Proxy>( std::move(sdbusConnection)
|
|
|
|
|
, std::move(destination)
|
|
|
|
|
, std::move(objectPath) );
|
2017-11-27 14:13:55 +01:00
|
|
|
}
|
|
|
|
|
|
2022-08-03 00:38:34 +02:00
|
|
|
std::unique_ptr<sdbus::IProxy> createProxy( std::string destination
|
|
|
|
|
, std::string objectPath
|
|
|
|
|
, dont_run_event_loop_thread_t )
|
|
|
|
|
{
|
|
|
|
|
auto connection = sdbus::createConnection();
|
|
|
|
|
|
|
|
|
|
auto sdbusConnection = std::unique_ptr<sdbus::internal::IConnection>(dynamic_cast<sdbus::internal::IConnection*>(connection.release()));
|
|
|
|
|
assert(sdbusConnection != nullptr);
|
|
|
|
|
|
|
|
|
|
return std::make_unique<sdbus::internal::Proxy>( std::move(sdbusConnection)
|
|
|
|
|
, std::move(destination)
|
|
|
|
|
, std::move(objectPath)
|
|
|
|
|
, dont_run_event_loop_thread );
|
|
|
|
|
}
|
|
|
|
|
|
2017-11-27 14:13:55 +01:00
|
|
|
}
|