Files
sdbus-cpp/src/Object.h
T
Jan Beich 1e2d13a04a feat: add FreeBSD support (#358)
* chore: don't use systemd headers with elogind

In file included from src/VTableUtils.c:27:
src/VTableUtils.h:30:10: fatal error: 'systemd/sd-bus.h' file not found
 #include <systemd/sd-bus.h>
          ^~~~~~~~~~~~~~~~~~

* chore: add basu support

Similar to elogind but also supported on non-Linux.

* chore(tests): permit /var/lib/machine-id on non-systemd

https://github.com/elogind/elogind/commit/84fdc0fc61c1
https://git.sr.ht/~emersion/basu/commit/8324e6729231

* chore(ci): add simple freebsd job

Mainly to cover libc++ and basu.

* chore(ci): explicitly pass CMAKE_INSTALL_PREFIX

Some sdbus-cpp tests require configuring system bus. However, Linux
testing relies on writing outside of prefix in order to affect current
system bus instance instead of launching a dedicated one.

* chore(tests): respect CMAKE_INSTALL_PREFIX for system bus config

DBus isn't part of base system on BSDs, so may not use /etc for configs.
Also, testing installation failed as non-root:

$ cmake -DBUILD_TESTS=1 -DCMAKE_INSTALL_PREFIX=/tmp/sdbus-cpp_prefix -DTESTS_INSTALL_PATH=/tmp/sdbus-cpp_prefix/tests
$ cmake --build .
$ cmake --install .
[...]
CMake Error at tests/cmake_install.cmake:105 (file):
  file cannot create directory: /etc/dbus-1/system.d.  Maybe need
  administrative privileges.

* chore(tests): temporarily skip 1 test on FreeBSD to keep CI happy

* chore(ci): run tests in freebsd job
2023-09-18 11:35:23 +02:00

187 lines
8.1 KiB
C++

/**
* (C) 2016 - 2021 KISTLER INSTRUMENTE AG, Winterthur, Switzerland
* (C) 2016 - 2022 Stanislav Angelovic <stanislav.angelovic@protonmail.com>
*
* @file Object.h
*
* 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/>.
*/
#ifndef SDBUS_CXX_INTERNAL_OBJECT_H_
#define SDBUS_CXX_INTERNAL_OBJECT_H_
#include <sdbus-c++/IObject.h>
#include "IConnection.h"
#include SDBUS_HEADER
#include <string>
#include <map>
#include <vector>
#include <functional>
#include <memory>
#include <atomic>
#include <cassert>
namespace sdbus::internal {
class Object
: public IObject
{
public:
Object(sdbus::internal::IConnection& connection, std::string objectPath);
void registerMethod( const std::string& interfaceName
, std::string methodName
, std::string inputSignature
, std::string outputSignature
, method_callback methodCallback
, Flags flags ) override;
void registerMethod( const std::string& interfaceName
, std::string methodName
, std::string inputSignature
, const std::vector<std::string>& inputNames
, std::string outputSignature
, const std::vector<std::string>& outputNames
, method_callback methodCallback
, Flags flags ) override;
void registerSignal( const std::string& interfaceName
, std::string signalName
, std::string signature
, Flags flags ) override;
void registerSignal( const std::string& interfaceName
, std::string signalName
, std::string signature
, const std::vector<std::string>& paramNames
, Flags flags ) override;
void registerProperty( const std::string& interfaceName
, std::string propertyName
, std::string signature
, property_get_callback getCallback
, Flags flags ) override;
void registerProperty( const std::string& interfaceName
, std::string propertyName
, std::string signature
, property_get_callback getCallback
, property_set_callback setCallback
, Flags flags ) override;
void setInterfaceFlags(const std::string& interfaceName, Flags flags) override;
void finishRegistration() override;
void unregister() override;
sdbus::Signal createSignal(const std::string& interfaceName, const std::string& signalName) override;
void emitSignal(const sdbus::Signal& message) override;
void emitPropertiesChangedSignal(const std::string& interfaceName, const std::vector<std::string>& propNames) override;
void emitPropertiesChangedSignal(const std::string& interfaceName) override;
void emitInterfacesAddedSignal() override;
void emitInterfacesAddedSignal(const std::vector<std::string>& interfaces) override;
void emitInterfacesRemovedSignal() override;
void emitInterfacesRemovedSignal(const std::vector<std::string>& interfaces) override;
void addObjectManager() override;
void removeObjectManager() override;
bool hasObjectManager() const override;
sdbus::IConnection& getConnection() const override;
const std::string& getObjectPath() const override;
const Message* getCurrentlyProcessedMessage() const override;
private:
using InterfaceName = std::string;
struct InterfaceData
{
InterfaceData(Object& object) : object(object) {}
using MethodName = std::string;
struct MethodData
{
const std::string inputArgs;
const std::string outputArgs;
const std::string paramNames;
method_callback callback;
Flags flags;
};
std::map<MethodName, MethodData> methods;
using SignalName = std::string;
struct SignalData
{
const std::string signature;
const std::string paramNames;
Flags flags;
};
std::map<SignalName, SignalData> signals;
using PropertyName = std::string;
struct PropertyData
{
const std::string signature;
property_get_callback getCallback;
property_set_callback setCallback;
Flags flags;
};
std::map<PropertyName, PropertyData> properties;
std::vector<sd_bus_vtable> vtable;
Flags flags;
Object& object;
// This is intentionally the last member, because it must be destructed first,
// releasing callbacks above before the callbacks themselves are destructed.
Slot slot;
};
InterfaceData& getInterface(const std::string& interfaceName);
static const std::vector<sd_bus_vtable>& createInterfaceVTable(InterfaceData& interfaceData);
static void registerMethodsToVTable(const InterfaceData& interfaceData, std::vector<sd_bus_vtable>& vtable);
static void registerSignalsToVTable(const InterfaceData& interfaceData, std::vector<sd_bus_vtable>& vtable);
static void registerPropertiesToVTable(const InterfaceData& interfaceData, std::vector<sd_bus_vtable>& vtable);
void activateInterfaceVTable( const std::string& interfaceName
, InterfaceData& interfaceData
, const std::vector<sd_bus_vtable>& vtable );
static std::string paramNamesToString(const std::vector<std::string>& paramNames);
static int sdbus_method_callback(sd_bus_message *sdbusMessage, void *userData, sd_bus_error *retError);
static int sdbus_property_get_callback( sd_bus *bus
, const char *objectPath
, const char *interface
, const char *property
, sd_bus_message *sdbusReply
, void *userData
, sd_bus_error *retError );
static int sdbus_property_set_callback( sd_bus *bus
, const char *objectPath
, const char *interface
, const char *property
, sd_bus_message *sdbusValue
, void *userData
, sd_bus_error *retError );
private:
sdbus::internal::IConnection& connection_;
std::string objectPath_;
std::map<InterfaceName, InterfaceData> interfaces_;
Slot objectManagerSlot_;
std::atomic<const Message*> m_CurrentlyProcessedMessage{nullptr};
};
}
#endif /* SDBUS_CXX_INTERNAL_OBJECT_H_ */