├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md └── workflows │ └── ci.yml ├── .gitignore ├── AUTHORS ├── CMakeLists.txt ├── COPYING ├── COPYING-LGPL-Exception ├── ChangeLog ├── INSTALL ├── NEWS ├── README ├── README.md ├── cmake ├── LibsystemdExternalProject.cmake └── sdbus-c++-config.cmake.in ├── docs ├── CMakeLists.txt ├── Doxyfile.in ├── sdbus-c++-class-diagram.png ├── sdbus-c++-class-diagram.uml ├── systemd-dbus-config.md └── using-sdbus-c++.md ├── examples ├── CMakeLists.txt └── org.freedesktop.DBus.ObjectManager │ ├── examplemanager-planet1-client-glue.h │ ├── examplemanager-planet1-server-glue.h │ ├── obj-manager-client.cpp │ ├── obj-manager-server.cpp │ └── org.sdbuscpp.ExampleManager.Planet1.xml ├── include └── sdbus-c++ │ ├── AdaptorInterfaces.h │ ├── ConvenienceApiClasses.h │ ├── ConvenienceApiClasses.inl │ ├── Error.h │ ├── Flags.h │ ├── IConnection.h │ ├── IObject.h │ ├── IProxy.h │ ├── Message.h │ ├── MethodResult.h │ ├── ProxyInterfaces.h │ ├── StandardInterfaces.h │ ├── TypeTraits.h │ ├── Types.h │ ├── VTableItems.h │ ├── VTableItems.inl │ └── sdbus-c++.h ├── pkgconfig └── sdbus-c++.pc.in ├── src ├── Connection.cpp ├── Connection.h ├── Error.cpp ├── Flags.cpp ├── IConnection.h ├── ISdBus.h ├── Message.cpp ├── MessageUtils.h ├── Object.cpp ├── Object.h ├── Proxy.cpp ├── Proxy.h ├── ScopeGuard.h ├── SdBus.cpp ├── SdBus.h ├── Types.cpp ├── Utils.h ├── VTableUtils.c └── VTableUtils.h ├── tests ├── CMakeLists.txt ├── integrationtests │ ├── DBusAsyncMethodsTests.cpp │ ├── DBusConnectionTests.cpp │ ├── DBusGeneralTests.cpp │ ├── DBusMethodsTests.cpp │ ├── DBusPropertiesTests.cpp │ ├── DBusSignalsTests.cpp │ ├── DBusStandardInterfacesTests.cpp │ ├── Defs.h │ ├── TestAdaptor.cpp │ ├── TestAdaptor.h │ ├── TestFixture.cpp │ ├── TestFixture.h │ ├── TestProxy.cpp │ ├── TestProxy.h │ ├── files │ │ └── org.sdbuscpp.integrationtests.conf │ ├── integrationtests-adaptor.h │ ├── integrationtests-proxy.h │ ├── org.sdbuscpp.integrationtests.xml │ └── sdbus-c++-integration-tests.cpp ├── perftests │ ├── client.cpp │ ├── files │ │ └── org.sdbuscpp.perftests.conf │ ├── org.sdbuscpp.perftests.xml │ ├── perftests-adaptor.h │ ├── perftests-proxy.h │ └── server.cpp ├── stresstests │ ├── celsius-thermometer-adaptor.h │ ├── celsius-thermometer-proxy.h │ ├── concatenator-adaptor.h │ ├── concatenator-proxy.h │ ├── fahrenheit-thermometer-adaptor.h │ ├── fahrenheit-thermometer-proxy.h │ ├── files │ │ └── org.sdbuscpp.stresstests.conf │ ├── org.sdbuscpp.stresstest.celsius.thermometer.xml │ ├── org.sdbuscpp.stresstest.concatenator.xml │ ├── org.sdbuscpp.stresstest.fahrenheit.thermometer.xml │ └── sdbus-c++-stress-tests.cpp └── unittests │ ├── Connection_test.cpp │ ├── Message_test.cpp │ ├── PollData_test.cpp │ ├── TypeTraits_test.cpp │ ├── Types_test.cpp │ ├── mocks │ └── SdBusMock.h │ └── sdbus-c++-unit-tests.cpp └── tools ├── CMakeLists.txt ├── COPYING ├── cmake └── sdbus-c++-tools-config.cmake.in ├── pkgconfig └── sdbus-c++-tools.pc.in └── xml2cpp-codegen ├── AdaptorGenerator.cpp ├── AdaptorGenerator.h ├── BaseGenerator.cpp ├── BaseGenerator.h ├── ProxyGenerator.cpp ├── ProxyGenerator.h ├── generator_utils.cpp ├── generator_utils.h ├── reserved_names.h ├── xml.cpp ├── xml.h └── xml2cpp.cpp /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior. 15 | 16 | **Expected behavior** 17 | A clear and concise description of what you expected to happen. 18 | 19 | **Real (buggy) behavior** 20 | A clear and concise description of what really happened in contrast to your expectation. 21 | 22 | **Additional context** 23 | Add any other context about the problem here, like version of sdbus-c++ library, version of systemd used, OS used. 24 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | pull_request: 7 | branches: 8 | - master 9 | - release/v2.0 10 | 11 | jobs: 12 | build: 13 | runs-on: ${{ matrix.os }} 14 | strategy: 15 | fail-fast: false 16 | matrix: 17 | os: [ubuntu-22.04, ubuntu-24.04] 18 | compiler: [g++, clang] 19 | build: [shared-libsystemd, embedded-static-libsystemd] 20 | steps: 21 | - uses: actions/checkout@v4 22 | - name: install-libsystemd-toolchain 23 | if: matrix.build == 'embedded-static-libsystemd' 24 | run: | 25 | sudo apt-get update -y 26 | sudo apt-get install -y meson ninja-build libcap-dev libmount-dev m4 gperf 27 | - name: install-libsystemd-dev 28 | if: matrix.build == 'shared-libsystemd' 29 | run: | 30 | sudo apt-get update -y 31 | sudo apt-get install -y libsystemd-dev 32 | - name: install-clang 33 | if: matrix.compiler == 'clang' 34 | run: | 35 | sudo apt-get install -y clang libc++-dev 36 | sudo update-alternatives --remove-all cc 37 | sudo update-alternatives --install /usr/bin/cc cc /usr/bin/clang 10 38 | sudo update-alternatives --remove-all c++ 39 | sudo update-alternatives --install /usr/bin/c++ c++ /usr/bin/clang++ 10 40 | # We need to use libc++ with Clang because there is a bug in libstdc++ chrono headers that Clang has issues with 41 | echo "SDBUSCPP_EXTRA_CXX_FLAGS=-stdlib=libc++" >> $GITHUB_ENV 42 | # We don't install googletest but we let it be built within sdbus-c++ builds below, since it needs to be built against libc++ for Clang jobs to pass 43 | # - name: install-googletest 44 | # run: | 45 | # sudo apt-get install -y libgmock-dev 46 | - name: configure-debug-gcc11 # For gcc 11, turn off the annoying deprecated-copy warning 47 | if: matrix.build == 'shared-libsystemd' && matrix.compiler == 'g++' && matrix.os == 'ubuntu-22.04' 48 | run: | 49 | mkdir build 50 | cd build 51 | cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX:PATH=/usr -DCMAKE_CXX_FLAGS="-O0 -g -W -Wextra -Wall -Wnon-virtual-dtor -Wno-deprecated-copy -Werror $SDBUSCPP_EXTRA_CXX_FLAGS" -DCMAKE_VERBOSE_MAKEFILE=ON -DSDBUSCPP_INSTALL=ON -DSDBUSCPP_BUILD_TESTS=ON -DSDBUSCPP_BUILD_PERF_TESTS=ON -DSDBUSCPP_BUILD_STRESS_TESTS=ON -DSDBUSCPP_BUILD_CODEGEN=ON -DSDBUSCPP_GOOGLETEST_VERSION=1.14.0 .. 52 | - name: configure-debug 53 | if: matrix.build == 'shared-libsystemd' && (matrix.compiler != 'g++' || matrix.os != 'ubuntu-22.04') 54 | run: | 55 | mkdir build 56 | cd build 57 | cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX:PATH=/usr -DCMAKE_CXX_FLAGS="-O0 -g -W -Wextra -Wall -Wnon-virtual-dtor -Werror $SDBUSCPP_EXTRA_CXX_FLAGS" -DCMAKE_VERBOSE_MAKEFILE=ON -DSDBUSCPP_INSTALL=ON -DSDBUSCPP_BUILD_TESTS=ON -DSDBUSCPP_BUILD_PERF_TESTS=ON -DSDBUSCPP_BUILD_STRESS_TESTS=ON -DSDBUSCPP_BUILD_CODEGEN=ON -DSDBUSCPP_GOOGLETEST_VERSION=1.14.0 .. 58 | - name: configure-release-with-embedded-libsystemd 59 | if: matrix.build == 'embedded-static-libsystemd' 60 | run: | 61 | mkdir build 62 | cd build 63 | cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX:PATH=/usr -DCMAKE_CXX_FLAGS="$SDBUSCPP_EXTRA_CXX_FLAGS" -DCMAKE_VERBOSE_MAKEFILE=ON -DSDBUSCPP_INSTALL=ON -DSDBUSCPP_BUILD_TESTS=ON -DSDBUSCPP_BUILD_PERF_TESTS=ON -DSDBUSCPP_BUILD_STRESS_TESTS=ON -DSDBUSCPP_BUILD_CODEGEN=ON -DSDBUSCPP_BUILD_LIBSYSTEMD=ON -DSDBUSCPP_LIBSYSTEMD_VERSION=252 -DSDBUSCPP_GOOGLETEST_VERSION=1.14.0 .. 64 | - name: make 65 | run: | 66 | cd build 67 | cmake --build . -j4 68 | - name: verify 69 | run: | 70 | cd build 71 | sudo cmake --build . --target install 72 | ctest --output-on-failure 73 | - name: pack 74 | if: matrix.build == 'shared-libsystemd' 75 | run: | 76 | cd build 77 | cpack -G DEB 78 | - name: 'Upload Artifact' 79 | if: matrix.build == 'shared-libsystemd' && matrix.compiler == 'g++' 80 | uses: actions/upload-artifact@v4 81 | with: 82 | name: "debian-packages-${{ matrix.os }}-${{ matrix.compiler }}" 83 | path: | 84 | build/sdbus-c++*.deb 85 | build/sdbus-c++*.ddeb 86 | retention-days: 10 87 | freebsd-build: 88 | name: build (freebsd, clang/libc++, basu) 89 | runs-on: ubuntu-22.04 # until https://github.com/actions/runner/issues/385 90 | steps: 91 | - uses: actions/checkout@v4 92 | - name: Test in FreeBSD VM 93 | uses: vmactions/freebsd-vm@v1 94 | with: 95 | copyback: false 96 | usesh: true 97 | prepare: | 98 | pkg install -y cmake ninja pkgconf basu expat googletest 99 | run: | 100 | cmake -B _build -G Ninja -DSDBUSCPP_INSTALL=ON -DSDBUSCPP_BUILD_CODEGEN=ON -DSDBUSCPP_BUILD_TESTS=ON -DSDBUSCPP_BUILD_PERF_TESTS=ON -DSDBUSCPP_BUILD_STRESS_TESTS=ON 101 | cmake --build _build 102 | cmake --install _build 103 | pkg install -y dbus 104 | service dbus onestart 105 | ctest --output-on-failure --test-dir _build 106 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # c++ 2 | *.o 3 | *.lo 4 | *.la 5 | m4/ 6 | build/ 7 | .deps/ 8 | .dirstamp 9 | .libs/ 10 | tests/libsdbus-c++_unittests 11 | tests/libsdbus-c++_integrationtests 12 | tests/run-test-on-device.sh 13 | 14 | #eclipse 15 | .cproject 16 | .settings 17 | *.log 18 | 19 | #autotools 20 | sdbus-cpp.pc 21 | *Makefile 22 | *Makefile.in 23 | aclocal.m4 24 | arm-poky-linux-gnueabi-libtool 25 | autom4te.cache 26 | configure 27 | config.h 28 | config.status 29 | config.guess 30 | config.h.in 31 | config.sub 32 | compile 33 | depcomp 34 | install-sh 35 | ltmain.sh 36 | missing 37 | stamp-h1 38 | test-driver 39 | .autotools 40 | .gdbinit 41 | sdbus-cpp_gdb_arm-poky-linux-gnueabi.launch 42 | sdbus-c++.pc 43 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | sdbus-c++ library: 2 | Stanislav Angelovic (https://github.com/sangelovic) 3 | 4 | Code generator: 5 | Lukas Durfina (https://github.com/lukasdurfina) 6 | 7 | ... and other contributors :) 8 | -------------------------------------------------------------------------------- /COPYING-LGPL-Exception: -------------------------------------------------------------------------------- 1 | sdbus-c++ LGPL Exception version 1.0 2 | 3 | As an additional permission to the GNU Lesser General Public License version 4 | 2.1, the object code form of a "work that uses the Library" may incorporate 5 | material from a header file that is part of the Library. You may distribute 6 | such object code under terms of your choice, provided that: 7 | (i) the header files of the Library have not been modified; and 8 | (ii) the incorporated material is limited to numerical parameters, data 9 | structure layouts, accessors, macros, inline functions and 10 | templates; and 11 | (iii) you comply with the terms of Section 6 of the GNU Lesser General 12 | Public License version 2.1. 13 | 14 | Moreover, you may apply this exception to a modified version of the Library, 15 | provided that such modification does not involve copying material from the 16 | Library into the modified Library's header files unless such material is 17 | limited to (i) numerical parameters; (ii) data structure layouts; 18 | (iii) accessors; and (iv) small macros, templates and inline functions of 19 | five lines or less in length. 20 | 21 | Furthermore, you are not required to apply this additional permission to a 22 | modified version of the Library. 23 | -------------------------------------------------------------------------------- /INSTALL: -------------------------------------------------------------------------------- 1 | Building: 2 | $ mkdir build 3 | $ cd build 4 | $ cmake .. -DCMAKE_BUILD_TYPE=Release ${OTHER_CONFIG_FLAGS} 5 | $ make 6 | 7 | Installing: 8 | $ sudo make install 9 | -------------------------------------------------------------------------------- /NEWS: -------------------------------------------------------------------------------- 1 | sdbus-c++: D-Bus IPC C++ binding library based on sd-bus 2 | 3 | v0.2.3: 4 | * sdbus-c++ v0.2.3 released to the public! 5 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | See README.md 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | sdbus-c++ 2 | ========= 3 | 4 | ![ci](https://github.com/Kistler-Group/sdbus-cpp/workflows/CI/badge.svg) 5 | ![license](https://img.shields.io/github/license/Kistler-Group/sdbus-cpp) 6 | ![release](https://img.shields.io/github/v/release/Kistler-Group/sdbus-cpp) 7 | 8 | sdbus-c++ is a high-level C++ D-Bus library for Linux designed to provide expressive, easy-to-use API in modern C++. It adds another layer of abstraction on top of sd-bus, a nice, fresh C D-Bus implementation by systemd. 9 | 10 | sdbus-c++ has been written primarily as a replacement of dbus-c++, which currently suffers from a number of (unresolved) bugs, concurrency issues and inherent design complexities and limitations. sdbus-c++ has learned from dbus-c++ and has chosen a different path, a path of simple yet powerful design that is intuitive and friendly to the user and inherently free of those bugs. 11 | 12 | Even though sdbus-c++ uses sd-bus library, it is not necessarily constrained to systemd and can perfectly be used in non-systemd environments as well. 13 | 14 | Building and installing the library 15 | ----------------------------------- 16 | 17 | The library is built using CMake: 18 | 19 | ```bash 20 | $ mkdir build 21 | $ cd build 22 | $ cmake .. -DCMAKE_BUILD_TYPE=Release ${OTHER_CONFIG_FLAGS} 23 | $ cmake --build . 24 | $ sudo cmake --build . --target install 25 | ``` 26 | 27 | ### CMake configuration flags for sdbus-c++ 28 | 29 | * `SDBUSCPP_BUILD_CODEGEN` [boolean] 30 | 31 | Build the codegen tool `sdbus-c++-xml2cpp` for generating the high level C++ bindings out of the D-Bus IDL XML description. Default value: `OFF`. Use `-DSDBUSCPP_BUILD_CODEGEN=ON` flag to turn on building the code gen. 32 | 33 | * `SDBUSCPP_BUILD_DOCS` [boolean] 34 | 35 | Include sdbus-c++ documentation files and tutorials. Default value: `ON`. With this option turned on, you may also enable/disable the following option: 36 | 37 | * `SDBUSCPP_BUILD_DOXYGEN_DOCS` [boolean] 38 | 39 | Build Doxygen documentation of sdbus-c++ API. If enabled, the documentation must still be built explicitly through `cmake --build . --target doc`. Default value: `OFF`. Use `-DSDBUSCPP_BUILD_DOXYGEN_DOCS=OFF` to disable searching for Doxygen and building Doxygen documentation of sdbus-c++ API. 40 | 41 | * `SDBUSCPP_BUILD_TESTS` [boolean] 42 | 43 | Build sdbus-c++ unit and integration tests, invokable by `cmake --build . --target test` (Note: before invoking `cmake --build . --target test`, make sure you copy `tests/integrationtests/files/org.sdbuscpp.integrationtests.conf` file to `/etc/dbus-1/system.d` directory). That incorporates downloading and building static libraries of Google Test. Default value: `OFF`. Use `-DBUILD_TESTS=ON` to enable building the tests. With this option turned on, you may also enable/disable the following options: 44 | 45 | * `SDBUSCPP_BUILD_PERF_TESTS` [boolean] 46 | 47 | Build sdbus-c++ performance tests. Default value: `OFF`. 48 | 49 | * `SDBUSCPP_BUILD_STRESS_TESTS` [boolean] 50 | 51 | Build sdbus-c++ stress tests. Default value: `OFF`. 52 | 53 | * `SDBUSCPP_TESTS_INSTALL_PATH` [string] 54 | 55 | Path where the test binaries shall get installed. Default value: `${CMAKE_INSTALL_PREFIX}/tests/sdbus-c++` (previously: `/opt/test/bin`). 56 | 57 | * `SDBUSCPP_BUILD_EXAMPLES` [boolean] 58 | 59 | Build example programs which are located in the _example_ directory. Examples are not installed. Default value: `OFF`. 60 | 61 | * `SDBUSCPP_BUILD_LIBSYSTEMD` [boolean] 62 | 63 | Build sd-bus (libsystemd library) instead of searching for it in the system, and make it part of sdbus-c++ library. Default value: `OFF`, which means that the sd-bus implementation library (`libsystemd`, `libelogind`, or `basu`) will be searched via `pkg-config` in the system. 64 | 65 | This option may be very helpful in environments where sd-bus implementation library is unavailable (see [Solving sd-bus dependency](docs/using-sdbus-c++.md#solving-sd-bus-dependency) for more information). 66 | 67 | With this option turned off, you may provide the following additional configuration flag: 68 | 69 | * `SDBUSCPP_SDBUS_LIB` [string] 70 | 71 | Defines which sd-bus implementation library to search for and use. Allowed values: `default`, `systemd`, `elogind`, `basu`. Default value: `default`, which means that sdbus-c++ will try to find any of `systemd`, `elogind`, `basu` in the order as listed here. 72 | 73 | With this option turned on, you may provide the following additional configuration flag: 74 | 75 | * `SDBUSCPP_LIBSYSTEMD_VERSION` [string] 76 | 77 | Defines version of systemd to be downloaded, built and integrated into sdbus-c++. Default value: `252`, minimum value: `239`. 78 | 79 | * `SDBUSCPP_LIBSYSTEMD_EXTRA_CONFIG_OPTS` [string] 80 | 81 | Additional options to be passed as-is to the libsystemd build system in its configure step. Can be used for passing e.g. toolchain file path in case of cross builds. Default value: empty. 82 | 83 | * `CMAKE_BUILD_TYPE` [string] 84 | 85 | CMake-builtin option. Set to `Release` to build sdbus-c++ for production use. Set to `Debug` if you want to help further develop (and debug) the library :) 86 | 87 | * `BUILD_SHARED_LIBS` [boolean] 88 | 89 | Global CMake flag, promoted in sdbus-c++ project to a CMake option. Use this to control whether sdbus-c++ is built as either a shared or static library. Default value: `ON`. 90 | 91 | Dependencies 92 | ------------ 93 | 94 | * `C++20/C++17` - the library uses C++20 features, but its public API is backwards compatible with C++17 and provides optional extra features when C++20 features are available 95 | * `libsystemd`/`libelogind`/`basu` - libraries containing sd-bus implementation that sdbus-c++ is written around. In case of `libsystemd` and `libelogind`, version >= 238 is needed. (In case you have you're missing any of those sd-bus implementations, don't worry, see [Solving sd-bus dependency](docs/using-sdbus-c++.md#solving-sd-bus-dependency) for more information.) 96 | * `googletest` - google unit testing framework, only necessary when building tests, will be downloaded and built automatically. 97 | * `pkgconfig` - required for sdbus-c++ to be able to find some dependency packages. 98 | * `expat` - necessary when building the xml2cpp binding code generator (`SDBUSCPP_BUILD_CODEGEN` option is `ON`). 99 | 100 | Licensing 101 | --------- 102 | 103 | The library is distributed under LGPLv2.1 license, with a specific exception for macro/template/inline code in library header files. 104 | 105 | References/documentation 106 | ------------------------ 107 | 108 | * [Using sdbus-c++](docs/using-sdbus-c++.md) - *the* main, comprehensive tutorial on sdbus-c++ 109 | * [Systemd and dbus configuration](docs/systemd-dbus-config.md) 110 | * [D-Bus Specification](https://dbus.freedesktop.org/doc/dbus-specification.html) 111 | * [sd-bus Overview](http://0pointer.net/blog/the-new-sd-bus-api-of-systemd.html) 112 | 113 | Contributing 114 | ------------ 115 | 116 | Contributions that increase the library quality, functionality, or fix issues are very welcome. To introduce a change, please submit a pull request with a description. 117 | 118 | Contact 119 | ------- 120 | 121 | https://github.com/Kistler-Group/sdbus-cpp 122 | -------------------------------------------------------------------------------- /cmake/LibsystemdExternalProject.cmake: -------------------------------------------------------------------------------- 1 | find_program(MESON meson) 2 | find_program(NINJA ninja) 3 | find_program(GPERF gperf) 4 | 5 | if((NOT MESON) OR (NOT NINJA)) 6 | message(FATAL_ERROR "Meson and Ninja are required to build libsystemd") 7 | endif() 8 | 9 | if(NOT GPERF) 10 | message(WARNING "gperf was not found, libsystemd configuration may fail") 11 | endif() 12 | 13 | find_library(GLIBC_RT_LIBRARY rt) 14 | find_package(PkgConfig REQUIRED) 15 | pkg_check_modules(MOUNT mount) 16 | pkg_check_modules(CAP REQUIRED libcap) 17 | if (NOT CAP_FOUND) 18 | find_library(CAP_LIBRARIES cap) # Compat with Ubuntu 14.04 which ships libcap w/o .pc file 19 | endif() 20 | 21 | if(NOT CMAKE_BUILD_TYPE) 22 | set(LIBSYSTEMD_BUILD_TYPE "plain") 23 | elseif(CMAKE_BUILD_TYPE STREQUAL "Debug") 24 | set(LIBSYSTEMD_BUILD_TYPE "debug") 25 | else() 26 | set(LIBSYSTEMD_BUILD_TYPE "release") 27 | endif() 28 | 29 | if(SDBUSCPP_LIBSYSTEMD_VERSION LESS "239") 30 | message(FATAL_ERROR "Only libsystemd version >=239 can be built as static part of sdbus-c++") 31 | endif() 32 | if(SDBUSCPP_LIBSYSTEMD_VERSION GREATER "240") 33 | set(BUILD_VERSION_H ${NINJA} -C version.h) 34 | endif() 35 | 36 | message(STATUS "Building with embedded libsystemd v${SDBUSCPP_LIBSYSTEMD_VERSION}") 37 | 38 | include(ExternalProject) 39 | ExternalProject_Add(LibsystemdBuildProject 40 | PREFIX libsystemd-v${SDBUSCPP_LIBSYSTEMD_VERSION} 41 | GIT_REPOSITORY https://github.com/systemd/systemd-stable.git 42 | GIT_TAG v${SDBUSCPP_LIBSYSTEMD_VERSION}-stable 43 | GIT_SHALLOW 1 44 | UPDATE_COMMAND "" 45 | CONFIGURE_COMMAND ${CMAKE_COMMAND} -E remove /* 46 | COMMAND ${MESON} --prefix= --buildtype=${LIBSYSTEMD_BUILD_TYPE} -Drootprefix= -Dstatic-libsystemd=pic -Dselinux=false ${SDBUSCPP_LIBSYSTEMD_EXTRA_CONFIG_OPTS} 47 | BUILD_COMMAND ${BUILD_VERSION_H} 48 | COMMAND ${NINJA} -C libsystemd.a 49 | BUILD_ALWAYS 0 50 | INSTALL_COMMAND ${CMAKE_COMMAND} -E copy_directory /src/systemd /include/systemd 51 | LOG_DOWNLOAD 1 LOG_UPDATE 1 LOG_CONFIGURE 1 LOG_BUILD 1 52 | BUILD_BYPRODUCTS /libsystemd.a) 53 | 54 | ExternalProject_Get_property(LibsystemdBuildProject SOURCE_DIR) 55 | ExternalProject_Get_property(LibsystemdBuildProject BINARY_DIR) 56 | ExternalProject_Get_property(LibsystemdBuildProject INSTALL_DIR) 57 | 58 | add_library(Systemd::Libsystemd STATIC IMPORTED) 59 | set_target_properties(Systemd::Libsystemd PROPERTIES IMPORTED_LOCATION ${BINARY_DIR}/libsystemd.a) 60 | file(MAKE_DIRECTORY ${INSTALL_DIR}/include/systemd) # Trick for CMake to stop complaining about non-existent ${INSTALL_DIR}/include directory 61 | target_include_directories(Systemd::Libsystemd INTERFACE ${INSTALL_DIR}/include) 62 | target_link_libraries(Systemd::Libsystemd INTERFACE ${CAP_LIBRARIES} ${GLIBC_RT_LIBRARY} ${MOUNT_LIBRARIES}) 63 | -------------------------------------------------------------------------------- /cmake/sdbus-c++-config.cmake.in: -------------------------------------------------------------------------------- 1 | @PACKAGE_INIT@ 2 | 3 | include("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@-targets.cmake") 4 | check_required_components("@PROJECT_NAME@") 5 | -------------------------------------------------------------------------------- /docs/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Building doxygen documentation 2 | 3 | find_package(Doxygen) 4 | 5 | if(SDBUSCPP_BUILD_DOXYGEN_DOCS) 6 | if(DOXYGEN_FOUND) 7 | configure_file(${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile @ONLY) 8 | 9 | add_custom_target(doc 10 | COMMAND ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile 11 | WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} 12 | COMMENT "Generating API documentation with Doxygen" 13 | VERBATIM) 14 | 15 | # workaround bug https://github.com/doxygen/doxygen/pull/6787 16 | add_custom_command(TARGET doc POST_BUILD 17 | COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_LIST_DIR}/sdbus-c++-class-diagram.png ${CMAKE_CURRENT_BINARY_DIR}/html/.) 18 | else() 19 | message(WARNING "Documentation enabled, but Doxygen cannot be found") 20 | endif() 21 | endif() 22 | 23 | if(SDBUSCPP_INSTALL) 24 | install(FILES sdbus-c++-class-diagram.png 25 | sdbus-c++-class-diagram.uml 26 | systemd-dbus-config.md 27 | using-sdbus-c++.md 28 | DESTINATION ${CMAKE_INSTALL_DOCDIR} COMPONENT sdbus-c++-doc) 29 | 30 | if (SDBUSCPP_BUILD_DOXYGEN_DOCS AND DOXYGEN_FOUND) 31 | install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/html DESTINATION ${CMAKE_INSTALL_DOCDIR} OPTIONAL COMPONENT sdbus-c++-doc) 32 | endif() 33 | endif() 34 | -------------------------------------------------------------------------------- /docs/sdbus-c++-class-diagram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kistler-Group/sdbus-cpp/7fbfcec455a2af6efe3910baa3089ecba48a9d6d/docs/sdbus-c++-class-diagram.png -------------------------------------------------------------------------------- /docs/sdbus-c++-class-diagram.uml: -------------------------------------------------------------------------------- 1 | @startuml 2 | 3 | package "Public API" <> #DDDDDD { 4 | interface IConnection { 5 | +requestName() 6 | +enterProcessLoop() 7 | +leaveProcessLoop() 8 | } 9 | 10 | interface IObject { 11 | +registerMethod() 12 | +emitSignal() 13 | } 14 | 15 | interface IProxy { 16 | +callMethod() 17 | +subscribeToSignal() 18 | +get/setProperty() 19 | } 20 | 21 | class Message { 22 | +serialize(...) 23 | +deserialize(...) 24 | +send() 25 | Type msgType 26 | } 27 | } 28 | 29 | interface IConnectionInternal { 30 | +addObjectVTable() 31 | +createMethodCall() 32 | +createSignal() 33 | } 34 | 35 | class Connection { 36 | } 37 | 38 | class Object { 39 | IConnectionInternal& connection 40 | string objectPath 41 | List interfaces 42 | List methods 43 | List signals 44 | List properties 45 | } 46 | 47 | class Proxy { 48 | IConnectionInternal& connection 49 | string destination 50 | string objectPath 51 | List signalHandlers 52 | } 53 | 54 | IConnection <|-- Connection 55 | IConnectionInternal <|- Connection 56 | IObject <|-- Object 57 | IProxy <|-- Proxy 58 | Connection <-- Object : "use" 59 | Connection <-- Proxy : "use" 60 | Message <.. Object : "send/receive" 61 | Message <.. Proxy : "send/receive" 62 | 63 | @enduml 64 | -------------------------------------------------------------------------------- /docs/systemd-dbus-config.md: -------------------------------------------------------------------------------- 1 | Systemd and D-Bus configuration 2 | ======================= 3 | 4 | **Table of contents** 5 | 6 | 1. [Introduction](#introduction) 7 | 2. [Systemd configuration](#systemd-configuration) 8 | 3. [Dbus configuration](#dbus-configuration) 9 | 10 | Introduction 11 | ------------ 12 | 13 | To run executable as a systemd service you may need some additional setup. For example, you may need explicitly allow the usage of your service. Following chapters contain template configurations. 14 | 15 | 16 | Systemd configuration 17 | --------------------------------------- 18 | 19 | Filename should use `.service` extension. It also must be placed in configuration directory (/etc/systemd/system in Ubuntu 18.04.1 LTS) 20 | 21 | ``` 22 | [Unit] 23 | Description=nameOfService 24 | 25 | [Service] 26 | ExecStart=/path/to/executable 27 | 28 | [Install] 29 | WantedBy=multi-user.target 30 | ``` 31 | 32 | D-Bus configuration 33 | ------------------ 34 | 35 | Typical default D-Bus configuration does not allow to register services except explicitly allowed. To allow a service to register its D-Bus API, we must place an appropriate conf file in `/etc/dbus-1/system.d/` directory. The conf file name must be `.conf`. I.e., full file path for Concatenator example from sdbus-c++ tutorial would be `/etc/dbus-1/system.d/org.sdbuscpp.concatenator.conf`. And here is template configuration to use its D-Bus interface under root: 36 | 37 | ``` 38 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | ``` 49 | 50 | If you need access from other user then `root` should be substituted by desired username. Or you can simply use policy `` like [conf file](/tests/integrationtests/files/org.sdbuscpp.integrationtests.conf) for sdbus-c++ integration tests is doing it. For more information refer to `man dbus-daemon`. 51 | -------------------------------------------------------------------------------- /examples/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Building examples 2 | 3 | add_executable(obj-manager-server org.freedesktop.DBus.ObjectManager/obj-manager-server.cpp) 4 | target_link_libraries(obj-manager-server sdbus-c++) 5 | 6 | add_executable(obj-manager-client org.freedesktop.DBus.ObjectManager/obj-manager-client.cpp) 7 | target_link_libraries(obj-manager-client sdbus-c++) 8 | 9 | if(SDBUSCPP_INSTALL) 10 | install(TARGETS obj-manager-server DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT sdbus-c++-examples) 11 | install(TARGETS obj-manager-client DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT sdbus-c++-examples) 12 | endif() 13 | -------------------------------------------------------------------------------- /examples/org.freedesktop.DBus.ObjectManager/examplemanager-planet1-client-glue.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * This file was automatically generated by sdbus-c++-xml2cpp; DO NOT EDIT! 4 | */ 5 | 6 | #ifndef __sdbuscpp__examplemanager_planet1_client_glue_h__proxy__H__ 7 | #define __sdbuscpp__examplemanager_planet1_client_glue_h__proxy__H__ 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | namespace org { 14 | namespace sdbuscpp { 15 | namespace ExampleManager { 16 | 17 | class Planet1_proxy 18 | { 19 | public: 20 | static constexpr const char* INTERFACE_NAME = "org.sdbuscpp.ExampleManager.Planet1"; 21 | 22 | protected: 23 | Planet1_proxy(sdbus::IProxy& proxy) 24 | : m_proxy(proxy) 25 | { 26 | } 27 | 28 | Planet1_proxy(const Planet1_proxy&) = delete; 29 | Planet1_proxy& operator=(const Planet1_proxy&) = delete; 30 | Planet1_proxy(Planet1_proxy&&) = delete; 31 | Planet1_proxy& operator=(Planet1_proxy&&) = delete; 32 | 33 | ~Planet1_proxy() = default; 34 | 35 | void registerProxy() 36 | { 37 | } 38 | 39 | public: 40 | uint64_t GetPopulation() 41 | { 42 | uint64_t result; 43 | m_proxy.callMethod("GetPopulation").onInterface(INTERFACE_NAME).storeResultsTo(result); 44 | return result; 45 | } 46 | 47 | public: 48 | std::string Name() 49 | { 50 | return m_proxy.getProperty("Name").onInterface(INTERFACE_NAME).get(); 51 | } 52 | 53 | private: 54 | sdbus::IProxy& m_proxy; 55 | }; 56 | 57 | }}} // namespaces 58 | 59 | #endif 60 | -------------------------------------------------------------------------------- /examples/org.freedesktop.DBus.ObjectManager/examplemanager-planet1-server-glue.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * This file was automatically generated by sdbus-c++-xml2cpp; DO NOT EDIT! 4 | */ 5 | 6 | #ifndef __sdbuscpp__examplemanager_planet1_server_glue_h__adaptor__H__ 7 | #define __sdbuscpp__examplemanager_planet1_server_glue_h__adaptor__H__ 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | namespace org { 14 | namespace sdbuscpp { 15 | namespace ExampleManager { 16 | 17 | class Planet1_adaptor 18 | { 19 | public: 20 | static constexpr const char* INTERFACE_NAME = "org.sdbuscpp.ExampleManager.Planet1"; 21 | 22 | protected: 23 | Planet1_adaptor(sdbus::IObject& object) 24 | : m_object(object) 25 | { 26 | } 27 | 28 | Planet1_adaptor(const Planet1_adaptor&) = delete; 29 | Planet1_adaptor& operator=(const Planet1_adaptor&) = delete; 30 | Planet1_adaptor(Planet1_adaptor&&) = delete; 31 | Planet1_adaptor& operator=(Planet1_adaptor&&) = delete; 32 | 33 | ~Planet1_adaptor() = default; 34 | 35 | void registerAdaptor() 36 | { 37 | m_object.addVTable( sdbus::registerMethod("GetPopulation").withOutputParamNames("population").implementedAs([this](){ return this->GetPopulation(); }) 38 | , sdbus::registerProperty("Name").withGetter([this](){ return this->Name(); }) 39 | ).forInterface(INTERFACE_NAME); 40 | } 41 | 42 | private: 43 | virtual uint64_t GetPopulation() = 0; 44 | 45 | private: 46 | virtual std::string Name() = 0; 47 | 48 | private: 49 | sdbus::IObject& m_object; 50 | }; 51 | 52 | }}} // namespaces 53 | 54 | #endif 55 | -------------------------------------------------------------------------------- /examples/org.freedesktop.DBus.ObjectManager/obj-manager-client.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Example of a D-Bus client which implements org.freedesktop.DBus.ObjectManager 3 | * 4 | * The example uses the generated stub API layer to listen to interfaces added to new objects under 5 | * "org.sdbuscpp.examplemanager". If added, we access "org.sdbuscpp.ExampleManager.Planet1" to print 6 | * info like this: 7 | * /org/sdbuscpp/examplemanager/Planet1/Earth added: org.sdbuscpp.ExampleManager.Planet1 8 | * Earth has a population of 7874965825. 9 | * 10 | */ 11 | 12 | #include "examplemanager-planet1-client-glue.h" 13 | #include 14 | #include 15 | #include 16 | 17 | class PlanetProxy final : public sdbus::ProxyInterfaces< org::sdbuscpp::ExampleManager::Planet1_proxy > 18 | { 19 | public: 20 | PlanetProxy(sdbus::IConnection& connection, sdbus::ServiceName destination, sdbus::ObjectPath path) 21 | : ProxyInterfaces(connection, std::move(destination), std::move(path)) 22 | { 23 | registerProxy(); 24 | } 25 | 26 | ~PlanetProxy() 27 | { 28 | unregisterProxy(); 29 | } 30 | }; 31 | 32 | class ManagerProxy final : public sdbus::ProxyInterfaces 33 | { 34 | public: 35 | ManagerProxy(sdbus::IConnection& connection, sdbus::ServiceName destination, sdbus::ObjectPath path) 36 | : ProxyInterfaces(connection, destination, std::move(path)) 37 | , m_connection(connection) 38 | , m_destination(destination) 39 | { 40 | registerProxy(); 41 | } 42 | 43 | ~ManagerProxy() 44 | { 45 | unregisterProxy(); 46 | } 47 | 48 | void handleExistingObjects() 49 | { 50 | auto objectsInterfacesAndProperties = GetManagedObjects(); 51 | for (const auto& [object, interfacesAndProperties] : objectsInterfacesAndProperties) { 52 | onInterfacesAdded(object, interfacesAndProperties); 53 | } 54 | } 55 | 56 | private: 57 | void onInterfacesAdded( const sdbus::ObjectPath& objectPath 58 | , const std::map>& interfacesAndProperties) override 59 | { 60 | std::cout << objectPath << " added:\t"; 61 | for (const auto& [interface, _] : interfacesAndProperties) { 62 | std::cout << interface << " "; 63 | } 64 | std::cout << std::endl; 65 | 66 | // Parse and print some more info 67 | auto planetInterface = interfacesAndProperties.find(sdbus::InterfaceName{org::sdbuscpp::ExampleManager::Planet1_proxy::INTERFACE_NAME}); 68 | if (planetInterface == interfacesAndProperties.end()) { 69 | return; 70 | } 71 | const auto& properties = planetInterface->second; 72 | // get a property which was passed as part of the signal. 73 | const auto& name = properties.at(sdbus::PropertyName{"Name"}).get(); 74 | // or create a proxy instance to the newly added object. 75 | PlanetProxy planet(m_connection, m_destination, objectPath); 76 | std::cout << name << " has a population of " << planet.GetPopulation() << ".\n" << std::endl; 77 | } 78 | 79 | void onInterfacesRemoved( const sdbus::ObjectPath& objectPath 80 | , const std::vector& interfaces) override 81 | { 82 | std::cout << objectPath << " removed:\t"; 83 | for (const auto& interface : interfaces) { 84 | std::cout << interface << " "; 85 | } 86 | std::cout << std::endl; 87 | } 88 | 89 | sdbus::IConnection& m_connection; 90 | sdbus::ServiceName m_destination; 91 | }; 92 | 93 | int main() 94 | { 95 | auto connection = sdbus::createSessionBusConnection(); 96 | 97 | sdbus::ServiceName destination{"org.sdbuscpp.examplemanager"}; 98 | sdbus::ObjectPath objectPath{"/org/sdbuscpp/examplemanager"}; 99 | auto managerProxy = std::make_unique(*connection, std::move(destination), std::move(objectPath)); 100 | try { 101 | managerProxy->handleExistingObjects(); 102 | } 103 | catch (const sdbus::Error& e) { 104 | if (e.getName() == "org.freedesktop.DBus.Error.ServiceUnknown") { 105 | std::cout << "Waiting for server to start ..." << std::endl; 106 | } 107 | } 108 | 109 | connection->enterEventLoop(); 110 | return 0; 111 | } 112 | -------------------------------------------------------------------------------- /examples/org.freedesktop.DBus.ObjectManager/obj-manager-server.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Example of a D-Bus server which implements org.freedesktop.DBus.ObjectManager 3 | * 4 | * The example uses the generated stub API layer to register an object manager under "org.sdbuscpp.examplemanager" 5 | * and add objects underneath which implement "org.sdbuscpp.ExampleManager.Planet1". 6 | * 7 | * We add and remove objects after a few seconds and print info like this: 8 | * Creating PlanetAdaptor in 5 4 3 2 1 9 | * Creating PlanetAdaptor in 5 4 3 2 1 10 | * Creating PlanetAdaptor in 5 4 3 2 1 11 | * Removing PlanetAdaptor in 5 4 3 2 1 12 | * Removing PlanetAdaptor in 5 4 3 2 1 13 | */ 14 | 15 | #include "examplemanager-planet1-server-glue.h" 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | using sdbus::ObjectPath; 23 | 24 | class ManagerAdaptor : public sdbus::AdaptorInterfaces 25 | { 26 | public: 27 | ManagerAdaptor(sdbus::IConnection& connection, sdbus::ObjectPath path) 28 | : AdaptorInterfaces(connection, std::move(path)) 29 | { 30 | registerAdaptor(); 31 | } 32 | 33 | ~ManagerAdaptor() 34 | { 35 | unregisterAdaptor(); 36 | } 37 | }; 38 | 39 | class PlanetAdaptor final : public sdbus::AdaptorInterfaces< org::sdbuscpp::ExampleManager::Planet1_adaptor 40 | , sdbus::ManagedObject_adaptor 41 | , sdbus::Properties_adaptor > 42 | { 43 | public: 44 | PlanetAdaptor(sdbus::IConnection& connection, sdbus::ObjectPath path, std::string name, uint64_t population) 45 | : AdaptorInterfaces(connection, std::move(path)) 46 | , m_name(std::move(name)) 47 | , m_population(population) 48 | { 49 | registerAdaptor(); 50 | emitInterfacesAddedSignal({sdbus::InterfaceName{org::sdbuscpp::ExampleManager::Planet1_adaptor::INTERFACE_NAME}}); 51 | } 52 | 53 | ~PlanetAdaptor() 54 | { 55 | emitInterfacesRemovedSignal({sdbus::InterfaceName{org::sdbuscpp::ExampleManager::Planet1_adaptor::INTERFACE_NAME}}); 56 | unregisterAdaptor(); 57 | } 58 | 59 | uint64_t GetPopulation() override 60 | { 61 | return m_population; 62 | } 63 | 64 | std::string Name() override 65 | { 66 | return m_name; 67 | } 68 | 69 | private: 70 | std::string m_name; 71 | uint64_t m_population; 72 | }; 73 | 74 | void printCountDown(const std::string& message, int seconds) 75 | { 76 | std::cout << message << std::flush; 77 | for (int i = seconds; i > 0; i--) { 78 | std::this_thread::sleep_for(std::chrono::seconds(1)); 79 | std::cout << i << " " << std::flush; 80 | } 81 | std::cout << std::endl; 82 | } 83 | 84 | int main() 85 | { 86 | auto connection = sdbus::createSessionBusConnection(); 87 | sdbus::ServiceName serviceName{"org.sdbuscpp.examplemanager"}; 88 | connection->requestName(serviceName); 89 | connection->enterEventLoopAsync(); 90 | 91 | auto manager = std::make_unique(*connection, ObjectPath{"/org/sdbuscpp/examplemanager"}); 92 | while (true) 93 | { 94 | printCountDown("Creating PlanetAdaptor in ", 5); 95 | auto earth = std::make_unique(*connection, ObjectPath{"/org/sdbuscpp/examplemanager/Planet1/Earth"}, "Earth", 7'874'965'825); 96 | printCountDown("Creating PlanetAdaptor in ", 5); 97 | auto trantor = std::make_unique(*connection, ObjectPath{"/org/sdbuscpp/examplemanager/Planet1/Trantor"}, "Trantor", 40'000'000'000); 98 | printCountDown("Creating PlanetAdaptor in ", 5); 99 | auto laconia = std::make_unique(*connection, ObjectPath{"/org/sdbuscpp/examplemanager/Planet1/Laconia"}, "Laconia", 231'721); 100 | printCountDown("Removing PlanetAdaptor in ", 5); 101 | earth.reset(); 102 | printCountDown("Removing PlanetAdaptor in ", 5); 103 | trantor.reset(); 104 | printCountDown("Removing PlanetAdaptor in ", 5); 105 | laconia.reset(); 106 | } 107 | 108 | connection->releaseName(serviceName); 109 | connection->leaveEventLoop(); 110 | return 0; 111 | } 112 | -------------------------------------------------------------------------------- /examples/org.freedesktop.DBus.ObjectManager/org.sdbuscpp.ExampleManager.Planet1.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 10 | 11 | 12 | 13 | 14 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /include/sdbus-c++/AdaptorInterfaces.h: -------------------------------------------------------------------------------- 1 | /** 2 | * (C) 2016 - 2021 KISTLER INSTRUMENTE AG, Winterthur, Switzerland 3 | * (C) 2016 - 2024 Stanislav Angelovic 4 | * 5 | * @file AdaptorInterfaces.h 6 | * 7 | * Created on: Nov 8, 2016 8 | * Project: sdbus-c++ 9 | * Description: High-level D-Bus IPC C++ library based on sd-bus 10 | * 11 | * This file is part of sdbus-c++. 12 | * 13 | * sdbus-c++ is free software; you can redistribute it and/or modify it 14 | * under the terms of the GNU Lesser General Public License as published by 15 | * the Free Software Foundation, either version 2.1 of the License, or 16 | * (at your option) any later version. 17 | * 18 | * sdbus-c++ is distributed in the hope that it will be useful, 19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 | * GNU Lesser General Public License for more details. 22 | * 23 | * You should have received a copy of the GNU Lesser General Public License 24 | * along with sdbus-c++. If not, see . 25 | */ 26 | 27 | #ifndef SDBUS_CXX_ADAPTORINTERFACES_H_ 28 | #define SDBUS_CXX_ADAPTORINTERFACES_H_ 29 | 30 | #include 31 | #include 32 | #include 33 | #include 34 | 35 | // Forward declarations 36 | namespace sdbus { 37 | class IConnection; 38 | } 39 | 40 | namespace sdbus { 41 | 42 | /********************************************//** 43 | * @class ObjectHolder 44 | * 45 | * ObjectHolder is a helper that simply owns and provides 46 | * access to an object to other classes in the inheritance 47 | * hierarchy of an object based on generated interface classes. 48 | * 49 | ***********************************************/ 50 | class ObjectHolder 51 | { 52 | protected: 53 | ObjectHolder(std::unique_ptr&& object) 54 | : object_(std::move(object)) 55 | { 56 | } 57 | 58 | const IObject& getObject() const 59 | { 60 | assert(object_ != nullptr); 61 | return *object_; 62 | } 63 | 64 | IObject& getObject() 65 | { 66 | assert(object_ != nullptr); 67 | return *object_; 68 | } 69 | 70 | private: 71 | std::unique_ptr object_; 72 | }; 73 | 74 | /********************************************//** 75 | * @class AdaptorInterfaces 76 | * 77 | * AdaptorInterfaces is a helper template class that joins all interface classes of a remote 78 | * D-Bus object generated by sdbus-c++-xml2cpp to be used on the server (the adaptor) side, 79 | * including some auxiliary classes. AdaptorInterfaces is the class that native-like object 80 | * implementation classes written by users should inherit from and implement all pure virtual 81 | * methods. So the _Interfaces template parameter is a list of sdbus-c++-xml2cpp-generated 82 | * adaptor-side interface classes representing interfaces (with methods, signals and properties) 83 | * of the D-Bus object. 84 | * 85 | * In the final adaptor class inherited from AdaptorInterfaces, one needs to make sure: 86 | * 1. to call `registerAdaptor();` in the class constructor, and, conversely, 87 | * 2. to call `unregisterAdaptor();` in the class destructor, 88 | * so that the object API vtable is registered and unregistered at the proper time. 89 | * 90 | ***********************************************/ 91 | template 92 | class AdaptorInterfaces 93 | : protected ObjectHolder 94 | , public _Interfaces... 95 | { 96 | public: 97 | /*! 98 | * @brief Creates object instance 99 | * 100 | * @param[in] connection D-Bus connection where the object will publish itself 101 | * @param[in] objectPath Path of the D-Bus object 102 | * 103 | * For more information, consult @ref createObject(sdbus::IConnection&,std::string) 104 | */ 105 | AdaptorInterfaces(IConnection& connection, ObjectPath objectPath) 106 | : ObjectHolder(createObject(connection, std::move(objectPath))) 107 | , _Interfaces(getObject())... 108 | { 109 | } 110 | 111 | /*! 112 | * @brief Adds object vtable (i.e. D-Bus API) definitions for all interfaces it implements 113 | * 114 | * This function must be called in the constructor of the final adaptor class that implements AdaptorInterfaces. 115 | * 116 | * See also @ref IObject::addVTable() 117 | */ 118 | void registerAdaptor() 119 | { 120 | (_Interfaces::registerAdaptor(), ...); 121 | } 122 | 123 | /*! 124 | * @brief Unregisters adaptors's API and removes it from the bus 125 | * 126 | * This function must be called in the destructor of the final adaptor class that implements AdaptorInterfaces. 127 | * 128 | * For more information, see underlying @ref IObject::unregister() 129 | */ 130 | void unregisterAdaptor() 131 | { 132 | getObject().unregister(); 133 | } 134 | 135 | /*! 136 | * @brief Returns reference to the underlying IObject instance 137 | */ 138 | using ObjectHolder::getObject; 139 | 140 | protected: 141 | using base_type = AdaptorInterfaces; 142 | 143 | AdaptorInterfaces(const AdaptorInterfaces&) = delete; 144 | AdaptorInterfaces& operator=(const AdaptorInterfaces&) = delete; 145 | AdaptorInterfaces(AdaptorInterfaces&&) = delete; 146 | AdaptorInterfaces& operator=(AdaptorInterfaces&&) = delete; 147 | ~AdaptorInterfaces() = default; 148 | }; 149 | 150 | } 151 | 152 | #endif /* SDBUS_CXX_ADAPTORINTERFACES_H_ */ 153 | -------------------------------------------------------------------------------- /include/sdbus-c++/Error.h: -------------------------------------------------------------------------------- 1 | /** 2 | * (C) 2016 - 2021 KISTLER INSTRUMENTE AG, Winterthur, Switzerland 3 | * (C) 2016 - 2024 Stanislav Angelovic 4 | * 5 | * @file Error.h 6 | * 7 | * Created on: Nov 8, 2016 8 | * Project: sdbus-c++ 9 | * Description: High-level D-Bus IPC C++ library based on sd-bus 10 | * 11 | * This file is part of sdbus-c++. 12 | * 13 | * sdbus-c++ is free software; you can redistribute it and/or modify it 14 | * under the terms of the GNU Lesser General Public License as published by 15 | * the Free Software Foundation, either version 2.1 of the License, or 16 | * (at your option) any later version. 17 | * 18 | * sdbus-c++ is distributed in the hope that it will be useful, 19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 | * GNU Lesser General Public License for more details. 22 | * 23 | * You should have received a copy of the GNU Lesser General Public License 24 | * along with sdbus-c++. If not, see . 25 | */ 26 | 27 | #ifndef SDBUS_CXX_ERROR_H_ 28 | #define SDBUS_CXX_ERROR_H_ 29 | 30 | #include 31 | #include 32 | #include 33 | 34 | namespace sdbus { 35 | 36 | /********************************************//** 37 | * @class Error 38 | * 39 | * Represents a common sdbus-c++ exception. 40 | * 41 | ***********************************************/ 42 | class Error 43 | : public std::runtime_error 44 | { 45 | public: 46 | // Strong type representing the D-Bus error name 47 | class Name : public std::string 48 | { 49 | public: 50 | Name() = default; 51 | explicit Name(std::string value) 52 | : std::string(std::move(value)) 53 | {} 54 | explicit Name(const char* value) 55 | : std::string(value) 56 | {} 57 | 58 | using std::string::operator=; 59 | }; 60 | 61 | explicit Error(Name name, const char* message = nullptr) 62 | : Error(std::move(name), std::string(message ? message : "")) 63 | { 64 | } 65 | 66 | Error(Name name, std::string message) 67 | : std::runtime_error("[" + name + "] " + message) 68 | , name_(std::move(name)) 69 | , message_(std::move(message)) 70 | { 71 | } 72 | 73 | [[nodiscard]] const Name& getName() const 74 | { 75 | return name_; 76 | } 77 | 78 | [[nodiscard]] const std::string& getMessage() const 79 | { 80 | return message_; 81 | } 82 | 83 | [[nodiscard]] bool isValid() const 84 | { 85 | return !getName().empty(); 86 | } 87 | 88 | private: 89 | Name name_; 90 | std::string message_; 91 | }; 92 | 93 | Error createError(int errNo, std::string customMsg); 94 | 95 | inline const Error::Name SDBUSCPP_ERROR_NAME{"org.sdbuscpp.Error"}; 96 | } 97 | 98 | #define SDBUS_THROW_ERROR(_MSG, _ERRNO) \ 99 | throw sdbus::createError((_ERRNO), (_MSG)) \ 100 | /**/ 101 | 102 | #define SDBUS_THROW_ERROR_IF(_COND, _MSG, _ERRNO) \ 103 | if (!(_COND)) ; else SDBUS_THROW_ERROR((_MSG), (_ERRNO)) \ 104 | /**/ 105 | 106 | #endif /* SDBUS_CXX_ERROR_H_ */ 107 | -------------------------------------------------------------------------------- /include/sdbus-c++/Flags.h: -------------------------------------------------------------------------------- 1 | /** 2 | * (C) 2016 - 2021 KISTLER INSTRUMENTE AG, Winterthur, Switzerland 3 | * (C) 2016 - 2024 Stanislav Angelovic 4 | * 5 | * @file Flags.h 6 | * 7 | * Created on: Dec 31, 2018 8 | * Project: sdbus-c++ 9 | * Description: High-level D-Bus IPC C++ library based on sd-bus 10 | * 11 | * This file is part of sdbus-c++. 12 | * 13 | * sdbus-c++ is free software; you can redistribute it and/or modify it 14 | * under the terms of the GNU Lesser General Public License as published by 15 | * the Free Software Foundation, either version 2.1 of the License, or 16 | * (at your option) any later version. 17 | * 18 | * sdbus-c++ is distributed in the hope that it will be useful, 19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 | * GNU Lesser General Public License for more details. 22 | * 23 | * You should have received a copy of the GNU Lesser General Public License 24 | * along with sdbus-c++. If not, see . 25 | */ 26 | 27 | #ifndef SDBUS_CXX_FLAGS_H_ 28 | #define SDBUS_CXX_FLAGS_H_ 29 | 30 | #include 31 | #include 32 | 33 | namespace sdbus { 34 | 35 | // D-Bus interface, method, signal or property flags 36 | class Flags 37 | { 38 | public: 39 | enum GeneralFlags : uint8_t 40 | { DEPRECATED = 0 41 | , METHOD_NO_REPLY = 1 42 | , PRIVILEGED = 2 43 | }; 44 | 45 | enum PropertyUpdateBehaviorFlags : uint8_t 46 | { EMITS_CHANGE_SIGNAL = 3 47 | , EMITS_INVALIDATION_SIGNAL = 4 48 | , EMITS_NO_SIGNAL = 5 49 | , CONST_PROPERTY_VALUE = 6 50 | }; 51 | 52 | enum : uint8_t 53 | { FLAG_COUNT = 7 54 | }; 55 | 56 | Flags() 57 | { 58 | // EMITS_CHANGE_SIGNAL is on by default 59 | flags_.set(EMITS_CHANGE_SIGNAL, true); 60 | } 61 | 62 | void set(GeneralFlags flag, bool value = true) 63 | { 64 | flags_.set(flag, value); 65 | } 66 | 67 | void set(PropertyUpdateBehaviorFlags flag, bool value = true) 68 | { 69 | flags_.set(EMITS_CHANGE_SIGNAL, false); 70 | flags_.set(EMITS_INVALIDATION_SIGNAL, false); 71 | flags_.set(EMITS_NO_SIGNAL, false); 72 | flags_.set(CONST_PROPERTY_VALUE, false); 73 | 74 | flags_.set(flag, value); 75 | } 76 | 77 | [[nodiscard]] bool test(GeneralFlags flag) const 78 | { 79 | return flags_.test(flag); 80 | } 81 | 82 | [[nodiscard]] bool test(PropertyUpdateBehaviorFlags flag) const 83 | { 84 | return flags_.test(flag); 85 | } 86 | 87 | [[nodiscard]] uint64_t toSdBusInterfaceFlags() const; 88 | [[nodiscard]] uint64_t toSdBusMethodFlags() const; 89 | [[nodiscard]] uint64_t toSdBusSignalFlags() const; 90 | [[nodiscard]] uint64_t toSdBusPropertyFlags() const; 91 | [[nodiscard]] uint64_t toSdBusWritablePropertyFlags() const; 92 | 93 | private: 94 | std::bitset flags_; 95 | }; 96 | 97 | } 98 | 99 | #endif /* SDBUS_CXX_FLAGS_H_ */ 100 | -------------------------------------------------------------------------------- /include/sdbus-c++/MethodResult.h: -------------------------------------------------------------------------------- 1 | /** 2 | * (C) 2016 - 2021 KISTLER INSTRUMENTE AG, Winterthur, Switzerland 3 | * (C) 2016 - 2024 Stanislav Angelovic 4 | * 5 | * @file MethodResult.h 6 | * 7 | * Created on: Nov 8, 2016 8 | * Project: sdbus-c++ 9 | * Description: High-level D-Bus IPC C++ library based on sd-bus 10 | * 11 | * This file is part of sdbus-c++. 12 | * 13 | * sdbus-c++ is free software; you can redistribute it and/or modify it 14 | * under the terms of the GNU Lesser General Public License as published by 15 | * the Free Software Foundation, either version 2.1 of the License, or 16 | * (at your option) any later version. 17 | * 18 | * sdbus-c++ is distributed in the hope that it will be useful, 19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 | * GNU Lesser General Public License for more details. 22 | * 23 | * You should have received a copy of the GNU Lesser General Public License 24 | * along with sdbus-c++. If not, see . 25 | */ 26 | 27 | #ifndef SDBUS_CXX_METHODRESULT_H_ 28 | #define SDBUS_CXX_METHODRESULT_H_ 29 | 30 | #include 31 | 32 | #include 33 | 34 | // Forward declarations 35 | namespace sdbus { 36 | class Error; 37 | } 38 | 39 | namespace sdbus { 40 | 41 | /********************************************//** 42 | * @class Result 43 | * 44 | * Represents result of an asynchronous server-side method. 45 | * An instance is provided to the method and shall be set 46 | * by the method to either method return value or an error. 47 | * 48 | ***********************************************/ 49 | template 50 | class Result 51 | { 52 | public: 53 | Result() = default; 54 | Result(MethodCall call); 55 | 56 | Result(const Result&) = delete; 57 | Result& operator=(const Result&) = delete; 58 | 59 | Result(Result&& other) = default; 60 | Result& operator=(Result&& other) = default; 61 | 62 | void returnResults(const _Results&... results) const; 63 | void returnError(const Error& error) const; 64 | 65 | private: 66 | MethodCall call_; 67 | }; 68 | 69 | template 70 | inline Result<_Results...>::Result(MethodCall call) 71 | : call_(std::move(call)) 72 | { 73 | } 74 | 75 | template 76 | inline void Result<_Results...>::returnResults(const _Results&... results) const 77 | { 78 | assert(call_.isValid()); 79 | auto reply = call_.createReply(); 80 | (void)(reply << ... << results); 81 | reply.send(); 82 | } 83 | 84 | template 85 | inline void Result<_Results...>::returnError(const Error& error) const 86 | { 87 | auto reply = call_.createErrorReply(error); 88 | reply.send(); 89 | } 90 | 91 | } 92 | 93 | #endif /* SDBUS_CXX_METHODRESULT_H_ */ 94 | -------------------------------------------------------------------------------- /include/sdbus-c++/VTableItems.h: -------------------------------------------------------------------------------- 1 | /** 2 | * (C) 2016 - 2024 Stanislav Angelovic 3 | * 4 | * @file VTableItems.h 5 | * 6 | * Created on: Dec 14, 2023 7 | * Project: sdbus-c++ 8 | * Description: High-level D-Bus IPC C++ library based on sd-bus 9 | * 10 | * This file is part of sdbus-c++. 11 | * 12 | * sdbus-c++ is free software; you can redistribute it and/or modify it 13 | * under the terms of the GNU Lesser General Public License as published by 14 | * the Free Software Foundation, either version 2.1 of the License, or 15 | * (at your option) any later version. 16 | * 17 | * sdbus-c++ is distributed in the hope that it will be useful, 18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | * GNU Lesser General Public License for more details. 21 | * 22 | * You should have received a copy of the GNU Lesser General Public License 23 | * along with sdbus-c++. If not, see . 24 | */ 25 | 26 | #ifndef SDBUS_CXX_VTABLEITEMS_H_ 27 | #define SDBUS_CXX_VTABLEITEMS_H_ 28 | 29 | #include 30 | #include 31 | #include 32 | 33 | #include 34 | #include 35 | #include 36 | 37 | namespace sdbus { 38 | 39 | struct MethodVTableItem 40 | { 41 | template MethodVTableItem& implementedAs(_Function&& callback); 42 | MethodVTableItem& withInputParamNames(std::vector names); 43 | template MethodVTableItem& withInputParamNames(_String... names); 44 | MethodVTableItem& withOutputParamNames(std::vector names); 45 | template MethodVTableItem& withOutputParamNames(_String... names); 46 | MethodVTableItem& markAsDeprecated(); 47 | MethodVTableItem& markAsPrivileged(); 48 | MethodVTableItem& withNoReply(); 49 | 50 | MethodName name; 51 | Signature inputSignature; 52 | std::vector inputParamNames; 53 | Signature outputSignature; 54 | std::vector outputParamNames; 55 | method_callback callbackHandler; 56 | Flags flags; 57 | }; 58 | 59 | MethodVTableItem registerMethod(MethodName methodName); 60 | MethodVTableItem registerMethod(std::string methodName); 61 | 62 | struct SignalVTableItem 63 | { 64 | template SignalVTableItem& withParameters(); 65 | template SignalVTableItem& withParameters(std::vector names); 66 | template SignalVTableItem& withParameters(_String... names); 67 | SignalVTableItem& markAsDeprecated(); 68 | 69 | SignalName name; 70 | Signature signature; 71 | std::vector paramNames; 72 | Flags flags; 73 | }; 74 | 75 | SignalVTableItem registerSignal(SignalName signalName); 76 | SignalVTableItem registerSignal(std::string signalName); 77 | 78 | struct PropertyVTableItem 79 | { 80 | template PropertyVTableItem& withGetter(_Function&& callback); 81 | template PropertyVTableItem& withSetter(_Function&& callback); 82 | PropertyVTableItem& markAsDeprecated(); 83 | PropertyVTableItem& markAsPrivileged(); 84 | PropertyVTableItem& withUpdateBehavior(Flags::PropertyUpdateBehaviorFlags behavior); 85 | 86 | PropertyName name; 87 | Signature signature; 88 | property_get_callback getter; 89 | property_set_callback setter; 90 | Flags flags; 91 | }; 92 | 93 | PropertyVTableItem registerProperty(PropertyName propertyName); 94 | PropertyVTableItem registerProperty(std::string propertyName); 95 | 96 | struct InterfaceFlagsVTableItem 97 | { 98 | InterfaceFlagsVTableItem& markAsDeprecated(); 99 | InterfaceFlagsVTableItem& markAsPrivileged(); 100 | InterfaceFlagsVTableItem& withNoReplyMethods(); 101 | InterfaceFlagsVTableItem& withPropertyUpdateBehavior(Flags::PropertyUpdateBehaviorFlags behavior); 102 | 103 | Flags flags; 104 | }; 105 | 106 | InterfaceFlagsVTableItem setInterfaceFlags(); 107 | 108 | using VTableItem = std::variant; 109 | 110 | } // namespace sdbus 111 | 112 | #endif /* SDBUS_CXX_VTABLEITEMS_H_ */ 113 | -------------------------------------------------------------------------------- /include/sdbus-c++/sdbus-c++.h: -------------------------------------------------------------------------------- 1 | /** 2 | * (C) 2016 - 2021 KISTLER INSTRUMENTE AG, Winterthur, Switzerland 3 | * (C) 2016 - 2024 Stanislav Angelovic 4 | * 5 | * @file sdbus-c++.h 6 | * 7 | * Created on: Jan 19, 2017 8 | * Project: sdbus-c++ 9 | * Description: High-level D-Bus IPC C++ library based on sd-bus 10 | * 11 | * This file is part of sdbus-c++. 12 | * 13 | * sdbus-c++ is free software; you can redistribute it and/or modify it 14 | * under the terms of the GNU Lesser General Public License as published by 15 | * the Free Software Foundation, either version 2.1 of the License, or 16 | * (at your option) any later version. 17 | * 18 | * sdbus-c++ is distributed in the hope that it will be useful, 19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 | * GNU Lesser General Public License for more details. 22 | * 23 | * You should have received a copy of the GNU Lesser General Public License 24 | * along with sdbus-c++. If not, see . 25 | */ 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | -------------------------------------------------------------------------------- /pkgconfig/sdbus-c++.pc.in: -------------------------------------------------------------------------------- 1 | prefix=@CMAKE_INSTALL_PREFIX@ 2 | exec_prefix=@CMAKE_INSTALL_PREFIX@ 3 | libdir=@CMAKE_INSTALL_FULL_LIBDIR@ 4 | includedir=@CMAKE_INSTALL_FULL_INCLUDEDIR@ 5 | 6 | Name: @PROJECT_NAME@ 7 | Description: C++ library on top of sd-bus, a systemd D-Bus library 8 | Requires@PKGCONFIG_REQS@: @PKGCONFIG_DEPS@ 9 | Version: @SDBUSCPP_VERSION@ 10 | Libs: -L${libdir} -l@PROJECT_NAME@ 11 | Cflags: -I${includedir} 12 | -------------------------------------------------------------------------------- /src/Error.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * (C) 2016 - 2021 KISTLER INSTRUMENTE AG, Winterthur, Switzerland 3 | * (C) 2016 - 2024 Stanislav Angelovic 4 | * 5 | * @file Error.cpp 6 | * 7 | * Created on: Nov 8, 2016 8 | * Project: sdbus-c++ 9 | * Description: High-level D-Bus IPC C++ library based on sd-bus 10 | * 11 | * This file is part of sdbus-c++. 12 | * 13 | * sdbus-c++ is free software; you can redistribute it and/or modify it 14 | * under the terms of the GNU Lesser General Public License as published by 15 | * the Free Software Foundation, either version 2.1 of the License, or 16 | * (at your option) any later version. 17 | * 18 | * sdbus-c++ is distributed in the hope that it will be useful, 19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 | * GNU Lesser General Public License for more details. 22 | * 23 | * You should have received a copy of the GNU Lesser General Public License 24 | * along with sdbus-c++. If not, see . 25 | */ 26 | 27 | #include "sdbus-c++/Error.h" 28 | 29 | #include "ScopeGuard.h" 30 | 31 | #include SDBUS_HEADER 32 | 33 | namespace sdbus 34 | { 35 | sdbus::Error createError(int errNo, std::string customMsg) 36 | { 37 | sd_bus_error sdbusError = SD_BUS_ERROR_NULL; 38 | sd_bus_error_set_errno(&sdbusError, errNo); 39 | SCOPE_EXIT{ sd_bus_error_free(&sdbusError); }; 40 | 41 | Error::Name name(sdbusError.name); 42 | std::string message(std::move(customMsg)); 43 | message.append(" ("); 44 | message.append(sdbusError.message); 45 | message.append(")"); 46 | 47 | return Error(std::move(name), std::move(message)); 48 | } 49 | } // namespace sdbus 50 | -------------------------------------------------------------------------------- /src/Flags.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * (C) 2016 - 2021 KISTLER INSTRUMENTE AG, Winterthur, Switzerland 3 | * (C) 2016 - 2024 Stanislav Angelovic 4 | * 5 | * @file Flags.cpp 6 | * 7 | * Created on: Dec 31, 2018 8 | * Project: sdbus-c++ 9 | * Description: High-level D-Bus IPC C++ library based on sd-bus 10 | * 11 | * This file is part of sdbus-c++. 12 | * 13 | * sdbus-c++ is free software; you can redistribute it and/or modify it 14 | * under the terms of the GNU Lesser General Public License as published by 15 | * the Free Software Foundation, either version 2.1 of the License, or 16 | * (at your option) any later version. 17 | * 18 | * sdbus-c++ is distributed in the hope that it will be useful, 19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 | * GNU Lesser General Public License for more details. 22 | * 23 | * You should have received a copy of the GNU Lesser General Public License 24 | * along with sdbus-c++. If not, see . 25 | */ 26 | 27 | #include 28 | #include SDBUS_HEADER 29 | 30 | namespace sdbus 31 | { 32 | uint64_t Flags::toSdBusInterfaceFlags() const 33 | { 34 | uint64_t sdbusFlags{}; 35 | 36 | using namespace sdbus; 37 | if (flags_.test(Flags::DEPRECATED)) 38 | sdbusFlags |= SD_BUS_VTABLE_DEPRECATED; 39 | if (!flags_.test(Flags::PRIVILEGED)) 40 | sdbusFlags |= SD_BUS_VTABLE_UNPRIVILEGED; 41 | 42 | if (flags_.test(Flags::EMITS_CHANGE_SIGNAL)) 43 | sdbusFlags |= SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE; 44 | else if (flags_.test(Flags::EMITS_INVALIDATION_SIGNAL)) 45 | sdbusFlags |= SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION; 46 | else if (flags_.test(Flags::CONST_PROPERTY_VALUE)) 47 | sdbusFlags |= SD_BUS_VTABLE_PROPERTY_CONST; 48 | else if (flags_.test(Flags::EMITS_NO_SIGNAL)) 49 | sdbusFlags |= 0; 50 | 51 | return sdbusFlags; 52 | } 53 | 54 | uint64_t Flags::toSdBusMethodFlags() const 55 | { 56 | uint64_t sdbusFlags{}; 57 | 58 | using namespace sdbus; 59 | if (flags_.test(Flags::DEPRECATED)) 60 | sdbusFlags |= SD_BUS_VTABLE_DEPRECATED; 61 | if (!flags_.test(Flags::PRIVILEGED)) 62 | sdbusFlags |= SD_BUS_VTABLE_UNPRIVILEGED; 63 | if (flags_.test(Flags::METHOD_NO_REPLY)) 64 | sdbusFlags |= SD_BUS_VTABLE_METHOD_NO_REPLY; 65 | 66 | return sdbusFlags; 67 | } 68 | 69 | uint64_t Flags::toSdBusSignalFlags() const 70 | { 71 | uint64_t sdbusFlags{}; 72 | 73 | using namespace sdbus; 74 | if (flags_.test(Flags::DEPRECATED)) 75 | sdbusFlags |= SD_BUS_VTABLE_DEPRECATED; 76 | 77 | return sdbusFlags; 78 | } 79 | 80 | uint64_t Flags::toSdBusPropertyFlags() const 81 | { 82 | uint64_t sdbusFlags{}; 83 | 84 | using namespace sdbus; 85 | if (flags_.test(Flags::DEPRECATED)) 86 | sdbusFlags |= SD_BUS_VTABLE_DEPRECATED; 87 | //if (!flags_.test(Flags::PRIVILEGED)) 88 | // sdbusFlags |= SD_BUS_VTABLE_UNPRIVILEGED; 89 | 90 | if (flags_.test(Flags::EMITS_CHANGE_SIGNAL)) 91 | sdbusFlags |= SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE; 92 | else if (flags_.test(Flags::EMITS_INVALIDATION_SIGNAL)) 93 | sdbusFlags |= SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION; 94 | else if (flags_.test(Flags::CONST_PROPERTY_VALUE)) 95 | sdbusFlags |= SD_BUS_VTABLE_PROPERTY_CONST; 96 | else if (flags_.test(Flags::EMITS_NO_SIGNAL)) 97 | sdbusFlags |= 0; 98 | 99 | return sdbusFlags; 100 | } 101 | 102 | uint64_t Flags::toSdBusWritablePropertyFlags() const 103 | { 104 | auto sdbusFlags = toSdBusPropertyFlags(); 105 | 106 | using namespace sdbus; 107 | if (!flags_.test(Flags::PRIVILEGED)) 108 | sdbusFlags |= SD_BUS_VTABLE_UNPRIVILEGED; 109 | 110 | return sdbusFlags; 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /src/IConnection.h: -------------------------------------------------------------------------------- 1 | /** 2 | * (C) 2016 - 2021 KISTLER INSTRUMENTE AG, Winterthur, Switzerland 3 | * (C) 2016 - 2024 Stanislav Angelovic 4 | * 5 | * @file IConnection.h 6 | * 7 | * Created on: Nov 9, 2016 8 | * Project: sdbus-c++ 9 | * Description: High-level D-Bus IPC C++ library based on sd-bus 10 | * 11 | * This file is part of sdbus-c++. 12 | * 13 | * sdbus-c++ is free software; you can redistribute it and/or modify it 14 | * under the terms of the GNU Lesser General Public License as published by 15 | * the Free Software Foundation, either version 2.1 of the License, or 16 | * (at your option) any later version. 17 | * 18 | * sdbus-c++ is distributed in the hope that it will be useful, 19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 | * GNU Lesser General Public License for more details. 22 | * 23 | * You should have received a copy of the GNU Lesser General Public License 24 | * along with sdbus-c++. If not, see . 25 | */ 26 | 27 | #ifndef SDBUS_CXX_INTERNAL_ICONNECTION_H_ 28 | #define SDBUS_CXX_INTERNAL_ICONNECTION_H_ 29 | 30 | #include "sdbus-c++/IConnection.h" 31 | 32 | #include "sdbus-c++/TypeTraits.h" 33 | 34 | #include 35 | #include 36 | #include 37 | #include SDBUS_HEADER 38 | #include 39 | 40 | // Forward declarations 41 | namespace sdbus { 42 | class MethodCall; 43 | class MethodReply; 44 | class Signal; 45 | class PlainMessage; 46 | class ObjectPath; 47 | class InterfaceName; 48 | class BusName; 49 | using ServiceName = BusName; 50 | class MemberName; 51 | using MethodName = MemberName; 52 | using SignalName = MemberName; 53 | using PropertyName = MemberName; 54 | class Error; 55 | namespace internal { 56 | class ISdBus; 57 | } 58 | } 59 | 60 | namespace sdbus::internal { 61 | 62 | class IConnection 63 | : public ::sdbus::IConnection 64 | { 65 | public: 66 | ~IConnection() override = default; 67 | 68 | [[nodiscard]] virtual Slot addObjectVTable( const ObjectPath& objectPath 69 | , const InterfaceName& interfaceName 70 | , const sd_bus_vtable* vtable 71 | , void* userData 72 | , return_slot_t ) = 0; 73 | 74 | [[nodiscard]] virtual PlainMessage createPlainMessage() const = 0; 75 | [[nodiscard]] virtual MethodCall createMethodCall( const ServiceName& destination 76 | , const ObjectPath& objectPath 77 | , const InterfaceName& interfaceName 78 | , const MethodName& methodName ) const = 0; 79 | [[nodiscard]] virtual MethodCall createMethodCall( const char* destination 80 | , const char* objectPath 81 | , const char* interfaceName 82 | , const char* methodName ) const = 0; 83 | [[nodiscard]] virtual Signal createSignal( const ObjectPath& objectPath 84 | , const InterfaceName& interfaceName 85 | , const SignalName& signalName ) const = 0; 86 | [[nodiscard]] virtual Signal createSignal( const char* objectPath 87 | , const char* interfaceName 88 | , const char* signalName ) const = 0; 89 | 90 | virtual void emitPropertiesChangedSignal( const ObjectPath& objectPath 91 | , const InterfaceName& interfaceName 92 | , const std::vector& propNames ) = 0; 93 | virtual void emitPropertiesChangedSignal( const char* objectPath 94 | , const char* interfaceName 95 | , const std::vector& propNames ) = 0; 96 | virtual void emitInterfacesAddedSignal(const ObjectPath& objectPath) = 0; 97 | virtual void emitInterfacesAddedSignal( const ObjectPath& objectPath 98 | , const std::vector& interfaces ) = 0; 99 | virtual void emitInterfacesRemovedSignal(const ObjectPath& objectPath) = 0; 100 | virtual void emitInterfacesRemovedSignal( const ObjectPath& objectPath 101 | , const std::vector& interfaces ) = 0; 102 | 103 | [[nodiscard]] virtual Slot registerSignalHandler( const char* sender 104 | , const char* objectPath 105 | , const char* interfaceName 106 | , const char* signalName 107 | , sd_bus_message_handler_t callback 108 | , void* userData 109 | , return_slot_t ) = 0; 110 | 111 | virtual sd_bus_message* incrementMessageRefCount(sd_bus_message* sdbusMsg) = 0; 112 | virtual sd_bus_message* decrementMessageRefCount(sd_bus_message* sdbusMsg) = 0; 113 | 114 | // TODO: Refactor to higher level (Creds class will ownership handling and getters) 115 | virtual int querySenderCredentials(sd_bus_message* sdbusMsg, uint64_t mask, sd_bus_creds **creds) = 0; 116 | virtual sd_bus_creds* incrementCredsRefCount(sd_bus_creds* creds) = 0; 117 | virtual sd_bus_creds* decrementCredsRefCount(sd_bus_creds* creds) = 0; 118 | 119 | virtual sd_bus_message* callMethod(sd_bus_message* sdbusMsg, uint64_t timeout) = 0; 120 | [[nodiscard]] virtual Slot callMethodAsync( sd_bus_message* sdbusMsg 121 | , sd_bus_message_handler_t callback 122 | , void* userData 123 | , uint64_t timeout 124 | , return_slot_t ) = 0; 125 | virtual void sendMessage(sd_bus_message* sdbusMsg) = 0; 126 | 127 | virtual sd_bus_message* createMethodReply(sd_bus_message* sdbusMsg) = 0; 128 | virtual sd_bus_message* createErrorReplyMessage(sd_bus_message* sdbusMsg, const Error& error) = 0; 129 | }; 130 | 131 | [[nodiscard]] std::unique_ptr createPseudoConnection(); 132 | 133 | } 134 | 135 | #endif /* SDBUS_CXX_INTERNAL_ICONNECTION_H_ */ 136 | -------------------------------------------------------------------------------- /src/ISdBus.h: -------------------------------------------------------------------------------- 1 | /** 2 | * (C) 2016 - 2021 KISTLER INSTRUMENTE AG, Winterthur, Switzerland 3 | * (C) 2016 - 2024 Stanislav Angelovic 4 | * 5 | * @file ISdBus.h 6 | * @author Ardazishvili Roman (ardazishvili.roman@yandex.ru) 7 | * 8 | * Created on: Mar 12, 2019 9 | * Project: sdbus-c++ 10 | * Description: High-level D-Bus IPC C++ library based on sd-bus 11 | * 12 | * This file is part of sdbus-c++. 13 | * 14 | * sdbus-c++ is free software; you can redistribute it and/or modify it 15 | * under the terms of the GNU Lesser General Public License as published by 16 | * the Free Software Foundation, either version 2.1 of the License, or 17 | * (at your option) any later version. 18 | * 19 | * sdbus-c++ is distributed in the hope that it will be useful, 20 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 21 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 | * GNU Lesser General Public License for more details. 23 | * 24 | * You should have received a copy of the GNU Lesser General Public License 25 | * along with sdbus-c++. If not, see . 26 | */ 27 | 28 | #ifndef SDBUS_CXX_ISDBUS_H 29 | #define SDBUS_CXX_ISDBUS_H 30 | 31 | #include SDBUS_HEADER 32 | 33 | namespace sdbus::internal { 34 | 35 | class ISdBus 36 | { 37 | public: 38 | struct PollData 39 | { 40 | int fd; 41 | short int events; 42 | uint64_t timeout_usec; 43 | }; 44 | 45 | virtual ~ISdBus() = default; 46 | 47 | virtual sd_bus_message* sd_bus_message_ref(sd_bus_message *m) = 0; 48 | virtual sd_bus_message* sd_bus_message_unref(sd_bus_message *m) = 0; 49 | 50 | virtual int sd_bus_send(sd_bus *bus, sd_bus_message *m, uint64_t *cookie) = 0; 51 | virtual int sd_bus_call(sd_bus *bus, sd_bus_message *m, uint64_t usec, sd_bus_error *ret_error, sd_bus_message **reply) = 0; 52 | virtual int sd_bus_call_async(sd_bus *bus, sd_bus_slot **slot, sd_bus_message *m, sd_bus_message_handler_t callback, void *userdata, uint64_t usec) = 0; 53 | 54 | virtual int sd_bus_message_new(sd_bus *bus, sd_bus_message **m, uint8_t type) = 0; 55 | virtual int sd_bus_message_new_method_call(sd_bus *bus, sd_bus_message **m, const char *destination, const char *path, const char *interface, const char *member) = 0; 56 | virtual int sd_bus_message_new_signal(sd_bus *bus, sd_bus_message **m, const char *path, const char *interface, const char *member) = 0; 57 | virtual int sd_bus_message_new_method_return(sd_bus_message *call, sd_bus_message **m) = 0; 58 | virtual int sd_bus_message_new_method_error(sd_bus_message *call, sd_bus_message **m, const sd_bus_error *e) = 0; 59 | 60 | virtual int sd_bus_set_method_call_timeout(sd_bus *bus, uint64_t usec) = 0; 61 | virtual int sd_bus_get_method_call_timeout(sd_bus *bus, uint64_t *ret) = 0; 62 | 63 | virtual int sd_bus_emit_properties_changed_strv(sd_bus *bus, const char *path, const char *interface, char **names) = 0; 64 | virtual int sd_bus_emit_object_added(sd_bus *bus, const char *path) = 0; 65 | virtual int sd_bus_emit_object_removed(sd_bus *bus, const char *path) = 0; 66 | virtual int sd_bus_emit_interfaces_added_strv(sd_bus *bus, const char *path, char **interfaces) = 0; 67 | virtual int sd_bus_emit_interfaces_removed_strv(sd_bus *bus, const char *path, char **interfaces) = 0; 68 | 69 | virtual int sd_bus_open(sd_bus **ret) = 0; 70 | virtual int sd_bus_open_system(sd_bus **ret) = 0; 71 | virtual int sd_bus_open_user(sd_bus **ret) = 0; 72 | virtual int sd_bus_open_user_with_address(sd_bus **ret, const char* address) = 0; 73 | virtual int sd_bus_open_system_remote(sd_bus **ret, const char* host) = 0; 74 | virtual int sd_bus_open_direct(sd_bus **ret, const char* address) = 0; 75 | virtual int sd_bus_open_direct(sd_bus **ret, int fd) = 0; 76 | virtual int sd_bus_open_server(sd_bus **ret, int fd) = 0; 77 | virtual int sd_bus_request_name(sd_bus *bus, const char *name, uint64_t flags) = 0; 78 | virtual int sd_bus_release_name(sd_bus *bus, const char *name) = 0; 79 | virtual int sd_bus_get_unique_name(sd_bus *bus, const char **name) = 0; 80 | virtual int sd_bus_add_object_vtable(sd_bus *bus, sd_bus_slot **slot, const char *path, const char *interface, const sd_bus_vtable *vtable, void *userdata) = 0; 81 | virtual int sd_bus_add_object_manager(sd_bus *bus, sd_bus_slot **slot, const char *path) = 0; 82 | virtual int sd_bus_add_match(sd_bus *bus, sd_bus_slot **slot, const char *match, sd_bus_message_handler_t callback, void *userdata) = 0; 83 | virtual int sd_bus_add_match_async(sd_bus *bus, sd_bus_slot **slot, const char *match, sd_bus_message_handler_t callback, sd_bus_message_handler_t install_callback, void *userdata) = 0; 84 | virtual int sd_bus_match_signal(sd_bus *bus, sd_bus_slot **ret, const char *sender, const char *path, const char *interface, const char *member, sd_bus_message_handler_t callback, void *userdata) = 0; 85 | virtual sd_bus_slot* sd_bus_slot_unref(sd_bus_slot *slot) = 0; 86 | 87 | virtual int sd_bus_new(sd_bus **ret) = 0; 88 | virtual int sd_bus_start(sd_bus *bus) = 0; 89 | 90 | virtual int sd_bus_process(sd_bus *bus, sd_bus_message **r) = 0; 91 | virtual sd_bus_message* sd_bus_get_current_message(sd_bus *bus) = 0; 92 | virtual int sd_bus_get_poll_data(sd_bus *bus, PollData* data) = 0; 93 | virtual int sd_bus_get_n_queued(sd_bus *bus, uint64_t *read, uint64_t* write) = 0; 94 | virtual int sd_bus_flush(sd_bus *bus) = 0; 95 | virtual sd_bus *sd_bus_flush_close_unref(sd_bus *bus) = 0; 96 | virtual sd_bus *sd_bus_close_unref(sd_bus *bus) = 0; 97 | 98 | virtual int sd_bus_message_set_destination(sd_bus_message *m, const char *destination) = 0; 99 | 100 | virtual int sd_bus_query_sender_creds(sd_bus_message *m, uint64_t mask, sd_bus_creds **c) = 0; 101 | virtual sd_bus_creds* sd_bus_creds_ref(sd_bus_creds *c) = 0; 102 | virtual sd_bus_creds* sd_bus_creds_unref(sd_bus_creds *c) = 0; 103 | 104 | virtual int sd_bus_creds_get_pid(sd_bus_creds *c, pid_t *pid) = 0; 105 | virtual int sd_bus_creds_get_uid(sd_bus_creds *c, uid_t *uid) = 0; 106 | virtual int sd_bus_creds_get_euid(sd_bus_creds *c, uid_t *uid) = 0; 107 | virtual int sd_bus_creds_get_gid(sd_bus_creds *c, gid_t *gid) = 0; 108 | virtual int sd_bus_creds_get_egid(sd_bus_creds *c, gid_t *egid) = 0; 109 | virtual int sd_bus_creds_get_supplementary_gids(sd_bus_creds *c, const gid_t **gids) = 0; 110 | virtual int sd_bus_creds_get_selinux_context(sd_bus_creds *c, const char **label) = 0; 111 | }; 112 | 113 | } 114 | 115 | #endif //SDBUS_CXX_ISDBUS_H 116 | -------------------------------------------------------------------------------- /src/MessageUtils.h: -------------------------------------------------------------------------------- 1 | /** 2 | * (C) 2016 - 2021 KISTLER INSTRUMENTE AG, Winterthur, Switzerland 3 | * (C) 2016 - 2024 Stanislav Angelovic 4 | * 5 | * @file MessageUtils.h 6 | * 7 | * Created on: Dec 5, 2016 8 | * Project: sdbus-c++ 9 | * Description: High-level D-Bus IPC C++ library based on sd-bus 10 | * 11 | * This file is part of sdbus-c++. 12 | * 13 | * sdbus-c++ is free software; you can redistribute it and/or modify it 14 | * under the terms of the GNU Lesser General Public License as published by 15 | * the Free Software Foundation, either version 2.1 of the License, or 16 | * (at your option) any later version. 17 | * 18 | * sdbus-c++ is distributed in the hope that it will be useful, 19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 | * GNU Lesser General Public License for more details. 22 | * 23 | * You should have received a copy of the GNU Lesser General Public License 24 | * along with sdbus-c++. If not, see . 25 | */ 26 | 27 | #ifndef SDBUS_CXX_INTERNAL_MESSAGEUTILS_H_ 28 | #define SDBUS_CXX_INTERNAL_MESSAGEUTILS_H_ 29 | 30 | #include 31 | 32 | namespace sdbus 33 | { 34 | class Message::Factory 35 | { 36 | public: 37 | template 38 | static _Msg create() 39 | { 40 | return _Msg{}; 41 | } 42 | 43 | template 44 | static _Msg create(void *msg) 45 | { 46 | return _Msg{msg}; 47 | } 48 | 49 | template 50 | static _Msg create(void *msg, internal::IConnection* connection) 51 | { 52 | return _Msg{msg, connection}; 53 | } 54 | 55 | template 56 | static _Msg create(void *msg, internal::IConnection* connection, adopt_message_t) 57 | { 58 | return _Msg{msg, connection, adopt_message}; 59 | } 60 | }; 61 | } 62 | 63 | #endif /* SDBUS_CXX_INTERNAL_MESSAGEUTILS_H_ */ 64 | -------------------------------------------------------------------------------- /src/Proxy.h: -------------------------------------------------------------------------------- 1 | /** 2 | * (C) 2016 - 2021 KISTLER INSTRUMENTE AG, Winterthur, Switzerland 3 | * (C) 2016 - 2024 Stanislav Angelovic 4 | * 5 | * @file Proxy.h 6 | * 7 | * Created on: Nov 8, 2016 8 | * Project: sdbus-c++ 9 | * Description: High-level D-Bus IPC C++ library based on sd-bus 10 | * 11 | * This file is part of sdbus-c++. 12 | * 13 | * sdbus-c++ is free software; you can redistribute it and/or modify it 14 | * under the terms of the GNU Lesser General Public License as published by 15 | * the Free Software Foundation, either version 2.1 of the License, or 16 | * (at your option) any later version. 17 | * 18 | * sdbus-c++ is distributed in the hope that it will be useful, 19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 | * GNU Lesser General Public License for more details. 22 | * 23 | * You should have received a copy of the GNU Lesser General Public License 24 | * along with sdbus-c++. If not, see . 25 | */ 26 | 27 | #ifndef SDBUS_CXX_INTERNAL_PROXY_H_ 28 | #define SDBUS_CXX_INTERNAL_PROXY_H_ 29 | 30 | #include "sdbus-c++/IProxy.h" 31 | 32 | #include "IConnection.h" 33 | #include "sdbus-c++/Types.h" 34 | 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include SDBUS_HEADER 40 | #include 41 | 42 | namespace sdbus::internal { 43 | 44 | class Proxy 45 | : public IProxy 46 | { 47 | public: 48 | Proxy( sdbus::internal::IConnection& connection 49 | , ServiceName destination 50 | , ObjectPath objectPath ); 51 | Proxy( std::unique_ptr&& connection 52 | , ServiceName destination 53 | , ObjectPath objectPath ); 54 | Proxy( std::unique_ptr&& connection 55 | , ServiceName destination 56 | , ObjectPath objectPath 57 | , dont_run_event_loop_thread_t ); 58 | 59 | MethodCall createMethodCall(const InterfaceName& interfaceName, const MethodName& methodName) const override; 60 | MethodCall createMethodCall(const char* interfaceName, const char* methodName) const override; 61 | MethodReply callMethod(const MethodCall& message) override; 62 | MethodReply callMethod(const MethodCall& message, uint64_t timeout) override; 63 | PendingAsyncCall callMethodAsync(const MethodCall& message, async_reply_handler asyncReplyCallback) override; 64 | Slot callMethodAsync( const MethodCall& message 65 | , async_reply_handler asyncReplyCallback 66 | , return_slot_t ) override; 67 | PendingAsyncCall callMethodAsync( const MethodCall& message 68 | , async_reply_handler asyncReplyCallback 69 | , uint64_t timeout ) override; 70 | Slot callMethodAsync( const MethodCall& message 71 | , async_reply_handler asyncReplyCallback 72 | , uint64_t timeout 73 | , return_slot_t ) override; 74 | std::future callMethodAsync(const MethodCall& message, with_future_t) override; 75 | std::future callMethodAsync(const MethodCall& message, uint64_t timeout, with_future_t) override; 76 | 77 | void registerSignalHandler( const InterfaceName& interfaceName 78 | , const SignalName& signalName 79 | , signal_handler signalHandler ) override; 80 | void registerSignalHandler( const char* interfaceName 81 | , const char* signalName 82 | , signal_handler signalHandler ) override; 83 | Slot registerSignalHandler( const InterfaceName& interfaceName 84 | , const SignalName& signalName 85 | , signal_handler signalHandler 86 | , return_slot_t ) override; 87 | Slot registerSignalHandler( const char* interfaceName 88 | , const char* signalName 89 | , signal_handler signalHandler 90 | , return_slot_t ) override; 91 | void unregister() override; 92 | 93 | [[nodiscard]] sdbus::IConnection& getConnection() const override; 94 | [[nodiscard]] const ObjectPath& getObjectPath() const override; 95 | [[nodiscard]] Message getCurrentlyProcessedMessage() const override; 96 | 97 | private: 98 | static int sdbus_signal_handler(sd_bus_message *sdbusMessage, void *userData, sd_bus_error *retError); 99 | static int sdbus_async_reply_handler(sd_bus_message *sdbusMessage, void *userData, sd_bus_error *retError); 100 | 101 | private: 102 | friend PendingAsyncCall; 103 | 104 | std::unique_ptr< sdbus::internal::IConnection 105 | , std::function 106 | > connection_; 107 | ServiceName destination_; 108 | ObjectPath objectPath_; 109 | 110 | std::vector floatingSignalSlots_; 111 | 112 | struct SignalInfo 113 | { 114 | signal_handler callback; 115 | Proxy& proxy; 116 | Slot slot; 117 | }; 118 | 119 | struct AsyncCallInfo 120 | { 121 | async_reply_handler callback; 122 | Proxy& proxy; 123 | Slot slot{}; 124 | bool finished{false}; 125 | bool floating; 126 | }; 127 | 128 | // Container keeping track of pending async calls 129 | class FloatingAsyncCallSlots 130 | { 131 | public: 132 | ~FloatingAsyncCallSlots(); 133 | void push_back(std::shared_ptr asyncCallInfo); 134 | void erase(AsyncCallInfo* info); 135 | void clear(); 136 | 137 | private: 138 | std::mutex mutex_; 139 | std::deque> slots_; 140 | }; 141 | 142 | FloatingAsyncCallSlots floatingAsyncCallSlots_; 143 | }; 144 | 145 | } 146 | 147 | #endif /* SDBUS_CXX_INTERNAL_PROXY_H_ */ 148 | -------------------------------------------------------------------------------- /src/ScopeGuard.h: -------------------------------------------------------------------------------- 1 | /** 2 | * (C) 2016 - 2021 KISTLER INSTRUMENTE AG, Winterthur, Switzerland 3 | * (C) 2016 - 2024 Stanislav Angelovic 4 | * 5 | * @file ScopeGuard.h 6 | * 7 | * Created on: Apr 29, 2015 8 | * Project: sdbus-c++ 9 | * Description: High-level D-Bus IPC C++ library based on sd-bus 10 | * 11 | * This file is part of sdbus-c++. 12 | * 13 | * sdbus-c++ is free software; you can redistribute it and/or modify it 14 | * under the terms of the GNU Lesser General Public License as published by 15 | * the Free Software Foundation, either version 2.1 of the License, or 16 | * (at your option) any later version. 17 | * 18 | * sdbus-c++ is distributed in the hope that it will be useful, 19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 | * GNU Lesser General Public License for more details. 22 | * 23 | * You should have received a copy of the GNU Lesser General Public License 24 | * along with sdbus-c++. If not, see . 25 | */ 26 | 27 | #ifndef SDBUS_CPP_INTERNAL_SCOPEGUARD_H_ 28 | #define SDBUS_CPP_INTERNAL_SCOPEGUARD_H_ 29 | 30 | #include 31 | #include 32 | 33 | // Straightforward, modern, easy-to-use RAII utility to perform work on scope exit in an exception-safe manner. 34 | // 35 | // The utility helps providing basic exception safety guarantee by ensuring that the resources are always 36 | // released in face of an exception and released or kept when exiting the scope normally. 37 | // 38 | // Use SCOPE_EXIT if you'd like to perform an (mostly clean-up) operation when the scope ends, either due 39 | // to an exception or because it just ends normally. 40 | // Use SCOPE_EXIT_NAMED if you'd like to conditionally deactivate given scope-exit operation. This is useful 41 | // if, for example, we want the operation to be executed only in face of an exception. 42 | // 43 | // Example usage (maybe a bit contrived): 44 | // SqlDb* g_pDb = nullptr; 45 | // void fnc() { 46 | // auto* pDb = open_database(...); // Resource to be released when scope exits due to whatever reason 47 | // SCOPE_EXIT{ close_database(pDb); }; // Executes body when exiting the scope due to whatever reason 48 | // g_pDb = open_database(...); // Resource to be released only in face of an exception 49 | // SCOPE_EXIT_NAMED(releaseGlobalDbOnException) // Executes body when exiting the scope in face of an exception 50 | // { 51 | // close_database(g_pDb); 52 | // g_pDb = nullptr; 53 | // }; 54 | // //... do operations (that may or may not possibly throw) on the database here 55 | // releaseGlobalDbOnException.dismiss(); // Don't release global DB on normal scope exit 56 | // return; // exiting scope normally 57 | // } 58 | 59 | #define SCOPE_EXIT \ 60 | auto ANONYMOUS_VARIABLE(SCOPE_EXIT_STATE) \ 61 | = ::sdbus::internal::ScopeGuardOnExitTag{} + [&]() \ 62 | /**/ 63 | #define SCOPE_EXIT_NAMED(NAME) \ 64 | auto NAME \ 65 | = ::sdbus::internal::ScopeGuardOnExitTag{} + [&]() \ 66 | /**/ 67 | #define SCOPE_EXIT_SUCCESS \ 68 | auto ANONYMOUS_VARIABLE(SCOPE_EXIT_STATE) \ 69 | = ::sdbus::internal::ScopeGuardOnExitSuccessTag{} + [&]() \ 70 | /**/ 71 | #define SCOPE_EXIT_SUCCESS_NAMED(NAME) \ 72 | auto NAME \ 73 | = ::sdbus::internal::ScopeGuardOnExitSuccessTag{} + [&]() \ 74 | /**/ 75 | #define SCOPE_EXIT_FAILURE \ 76 | auto ANONYMOUS_VARIABLE(SCOPE_EXIT_STATE) \ 77 | = ::sdbus::internal::ScopeGuardOnExitFailureTag{} + [&]() \ 78 | /**/ 79 | #define SCOPE_EXIT_FAILURE_NAMED(NAME) \ 80 | auto NAME \ 81 | = ::sdbus::internal::ScopeGuardOnExitFailureTag{} + [&]() \ 82 | /**/ 83 | 84 | namespace sdbus::internal { 85 | 86 | struct ScopeGuardOnExitTag 87 | { 88 | static bool holds(int /*originalExceptions*/) 89 | { 90 | return true; // Always holds 91 | } 92 | }; 93 | struct ScopeGuardOnExitSuccessTag 94 | { 95 | static bool holds(int originalExceptions) 96 | { 97 | return originalExceptions == std::uncaught_exceptions(); // Only holds when no exception occurred within the scope 98 | } 99 | }; 100 | struct ScopeGuardOnExitFailureTag 101 | { 102 | static bool holds(int originalExceptions) 103 | { 104 | return originalExceptions != std::uncaught_exceptions(); // Only holds when an exception occurred within the scope 105 | } 106 | }; 107 | 108 | template 109 | class ScopeGuard 110 | { 111 | public: 112 | ScopeGuard(_Fun f) : fnc_(std::move(f)) 113 | { 114 | } 115 | 116 | ScopeGuard() = delete; 117 | ScopeGuard(const ScopeGuard&) = delete; 118 | ScopeGuard& operator=(const ScopeGuard&) = delete; 119 | ScopeGuard(ScopeGuard&& rhs) : fnc_(std::move(rhs.fnc_)), active_(rhs.active_), exceptions_(rhs.exceptions_) 120 | { 121 | rhs.dismiss(); 122 | } 123 | 124 | void dismiss() 125 | { 126 | active_ = false; 127 | } 128 | 129 | ~ScopeGuard() 130 | { 131 | if (active_ && _Tag::holds(exceptions_)) 132 | fnc_(); 133 | } 134 | 135 | private: 136 | _Fun fnc_; 137 | int exceptions_{std::uncaught_exceptions()}; 138 | bool active_{true}; 139 | }; 140 | 141 | template 142 | ScopeGuard<_Fun, ScopeGuardOnExitTag> operator+(ScopeGuardOnExitTag, _Fun&& fnc) 143 | { 144 | return ScopeGuard<_Fun, ScopeGuardOnExitTag>(std::forward<_Fun>(fnc)); 145 | } 146 | 147 | template 148 | ScopeGuard<_Fun, ScopeGuardOnExitSuccessTag> operator+(ScopeGuardOnExitSuccessTag, _Fun&& fnc) 149 | { 150 | return ScopeGuard<_Fun, ScopeGuardOnExitSuccessTag>(std::forward<_Fun>(fnc)); 151 | } 152 | 153 | template 154 | ScopeGuard<_Fun, ScopeGuardOnExitFailureTag> operator+(ScopeGuardOnExitFailureTag, _Fun&& fnc) 155 | { 156 | return ScopeGuard<_Fun, ScopeGuardOnExitFailureTag>(std::forward<_Fun>(fnc)); 157 | } 158 | 159 | } 160 | 161 | #define CONCATENATE_IMPL(s1, s2) s1##s2 162 | #define CONCATENATE(s1, s2) CONCATENATE_IMPL(s1, s2) 163 | 164 | #ifdef __COUNTER__ 165 | #define ANONYMOUS_VARIABLE(str) CONCATENATE(str, __COUNTER__) 166 | #else 167 | #define ANONYMOUS_VARIABLE(str) CONCATENATE(str, __LINE__) 168 | #endif 169 | 170 | #endif /* SDBUS_CPP_INTERNAL_SCOPEGUARD_H_ */ 171 | -------------------------------------------------------------------------------- /src/SdBus.h: -------------------------------------------------------------------------------- 1 | /** 2 | * (C) 2016 - 2021 KISTLER INSTRUMENTE AG, Winterthur, Switzerland 3 | * (C) 2016 - 2024 Stanislav Angelovic 4 | * 5 | * @file SdBus.h 6 | * @author Ardazishvili Roman (ardazishvili.roman@yandex.ru) 7 | * 8 | * Created on: Mar 3, 2019 9 | * Project: sdbus-c++ 10 | * Description: High-level D-Bus IPC C++ library based on sd-bus 11 | * 12 | * This file is part of sdbus-c++. 13 | * 14 | * sdbus-c++ is free software; you can redistribute it and/or modify it 15 | * under the terms of the GNU Lesser General Public License as published by 16 | * the Free Software Foundation, either version 2.1 of the License, or 17 | * (at your option) any later version. 18 | * 19 | * sdbus-c++ is distributed in the hope that it will be useful, 20 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 21 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 | * GNU Lesser General Public License for more details. 23 | * 24 | * You should have received a copy of the GNU Lesser General Public License 25 | * along with sdbus-c++. If not, see . 26 | */ 27 | 28 | #ifndef SDBUS_CXX_SDBUS_H 29 | #define SDBUS_CXX_SDBUS_H 30 | 31 | #include "ISdBus.h" 32 | #include 33 | 34 | namespace sdbus::internal { 35 | 36 | class SdBus final : public ISdBus 37 | { 38 | public: 39 | virtual sd_bus_message* sd_bus_message_ref(sd_bus_message *m) override; 40 | virtual sd_bus_message* sd_bus_message_unref(sd_bus_message *m) override; 41 | 42 | virtual int sd_bus_send(sd_bus *bus, sd_bus_message *m, uint64_t *cookie) override; 43 | virtual int sd_bus_call(sd_bus *bus, sd_bus_message *m, uint64_t usec, sd_bus_error *ret_error, sd_bus_message **reply) override; 44 | virtual int sd_bus_call_async(sd_bus *bus, sd_bus_slot **slot, sd_bus_message *m, sd_bus_message_handler_t callback, void *userdata, uint64_t usec) override; 45 | 46 | virtual int sd_bus_message_new(sd_bus *bus, sd_bus_message **m, uint8_t type) override; 47 | virtual int sd_bus_message_new_method_call(sd_bus *bus, sd_bus_message **m, const char *destination, const char *path, const char *interface, const char *member) override; 48 | virtual int sd_bus_message_new_signal(sd_bus *bus, sd_bus_message **m, const char *path, const char *interface, const char *member) override; 49 | virtual int sd_bus_message_new_method_return(sd_bus_message *call, sd_bus_message **m) override; 50 | virtual int sd_bus_message_new_method_error(sd_bus_message *call, sd_bus_message **m, const sd_bus_error *e) override; 51 | 52 | virtual int sd_bus_set_method_call_timeout(sd_bus *bus, uint64_t usec) override; 53 | virtual int sd_bus_get_method_call_timeout(sd_bus *bus, uint64_t *ret) override; 54 | 55 | virtual int sd_bus_emit_properties_changed_strv(sd_bus *bus, const char *path, const char *interface, char **names) override; 56 | virtual int sd_bus_emit_object_added(sd_bus *bus, const char *path) override; 57 | virtual int sd_bus_emit_object_removed(sd_bus *bus, const char *path) override; 58 | virtual int sd_bus_emit_interfaces_added_strv(sd_bus *bus, const char *path, char **interfaces) override; 59 | virtual int sd_bus_emit_interfaces_removed_strv(sd_bus *bus, const char *path, char **interfaces) override; 60 | 61 | virtual int sd_bus_open(sd_bus **ret) override; 62 | virtual int sd_bus_open_system(sd_bus **ret) override; 63 | virtual int sd_bus_open_user(sd_bus **ret) override; 64 | virtual int sd_bus_open_user_with_address(sd_bus **ret, const char* address) override; 65 | virtual int sd_bus_open_system_remote(sd_bus **ret, const char* hsot) override; 66 | virtual int sd_bus_open_direct(sd_bus **ret, const char* address) override; 67 | virtual int sd_bus_open_direct(sd_bus **ret, int fd) override; 68 | virtual int sd_bus_open_server(sd_bus **ret, int fd) override; 69 | virtual int sd_bus_request_name(sd_bus *bus, const char *name, uint64_t flags) override; 70 | virtual int sd_bus_release_name(sd_bus *bus, const char *name) override; 71 | virtual int sd_bus_get_unique_name(sd_bus *bus, const char **name) override; 72 | virtual int sd_bus_add_object_vtable(sd_bus *bus, sd_bus_slot **slot, const char *path, const char *interface, const sd_bus_vtable *vtable, void *userdata) override; 73 | virtual int sd_bus_add_object_manager(sd_bus *bus, sd_bus_slot **slot, const char *path) override; 74 | virtual int sd_bus_add_match(sd_bus *bus, sd_bus_slot **slot, const char *match, sd_bus_message_handler_t callback, void *userdata) override; 75 | virtual int sd_bus_add_match_async(sd_bus *bus, sd_bus_slot **slot, const char *match, sd_bus_message_handler_t callback, sd_bus_message_handler_t install_callback, void *userdata) override; 76 | virtual int sd_bus_match_signal(sd_bus *bus, sd_bus_slot **ret, const char *sender, const char *path, const char *interface, const char *member, sd_bus_message_handler_t callback, void *userdata) override; 77 | virtual sd_bus_slot* sd_bus_slot_unref(sd_bus_slot *slot) override; 78 | 79 | virtual int sd_bus_new(sd_bus **ret) override; 80 | virtual int sd_bus_start(sd_bus *bus) override; 81 | 82 | virtual int sd_bus_process(sd_bus *bus, sd_bus_message **r) override; 83 | virtual sd_bus_message* sd_bus_get_current_message(sd_bus *bus) override; 84 | virtual int sd_bus_get_poll_data(sd_bus *bus, PollData* data) override; 85 | virtual int sd_bus_get_n_queued(sd_bus *bus, uint64_t *read, uint64_t* write) override; 86 | virtual int sd_bus_flush(sd_bus *bus) override; 87 | virtual sd_bus *sd_bus_flush_close_unref(sd_bus *bus) override; 88 | virtual sd_bus *sd_bus_close_unref(sd_bus *bus) override; 89 | 90 | virtual int sd_bus_message_set_destination(sd_bus_message *m, const char *destination) override; 91 | 92 | virtual int sd_bus_query_sender_creds(sd_bus_message *m, uint64_t mask, sd_bus_creds **c) override; 93 | virtual sd_bus_creds* sd_bus_creds_ref(sd_bus_creds *c) override; 94 | virtual sd_bus_creds* sd_bus_creds_unref(sd_bus_creds *c) override; 95 | 96 | virtual int sd_bus_creds_get_pid(sd_bus_creds *c, pid_t *pid) override; 97 | virtual int sd_bus_creds_get_uid(sd_bus_creds *c, uid_t *uid) override; 98 | virtual int sd_bus_creds_get_euid(sd_bus_creds *c, uid_t *euid) override; 99 | virtual int sd_bus_creds_get_gid(sd_bus_creds *c, gid_t *gid) override; 100 | virtual int sd_bus_creds_get_egid(sd_bus_creds *c, gid_t *egid) override; 101 | virtual int sd_bus_creds_get_supplementary_gids(sd_bus_creds *c, const gid_t **gids) override; 102 | virtual int sd_bus_creds_get_selinux_context(sd_bus_creds *c, const char **label) override; 103 | 104 | private: 105 | std::recursive_mutex sdbusMutex_; 106 | }; 107 | 108 | } 109 | 110 | #endif //SDBUS_C_SDBUS_H 111 | -------------------------------------------------------------------------------- /src/Types.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * (C) 2016 - 2021 KISTLER INSTRUMENTE AG, Winterthur, Switzerland 3 | * (C) 2016 - 2024 Stanislav Angelovic 4 | * 5 | * @file Types.cpp 6 | * 7 | * Created on: Nov 30, 2016 8 | * Project: sdbus-c++ 9 | * Description: High-level D-Bus IPC C++ library based on sd-bus 10 | * 11 | * This file is part of sdbus-c++. 12 | * 13 | * sdbus-c++ is free software; you can redistribute it and/or modify it 14 | * under the terms of the GNU Lesser General Public License as published by 15 | * the Free Software Foundation, either version 2.1 of the License, or 16 | * (at your option) any later version. 17 | * 18 | * sdbus-c++ is distributed in the hope that it will be useful, 19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 | * GNU Lesser General Public License for more details. 22 | * 23 | * You should have received a copy of the GNU Lesser General Public License 24 | * along with sdbus-c++. If not, see . 25 | */ 26 | 27 | #include "sdbus-c++/Types.h" 28 | 29 | #include "sdbus-c++/Error.h" 30 | 31 | #include "MessageUtils.h" 32 | 33 | #include 34 | #include 35 | #include SDBUS_HEADER 36 | #include 37 | 38 | namespace sdbus { 39 | 40 | Variant::Variant() 41 | : msg_(createPlainMessage()) 42 | { 43 | } 44 | 45 | void Variant::serializeTo(Message& msg) const 46 | { 47 | SDBUS_THROW_ERROR_IF(isEmpty(), "Empty variant is not allowed", EINVAL); 48 | msg_.rewind(true); 49 | msg_.copyTo(msg, true); 50 | } 51 | 52 | void Variant::deserializeFrom(Message& msg) 53 | { 54 | msg.copyTo(msg_, false); 55 | msg_.seal(); 56 | } 57 | 58 | const char* Variant::peekValueType() const 59 | { 60 | msg_.rewind(false); 61 | auto [type, contents] = msg_.peekType(); 62 | return contents; 63 | } 64 | 65 | bool Variant::isEmpty() const 66 | { 67 | return msg_.isEmpty(); 68 | } 69 | 70 | void UnixFd::close() // NOLINT(readability-make-member-function-const) 71 | { 72 | if (fd_ >= 0) 73 | { 74 | ::close(fd_); 75 | } 76 | } 77 | 78 | int UnixFd::checkedDup(int fd) 79 | { 80 | if (fd < 0) 81 | { 82 | return fd; 83 | } 84 | 85 | int ret = ::dup(fd); // NOLINT(android-cloexec-dup) // TODO: verify 86 | if (ret < 0) 87 | { 88 | throw std::system_error(errno, std::generic_category(), "dup failed"); 89 | } 90 | return ret; 91 | } 92 | 93 | } // namespace sdbus 94 | -------------------------------------------------------------------------------- /src/Utils.h: -------------------------------------------------------------------------------- 1 | /** 2 | * (C) 2016 - 2021 KISTLER INSTRUMENTE AG, Winterthur, Switzerland 3 | * (C) 2016 - 2024 Stanislav Angelovic 4 | * 5 | * @file Utils.h 6 | * 7 | * Created on: Feb 9, 2022 8 | * Project: sdbus-c++ 9 | * Description: High-level D-Bus IPC C++ library based on sd-bus 10 | * 11 | * This file is part of sdbus-c++. 12 | * 13 | * sdbus-c++ is free software; you can redistribute it and/or modify it 14 | * under the terms of the GNU Lesser General Public License as published by 15 | * the Free Software Foundation, either version 2.1 of the License, or 16 | * (at your option) any later version. 17 | * 18 | * sdbus-c++ is distributed in the hope that it will be useful, 19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 | * GNU Lesser General Public License for more details. 22 | * 23 | * You should have received a copy of the GNU Lesser General Public License 24 | * along with sdbus-c++. If not, see . 25 | */ 26 | 27 | #ifndef SDBUS_CXX_INTERNAL_UTILS_H_ 28 | #define SDBUS_CXX_INTERNAL_UTILS_H_ 29 | 30 | #include 31 | #include SDBUS_HEADER 32 | 33 | #if LIBSYSTEMD_VERSION>=246 34 | #define SDBUS_CHECK_OBJECT_PATH(_PATH) \ 35 | SDBUS_THROW_ERROR_IF(!sd_bus_object_path_is_valid(_PATH), std::string("Invalid object path '") + _PATH + "' provided", EINVAL) \ 36 | /**/ 37 | #define SDBUS_CHECK_INTERFACE_NAME(_NAME) \ 38 | SDBUS_THROW_ERROR_IF(!sd_bus_interface_name_is_valid(_NAME), std::string("Invalid interface name '") + _NAME + "' provided", EINVAL) \ 39 | /**/ 40 | #define SDBUS_CHECK_SERVICE_NAME(_NAME) \ 41 | SDBUS_THROW_ERROR_IF(*_NAME && !sd_bus_service_name_is_valid(_NAME), std::string("Invalid service name '") + _NAME + "' provided", EINVAL) \ 42 | /**/ 43 | #define SDBUS_CHECK_MEMBER_NAME(_NAME) \ 44 | SDBUS_THROW_ERROR_IF(!sd_bus_member_name_is_valid(_NAME), std::string("Invalid member name '") + _NAME + "' provided", EINVAL) \ 45 | /**/ 46 | #else 47 | #define SDBUS_CHECK_OBJECT_PATH(_PATH) 48 | #define SDBUS_CHECK_INTERFACE_NAME(_NAME) 49 | #define SDBUS_CHECK_SERVICE_NAME(_NAME) 50 | #define SDBUS_CHECK_MEMBER_NAME(_NAME) 51 | #endif 52 | 53 | namespace sdbus::internal { 54 | 55 | template 56 | bool invokeHandlerAndCatchErrors(_Callable callable, sd_bus_error *retError) 57 | { 58 | try 59 | { 60 | callable(); 61 | } 62 | catch (const Error& e) 63 | { 64 | sd_bus_error_set(retError, e.getName().c_str(), e.getMessage().c_str()); 65 | return false; 66 | } 67 | catch (const std::exception& e) 68 | { 69 | sd_bus_error_set(retError, SDBUSCPP_ERROR_NAME.c_str(), e.what()); 70 | return false; 71 | } 72 | catch (...) 73 | { 74 | sd_bus_error_set(retError, SDBUSCPP_ERROR_NAME.c_str(), "Unknown error occurred"); 75 | return false; 76 | } 77 | 78 | return true; 79 | } 80 | 81 | // Returns time since epoch based of POSIX CLOCK_MONOTONIC, 82 | // so we use the very same clock as underlying sd-bus library. 83 | [[nodiscard]] inline auto now() 84 | { 85 | struct timespec ts{}; 86 | auto r = clock_gettime(CLOCK_MONOTONIC, &ts); 87 | SDBUS_THROW_ERROR_IF(r < 0, "clock_gettime failed: ", -errno); 88 | 89 | return std::chrono::nanoseconds(ts.tv_nsec) + std::chrono::seconds(ts.tv_sec); 90 | } 91 | 92 | // Implementation of the overload pattern for variant visitation 93 | template struct overload : Ts... { using Ts::operator()...; }; 94 | template overload(Ts...) -> overload; 95 | 96 | } 97 | 98 | #endif /* SDBUS_CXX_INTERNAL_UTILS_H_ */ 99 | -------------------------------------------------------------------------------- /src/VTableUtils.c: -------------------------------------------------------------------------------- 1 | /** 2 | * (C) 2016 - 2021 KISTLER INSTRUMENTE AG, Winterthur, Switzerland 3 | * (C) 2016 - 2024 Stanislav Angelovic 4 | * 5 | * @file VTableUtils.c 6 | * 7 | * Created on: Nov 8, 2016 8 | * Project: sdbus-c++ 9 | * Description: High-level D-Bus IPC C++ library based on sd-bus 10 | * 11 | * This file is part of sdbus-c++. 12 | * 13 | * sdbus-c++ is free software; you can redistribute it and/or modify it 14 | * under the terms of the GNU Lesser General Public License as published by 15 | * the Free Software Foundation, either version 2.1 of the License, or 16 | * (at your option) any later version. 17 | * 18 | * sdbus-c++ is distributed in the hope that it will be useful, 19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 | * GNU Lesser General Public License for more details. 22 | * 23 | * You should have received a copy of the GNU Lesser General Public License 24 | * along with sdbus-c++. If not, see . 25 | */ 26 | 27 | #include "VTableUtils.h" 28 | #include SDBUS_HEADER 29 | 30 | sd_bus_vtable createSdBusVTableStartItem(uint64_t flags) 31 | { 32 | struct sd_bus_vtable vtableStart = SD_BUS_VTABLE_START(flags); 33 | return vtableStart; 34 | } 35 | 36 | sd_bus_vtable createSdBusVTableMethodItem( const char *member 37 | , const char *signature 38 | , const char *result 39 | , const char *paramNames 40 | , sd_bus_message_handler_t handler 41 | , uint64_t flags ) 42 | { 43 | #if LIBSYSTEMD_VERSION>=242 44 | // We have to expand macro SD_BUS_METHOD_WITH_NAMES manually here, because the macro expects literal char strings 45 | /*struct sd_bus_vtable vtableItem = SD_BUS_METHOD_WITH_NAMES(member, signature, innames, result, outnames, handler, flags);*/ 46 | struct sd_bus_vtable vtableItem = 47 | { 48 | .type = _SD_BUS_VTABLE_METHOD, 49 | .flags = flags, 50 | .x = { 51 | .method = { 52 | .member = member, 53 | .signature = signature, 54 | .result = result, 55 | .handler = handler, 56 | .offset = 0, 57 | .names = paramNames, 58 | }, 59 | }, 60 | }; 61 | #else 62 | (void)paramNames; 63 | struct sd_bus_vtable vtableItem = SD_BUS_METHOD(member, signature, result, handler, flags); 64 | #endif 65 | return vtableItem; 66 | } 67 | 68 | sd_bus_vtable createSdBusVTableSignalItem( const char *member 69 | , const char *signature 70 | , const char *outnames 71 | , uint64_t flags ) 72 | { 73 | #if LIBSYSTEMD_VERSION>=242 74 | struct sd_bus_vtable vtableItem = SD_BUS_SIGNAL_WITH_NAMES(member, signature, outnames, flags); 75 | #else 76 | (void)outnames; 77 | struct sd_bus_vtable vtableItem = SD_BUS_SIGNAL(member, signature, flags); 78 | #endif 79 | return vtableItem; 80 | } 81 | 82 | sd_bus_vtable createSdBusVTableReadOnlyPropertyItem( const char *member 83 | , const char *signature 84 | , sd_bus_property_get_t getter 85 | , uint64_t flags ) 86 | { 87 | struct sd_bus_vtable vtableItem = SD_BUS_PROPERTY(member, signature, getter, 0, flags); 88 | return vtableItem; 89 | } 90 | 91 | sd_bus_vtable createSdBusVTableWritablePropertyItem( const char *member 92 | , const char *signature 93 | , sd_bus_property_get_t getter 94 | , sd_bus_property_set_t setter 95 | , uint64_t flags ) 96 | { 97 | struct sd_bus_vtable vtableItem = SD_BUS_WRITABLE_PROPERTY(member, signature, getter, setter, 0, flags); 98 | return vtableItem; 99 | } 100 | 101 | sd_bus_vtable createSdBusVTableEndItem() 102 | { 103 | struct sd_bus_vtable vtableEnd = SD_BUS_VTABLE_END; 104 | return vtableEnd; 105 | } 106 | -------------------------------------------------------------------------------- /src/VTableUtils.h: -------------------------------------------------------------------------------- 1 | /** 2 | * (C) 2016 - 2021 KISTLER INSTRUMENTE AG, Winterthur, Switzerland 3 | * (C) 2016 - 2024 Stanislav Angelovic 4 | * 5 | * @file VTableUtils.h 6 | * 7 | * Created on: Nov 8, 2016 8 | * Project: sdbus-c++ 9 | * Description: High-level D-Bus IPC C++ library based on sd-bus 10 | * 11 | * This file is part of sdbus-c++. 12 | * 13 | * sdbus-c++ is free software; you can redistribute it and/or modify it 14 | * under the terms of the GNU Lesser General Public License as published by 15 | * the Free Software Foundation, either version 2.1 of the License, or 16 | * (at your option) any later version. 17 | * 18 | * sdbus-c++ is distributed in the hope that it will be useful, 19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 | * GNU Lesser General Public License for more details. 22 | * 23 | * You should have received a copy of the GNU Lesser General Public License 24 | * along with sdbus-c++. If not, see . 25 | */ 26 | 27 | #ifndef SDBUS_CXX_INTERNAL_VTABLEUTILS_H_ 28 | #define SDBUS_CXX_INTERNAL_VTABLEUTILS_H_ 29 | 30 | #include 31 | #include SDBUS_HEADER 32 | 33 | #ifdef __cplusplus 34 | extern "C" { 35 | #endif 36 | 37 | sd_bus_vtable createSdBusVTableStartItem(uint64_t flags); 38 | sd_bus_vtable createSdBusVTableMethodItem( const char *member 39 | , const char *signature 40 | , const char *result 41 | , const char *paramNames 42 | , sd_bus_message_handler_t handler 43 | , uint64_t flags ); 44 | sd_bus_vtable createSdBusVTableSignalItem( const char *member 45 | , const char *signature 46 | , const char *outnames 47 | , uint64_t flags ); 48 | sd_bus_vtable createSdBusVTableReadOnlyPropertyItem( const char *member 49 | , const char *signature 50 | , sd_bus_property_get_t getter 51 | , uint64_t flags ); 52 | sd_bus_vtable createSdBusVTableWritablePropertyItem( const char *member 53 | , const char *signature 54 | , sd_bus_property_get_t getter 55 | , sd_bus_property_set_t setter 56 | , uint64_t flags ); 57 | sd_bus_vtable createSdBusVTableEndItem(); 58 | 59 | #ifdef __cplusplus 60 | } 61 | #endif 62 | 63 | #endif /* SDBUS_CXX_INTERNAL_VTABLEUTILS_H_ */ 64 | -------------------------------------------------------------------------------- /tests/integrationtests/DBusConnectionTests.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * (C) 2016 - 2021 KISTLER INSTRUMENTE AG, Winterthur, Switzerland 3 | * (C) 2016 - 2024 Stanislav Angelovic 4 | * 5 | * @file DBusConnectionTests.cpp 6 | * 7 | * Created on: Jan 2, 2017 8 | * Project: sdbus-c++ 9 | * Description: High-level D-Bus IPC C++ library based on sd-bus 10 | * 11 | * This file is part of sdbus-c++. 12 | * 13 | * sdbus-c++ is free software; you can redistribute it and/or modify it 14 | * under the terms of the GNU Lesser General Public License as published by 15 | * the Free Software Foundation, either version 2.1 of the License, or 16 | * (at your option) any later version. 17 | * 18 | * sdbus-c++ is distributed in the hope that it will be useful, 19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 | * GNU Lesser General Public License for more details. 22 | * 23 | * You should have received a copy of the GNU Lesser General Public License 24 | * along with sdbus-c++. If not, see . 25 | */ 26 | 27 | // Own 28 | #include "Defs.h" 29 | 30 | // sdbus 31 | #include 32 | #include 33 | 34 | // gmock 35 | #include 36 | #include 37 | 38 | // STL 39 | #include 40 | #include 41 | 42 | using ::testing::Eq; 43 | using namespace sdbus::test; 44 | 45 | /*-------------------------------------*/ 46 | /* -- TEST CASES -- */ 47 | /*-------------------------------------*/ 48 | 49 | TEST(Connection, CanBeDefaultConstructed) 50 | { 51 | ASSERT_NO_THROW(auto con = sdbus::createBusConnection()); 52 | } 53 | 54 | TEST(Connection, CanRequestName) 55 | { 56 | auto connection = sdbus::createBusConnection(); 57 | 58 | // In case of system bus connection, requesting may throw as we need to allow that first through a config file in /etc/dbus-1/system.d 59 | ASSERT_NO_THROW(connection->requestName(SERVICE_NAME)) 60 | << "Perhaps you've forgotten to copy `org.sdbuscpp.integrationtests.conf` file to `/etc/dbus-1/system.d` directory before running the tests?"; 61 | } 62 | 63 | TEST(SystemBusConnection, CannotRequestNonregisteredDbusName) 64 | { 65 | auto connection = sdbus::createSystemBusConnection(); 66 | sdbus::ServiceName notSupportedBusName{"some.random.not.supported.dbus.name"}; 67 | 68 | ASSERT_THROW(connection->requestName(notSupportedBusName), sdbus::Error); 69 | } 70 | 71 | TEST(Connection, CanReleaseRequestedName) 72 | { 73 | auto connection = sdbus::createBusConnection(); 74 | connection->requestName(SERVICE_NAME); 75 | 76 | ASSERT_NO_THROW(connection->releaseName(SERVICE_NAME)); 77 | } 78 | 79 | TEST(Connection, CannotReleaseNonrequestedName) 80 | { 81 | auto connection = sdbus::createBusConnection(); 82 | sdbus::ServiceName notAcquiredBusName{"some.random.unacquired.name"}; 83 | 84 | ASSERT_THROW(connection->releaseName(notAcquiredBusName), sdbus::Error); 85 | } 86 | 87 | TEST(Connection, CanEnterAndLeaveInternalEventLoop) 88 | { 89 | auto connection = sdbus::createBusConnection(); 90 | connection->requestName(SERVICE_NAME); 91 | 92 | std::thread t([&](){ connection->enterEventLoop(); }); 93 | connection->leaveEventLoop(); 94 | 95 | t.join(); 96 | } 97 | -------------------------------------------------------------------------------- /tests/integrationtests/DBusGeneralTests.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * (C) 2016 - 2021 KISTLER INSTRUMENTE AG, Winterthur, Switzerland 3 | * (C) 2016 - 2024 Stanislav Angelovic 4 | * 5 | * @file DBusGeneralTests.cpp 6 | * 7 | * Created on: Jan 2, 2017 8 | * Project: sdbus-c++ 9 | * Description: High-level D-Bus IPC C++ library based on sd-bus 10 | * 11 | * This file is part of sdbus-c++. 12 | * 13 | * sdbus-c++ is free software; you can redistribute it and/or modify it 14 | * under the terms of the GNU Lesser General Public License as published by 15 | * the Free Software Foundation, either version 2.1 of the License, or 16 | * (at your option) any later version. 17 | * 18 | * sdbus-c++ is distributed in the hope that it will be useful, 19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 | * GNU Lesser General Public License for more details. 22 | * 23 | * You should have received a copy of the GNU Lesser General Public License 24 | * along with sdbus-c++. If not, see . 25 | */ 26 | 27 | #include "TestAdaptor.h" 28 | #include "TestProxy.h" 29 | #include "TestFixture.h" 30 | #include "sdbus-c++/sdbus-c++.h" 31 | 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | 43 | using ::testing::ElementsAre; 44 | using ::testing::Eq; 45 | using namespace std::chrono_literals; 46 | using namespace sdbus::test; 47 | using namespace std::string_view_literals; 48 | 49 | using ADirectConnection = TestFixtureWithDirectConnection; 50 | 51 | /*-------------------------------------*/ 52 | /* -- TEST CASES -- */ 53 | /*-------------------------------------*/ 54 | 55 | TEST(AdaptorAndProxy, CanBeConstructedSuccessfully) 56 | { 57 | auto connection = sdbus::createBusConnection(); 58 | connection->requestName(SERVICE_NAME); 59 | 60 | ASSERT_NO_THROW(TestAdaptor adaptor(*connection, OBJECT_PATH)); 61 | ASSERT_NO_THROW(TestProxy proxy(SERVICE_NAME, OBJECT_PATH)); 62 | 63 | connection->releaseName(SERVICE_NAME); 64 | } 65 | 66 | TEST(AProxy, DoesNotSupportMoveSemantics) 67 | { 68 | static_assert(!std::is_move_constructible_v); 69 | static_assert(!std::is_move_assignable_v); 70 | } 71 | 72 | TEST(AnAdaptor, DoesNotSupportMoveSemantics) 73 | { 74 | static_assert(!std::is_move_constructible_v); 75 | static_assert(!std::is_move_assignable_v); 76 | } 77 | 78 | TYPED_TEST(AConnection, WillCallCallbackHandlerForIncomingMessageMatchingMatchRule) 79 | { 80 | auto matchRule = "sender='" + SERVICE_NAME + "',path='" + OBJECT_PATH + "'"; 81 | std::atomic matchingMessageReceived{false}; 82 | auto slot = this->s_proxyConnection->addMatch(matchRule, [&](sdbus::Message msg) 83 | { 84 | if(msg.getPath() == OBJECT_PATH) 85 | matchingMessageReceived = true; 86 | }, sdbus::return_slot); 87 | 88 | this->m_adaptor->emitSimpleSignal(); 89 | 90 | ASSERT_TRUE(waitUntil(matchingMessageReceived)); 91 | } 92 | 93 | TYPED_TEST(AConnection, CanInstallMatchRuleAsynchronously) 94 | { 95 | auto matchRule = "sender='" + SERVICE_NAME + "',path='" + OBJECT_PATH + "'"; 96 | std::atomic matchingMessageReceived{false}; 97 | std::atomic matchRuleInstalled{false}; 98 | auto slot = this->s_proxyConnection->addMatchAsync( matchRule 99 | , [&](sdbus::Message msg) 100 | { 101 | if(msg.getPath() == OBJECT_PATH) 102 | matchingMessageReceived = true; 103 | } 104 | , [&](sdbus::Message /*msg*/) 105 | { 106 | matchRuleInstalled = true; 107 | } 108 | , sdbus::return_slot ); 109 | 110 | EXPECT_TRUE(waitUntil(matchRuleInstalled)); 111 | 112 | this->m_adaptor->emitSimpleSignal(); 113 | 114 | ASSERT_TRUE(waitUntil(matchingMessageReceived)); 115 | } 116 | 117 | TYPED_TEST(AConnection, WillUnsubscribeMatchRuleWhenClientDestroysTheAssociatedSlot) 118 | { 119 | auto matchRule = "sender='" + SERVICE_NAME + "',path='" + OBJECT_PATH + "'"; 120 | std::atomic matchingMessageReceived{false}; 121 | auto slot = this->s_proxyConnection->addMatch(matchRule, [&](sdbus::Message msg) 122 | { 123 | if(msg.getPath() == OBJECT_PATH) 124 | matchingMessageReceived = true; 125 | }, sdbus::return_slot); 126 | slot.reset(); 127 | 128 | this->m_adaptor->emitSimpleSignal(); 129 | 130 | ASSERT_FALSE(waitUntil(matchingMessageReceived, 1s)); 131 | } 132 | 133 | TYPED_TEST(AConnection, CanAddFloatingMatchRule) 134 | { 135 | auto matchRule = "sender='" + SERVICE_NAME + "',path='" + OBJECT_PATH + "'"; 136 | std::atomic matchingMessageReceived{false}; 137 | auto con = sdbus::createBusConnection(); 138 | con->enterEventLoopAsync(); 139 | auto callback = [&](sdbus::Message msg) 140 | { 141 | if(msg.getPath() == OBJECT_PATH) 142 | matchingMessageReceived = true; 143 | }; 144 | con->addMatch(matchRule, std::move(callback)); 145 | this->m_adaptor->emitSimpleSignal(); 146 | [[maybe_unused]] auto gotMessage = waitUntil(matchingMessageReceived, 2s); 147 | assert(gotMessage); 148 | matchingMessageReceived = false; 149 | 150 | con.reset(); 151 | this->m_adaptor->emitSimpleSignal(); 152 | 153 | ASSERT_FALSE(waitUntil(matchingMessageReceived, 1s)); 154 | } 155 | 156 | TYPED_TEST(AConnection, WillNotPassToMatchCallbackMessagesThatDoNotMatchTheRule) 157 | { 158 | auto matchRule = "type='signal',interface='" + INTERFACE_NAME + "',member='simpleSignal'"; 159 | std::atomic numberOfMatchingMessages{}; 160 | auto slot = this->s_proxyConnection->addMatch(matchRule, [&](sdbus::Message msg) 161 | { 162 | if(msg.getMemberName() == "simpleSignal"sv) 163 | numberOfMatchingMessages++; 164 | }, sdbus::return_slot); 165 | auto adaptor2 = std::make_unique(*this->s_adaptorConnection, OBJECT_PATH_2); 166 | 167 | this->m_adaptor->emitSignalWithMap({}); 168 | adaptor2->emitSimpleSignal(); 169 | this->m_adaptor->emitSimpleSignal(); 170 | 171 | ASSERT_TRUE(waitUntil([&](){ return numberOfMatchingMessages == 2; })); 172 | ASSERT_FALSE(waitUntil([&](){ return numberOfMatchingMessages > 2; }, 1s)); 173 | } 174 | 175 | // A simple direct connection test similar in nature to https://github.com/systemd/systemd/blob/main/src/libsystemd/sd-bus/test-bus-server.c 176 | TEST_F(ADirectConnection, CanBeUsedBetweenClientAndServer) 177 | { 178 | auto val = m_proxy->sumArrayItems({1, 7}, {2, 3, 4}); 179 | m_adaptor->emitSimpleSignal(); 180 | 181 | // Make sure method call passes and emitted signal is received 182 | ASSERT_THAT(val, Eq(1 + 7 + 2 + 3 + 4)); 183 | ASSERT_TRUE(waitUntil(m_proxy->m_gotSimpleSignal)); 184 | } 185 | -------------------------------------------------------------------------------- /tests/integrationtests/DBusPropertiesTests.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * (C) 2016 - 2021 KISTLER INSTRUMENTE AG, Winterthur, Switzerland 3 | * (C) 2016 - 2024 Stanislav Angelovic 4 | * 5 | * @file DBusPropertiesTests.cpp 6 | * 7 | * Created on: Jan 2, 2017 8 | * Project: sdbus-c++ 9 | * Description: High-level D-Bus IPC C++ library based on sd-bus 10 | * 11 | * This file is part of sdbus-c++. 12 | * 13 | * sdbus-c++ is free software; you can redistribute it and/or modify it 14 | * under the terms of the GNU Lesser General Public License as published by 15 | * the Free Software Foundation, either version 2.1 of the License, or 16 | * (at your option) any later version. 17 | * 18 | * sdbus-c++ is distributed in the hope that it will be useful, 19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 | * GNU Lesser General Public License for more details. 22 | * 23 | * You should have received a copy of the GNU Lesser General Public License 24 | * along with sdbus-c++. If not, see . 25 | */ 26 | 27 | #include "TestFixture.h" 28 | #include "TestAdaptor.h" 29 | #include "TestProxy.h" 30 | #include "sdbus-c++/sdbus-c++.h" 31 | 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | 42 | using ::testing::Eq; 43 | using ::testing::DoubleEq; 44 | using ::testing::Gt; 45 | using ::testing::AnyOf; 46 | using ::testing::ElementsAre; 47 | using ::testing::SizeIs; 48 | using ::testing::NotNull; 49 | using ::testing::Not; 50 | using ::testing::IsEmpty; 51 | using namespace std::chrono_literals; 52 | using namespace sdbus::test; 53 | 54 | /*-------------------------------------*/ 55 | /* -- TEST CASES -- */ 56 | /*-------------------------------------*/ 57 | 58 | TYPED_TEST(SdbusTestObject, ReadsReadOnlyPropertySuccessfully) 59 | { 60 | ASSERT_THAT(this->m_proxy->state(), Eq(DEFAULT_STATE_VALUE)); 61 | } 62 | 63 | TYPED_TEST(SdbusTestObject, FailsWritingToReadOnlyProperty) 64 | { 65 | ASSERT_THROW(this->m_proxy->setStateProperty("new_value"), sdbus::Error); 66 | } 67 | 68 | TYPED_TEST(SdbusTestObject, WritesAndReadsReadWritePropertySuccessfully) 69 | { 70 | uint32_t newActionValue = 5678; 71 | 72 | this->m_proxy->action(newActionValue); 73 | 74 | ASSERT_THAT(this->m_proxy->action(), Eq(newActionValue)); 75 | } 76 | 77 | TYPED_TEST(SdbusTestObject, CanAccessAssociatedPropertySetMessageInPropertySetHandler) 78 | { 79 | this->m_proxy->blocking(true); // This will save pointer to property get message on server side 80 | 81 | ASSERT_THAT(this->m_adaptor->m_propertySetMsg, NotNull()); 82 | ASSERT_THAT(this->m_adaptor->m_propertySetSender, Not(IsEmpty())); 83 | } 84 | 85 | TYPED_TEST(SdbusTestObject, WritesAndReadsReadWriteVariantPropertySuccessfully) 86 | { 87 | sdbus::Variant newActionValue{5678}; 88 | 89 | this->m_proxy->actionVariant(newActionValue); 90 | 91 | ASSERT_THAT(this->m_proxy->actionVariant().template get(), Eq(5678)); 92 | } 93 | -------------------------------------------------------------------------------- /tests/integrationtests/DBusSignalsTests.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * (C) 2016 - 2021 KISTLER INSTRUMENTE AG, Winterthur, Switzerland 3 | * (C) 2016 - 2024 Stanislav Angelovic 4 | * 5 | * @file AdaptorAndProxy_test.cpp 6 | * 7 | * Created on: Jan 2, 2017 8 | * Project: sdbus-c++ 9 | * Description: High-level D-Bus IPC C++ library based on sd-bus 10 | * 11 | * This file is part of sdbus-c++. 12 | * 13 | * sdbus-c++ is free software; you can redistribute it and/or modify it 14 | * under the terms of the GNU Lesser General Public License as published by 15 | * the Free Software Foundation, either version 2.1 of the License, or 16 | * (at your option) any later version. 17 | * 18 | * sdbus-c++ is distributed in the hope that it will be useful, 19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 | * GNU Lesser General Public License for more details. 22 | * 23 | * You should have received a copy of the GNU Lesser General Public License 24 | * along with sdbus-c++. If not, see . 25 | */ 26 | 27 | #include "TestFixture.h" 28 | #include "TestAdaptor.h" 29 | #include "TestProxy.h" 30 | #include "sdbus-c++/sdbus-c++.h" 31 | 32 | #include 33 | #include 34 | #include 35 | #include 36 | 37 | using ::testing::Eq; 38 | using ::testing::DoubleEq; 39 | using ::testing::Gt; 40 | using ::testing::AnyOf; 41 | using ::testing::ElementsAre; 42 | using ::testing::SizeIs; 43 | using ::testing::NotNull; 44 | using namespace std::chrono_literals; 45 | using namespace sdbus::test; 46 | 47 | /*-------------------------------------*/ 48 | /* -- TEST CASES -- */ 49 | /*-------------------------------------*/ 50 | 51 | TYPED_TEST(SdbusTestObject, EmitsSimpleSignalSuccessfully) 52 | { 53 | this->m_adaptor->emitSimpleSignal(); 54 | 55 | ASSERT_TRUE(waitUntil(this->m_proxy->m_gotSimpleSignal)); 56 | } 57 | 58 | TYPED_TEST(SdbusTestObject, EmitsSimpleSignalToMultipleProxiesSuccessfully) 59 | { 60 | auto proxy1 = std::make_unique(*this->s_adaptorConnection, SERVICE_NAME, OBJECT_PATH); 61 | auto proxy2 = std::make_unique(*this->s_adaptorConnection, SERVICE_NAME, OBJECT_PATH); 62 | 63 | this->m_adaptor->emitSimpleSignal(); 64 | 65 | ASSERT_TRUE(waitUntil(this->m_proxy->m_gotSimpleSignal)); 66 | ASSERT_TRUE(waitUntil(proxy1->m_gotSimpleSignal)); 67 | ASSERT_TRUE(waitUntil(proxy2->m_gotSimpleSignal)); 68 | } 69 | 70 | TYPED_TEST(SdbusTestObject, ProxyDoesNotReceiveSignalFromOtherBusName) 71 | { 72 | sdbus::ServiceName otherBusName{SERVICE_NAME + "2"}; 73 | auto connection2 = sdbus::createBusConnection(otherBusName); 74 | auto adaptor2 = std::make_unique(*connection2, OBJECT_PATH); 75 | 76 | adaptor2->emitSimpleSignal(); 77 | 78 | ASSERT_FALSE(waitUntil(this->m_proxy->m_gotSimpleSignal, 1s)); 79 | } 80 | 81 | TYPED_TEST(SdbusTestObject, EmitsSignalWithMapSuccessfully) 82 | { 83 | this->m_adaptor->emitSignalWithMap({{0, "zero"}, {1, "one"}}); 84 | 85 | ASSERT_TRUE(waitUntil(this->m_proxy->m_gotSignalWithMap)); 86 | ASSERT_THAT(this->m_proxy->m_mapFromSignal[0], Eq("zero")); 87 | ASSERT_THAT(this->m_proxy->m_mapFromSignal[1], Eq("one")); 88 | } 89 | 90 | TYPED_TEST(SdbusTestObject, EmitsSignalWithLargeMapSuccessfully) 91 | { 92 | std::map largeMap; 93 | for (int32_t i = 0; i < 20'000; ++i) 94 | largeMap.emplace(i, "This is string nr. " + std::to_string(i+1)); 95 | this->m_adaptor->emitSignalWithMap(largeMap); 96 | 97 | ASSERT_TRUE(waitUntil(this->m_proxy->m_gotSignalWithMap)); 98 | ASSERT_THAT(this->m_proxy->m_mapFromSignal[0], Eq("This is string nr. 1")); 99 | ASSERT_THAT(this->m_proxy->m_mapFromSignal[1], Eq("This is string nr. 2")); 100 | } 101 | 102 | TYPED_TEST(SdbusTestObject, EmitsSignalWithVariantSuccessfully) 103 | { 104 | double d = 3.14; 105 | this->m_adaptor->emitSignalWithVariant(sdbus::Variant{d}); 106 | 107 | ASSERT_TRUE(waitUntil(this->m_proxy->m_gotSignalWithVariant)); 108 | ASSERT_THAT(this->m_proxy->m_variantFromSignal, DoubleEq(d)); 109 | } 110 | 111 | TYPED_TEST(SdbusTestObject, EmitsSignalWithoutRegistrationSuccessfully) 112 | { 113 | this->m_adaptor->emitSignalWithoutRegistration({"platform", sdbus::Signature{"av"}}); 114 | 115 | ASSERT_TRUE(waitUntil(this->m_proxy->m_gotSignalWithSignature)); 116 | ASSERT_THAT(this->m_proxy->m_signatureFromSignal["platform"], Eq(sdbus::Signature{"av"})); 117 | } 118 | 119 | TYPED_TEST(SdbusTestObject, CanAccessAssociatedSignalMessageInSignalHandler) 120 | { 121 | this->m_adaptor->emitSimpleSignal(); 122 | 123 | waitUntil(this->m_proxy->m_gotSimpleSignal); 124 | 125 | ASSERT_THAT(this->m_proxy->m_signalMsg, NotNull()); 126 | ASSERT_THAT(this->m_proxy->m_signalName, Eq(std::string("simpleSignal"))); 127 | } 128 | 129 | TYPED_TEST(SdbusTestObject, UnregistersSignalHandler) 130 | { 131 | ASSERT_NO_THROW(this->m_proxy->unregisterSimpleSignalHandler()); 132 | 133 | this->m_adaptor->emitSimpleSignal(); 134 | 135 | ASSERT_FALSE(waitUntil(this->m_proxy->m_gotSimpleSignal, 1s)); 136 | } 137 | 138 | TYPED_TEST(SdbusTestObject, UnregistersSignalHandlerForSomeProxies) 139 | { 140 | auto proxy1 = std::make_unique(*this->s_adaptorConnection, SERVICE_NAME, OBJECT_PATH); 141 | auto proxy2 = std::make_unique(*this->s_adaptorConnection, SERVICE_NAME, OBJECT_PATH); 142 | 143 | ASSERT_NO_THROW(this->m_proxy->unregisterSimpleSignalHandler()); 144 | 145 | this->m_adaptor->emitSimpleSignal(); 146 | 147 | ASSERT_TRUE(waitUntil(proxy1->m_gotSimpleSignal)); 148 | ASSERT_TRUE(waitUntil(proxy2->m_gotSimpleSignal)); 149 | ASSERT_FALSE(waitUntil(this->m_proxy->m_gotSimpleSignal, 1s)); 150 | } 151 | 152 | TYPED_TEST(SdbusTestObject, ReRegistersSignalHandler) 153 | { 154 | // unregister simple-signal handler 155 | ASSERT_NO_THROW(this->m_proxy->unregisterSimpleSignalHandler()); 156 | 157 | this->m_adaptor->emitSimpleSignal(); 158 | 159 | ASSERT_FALSE(waitUntil(this->m_proxy->m_gotSimpleSignal, 1s)); 160 | 161 | // re-register simple-signal handler 162 | ASSERT_NO_THROW(this->m_proxy->reRegisterSimpleSignalHandler()); 163 | 164 | this->m_adaptor->emitSimpleSignal(); 165 | 166 | ASSERT_TRUE(waitUntil(this->m_proxy->m_gotSimpleSignal)); 167 | } 168 | -------------------------------------------------------------------------------- /tests/integrationtests/Defs.h: -------------------------------------------------------------------------------- 1 | /** 2 | * (C) 2016 - 2021 KISTLER INSTRUMENTE AG, Winterthur, Switzerland 3 | * (C) 2016 - 2024 Stanislav Angelovic 4 | * 5 | * @file Defs.h 6 | * 7 | * Created on: Jan 2, 2017 8 | * Project: sdbus-c++ 9 | * Description: High-level D-Bus IPC C++ library based on sd-bus 10 | * 11 | * This file is part of sdbus-c++. 12 | * 13 | * sdbus-c++ is free software; you can redistribute it and/or modify it 14 | * under the terms of the GNU Lesser General Public License as published by 15 | * the Free Software Foundation, either version 2.1 of the License, or 16 | * (at your option) any later version. 17 | * 18 | * sdbus-c++ is distributed in the hope that it will be useful, 19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 | * GNU Lesser General Public License for more details. 22 | * 23 | * You should have received a copy of the GNU Lesser General Public License 24 | * along with sdbus-c++. If not, see . 25 | */ 26 | 27 | #ifndef SDBUS_CPP_INTEGRATIONTESTS_DEFS_H_ 28 | #define SDBUS_CPP_INTEGRATIONTESTS_DEFS_H_ 29 | 30 | #include "sdbus-c++/Types.h" 31 | #include 32 | #include 33 | #include 34 | 35 | namespace sdbus { namespace test { 36 | 37 | const InterfaceName INTERFACE_NAME{"org.sdbuscpp.integrationtests"}; 38 | const ServiceName SERVICE_NAME{"org.sdbuscpp.integrationtests"}; 39 | const ServiceName EMPTY_DESTINATION; 40 | const ObjectPath MANAGER_PATH {"/org/sdbuscpp/integrationtests"}; 41 | const ObjectPath OBJECT_PATH {"/org/sdbuscpp/integrationtests/ObjectA1"}; 42 | const ObjectPath OBJECT_PATH_2{"/org/sdbuscpp/integrationtests/ObjectB1"}; 43 | const PropertyName STATE_PROPERTY{"state"}; 44 | const PropertyName ACTION_PROPERTY{"action"}; 45 | const PropertyName ACTION_VARIANT_PROPERTY{"actionVariant"}; 46 | const PropertyName BLOCKING_PROPERTY{"blocking"}; 47 | const std::string DIRECT_CONNECTION_SOCKET_PATH{std::filesystem::temp_directory_path() / "sdbus-cpp-direct-connection-test"}; 48 | 49 | constexpr const uint8_t UINT8_VALUE{1}; 50 | constexpr const int16_t INT16_VALUE{21}; 51 | constexpr const uint32_t UINT32_VALUE{42}; 52 | constexpr const int32_t INT32_VALUE{-42}; 53 | constexpr const int32_t INT64_VALUE{-1024}; 54 | 55 | const std::string STRING_VALUE{"sdbus-c++-testing"}; 56 | const Signature SIGNATURE_VALUE{"a{is}"}; 57 | const ObjectPath OBJECT_PATH_VALUE{"/"}; 58 | const int UNIX_FD_VALUE = 0; 59 | 60 | const std::string DEFAULT_STATE_VALUE{"default-state-value"}; 61 | const uint32_t DEFAULT_ACTION_VALUE{999}; 62 | const std::string DEFAULT_ACTION_VARIANT_VALUE{"ahoj"}; 63 | const bool DEFAULT_BLOCKING_VALUE{true}; 64 | 65 | constexpr const double DOUBLE_VALUE{3.24L}; 66 | 67 | }} 68 | 69 | namespace testing::internal { 70 | 71 | // Printer for std::chrono::duration types. 72 | // This is a workaround, since it's not a good thing to add this to std namespace. 73 | template< class Rep, class Period > 74 | void PrintTo(const ::std::chrono::duration& d, ::std::ostream* os) { 75 | auto seconds = std::chrono::duration_cast>(d); 76 | *os << seconds.count() << "s"; 77 | } 78 | 79 | } 80 | 81 | #endif /* SDBUS_CPP_INTEGRATIONTESTS_DEFS_H_ */ 82 | -------------------------------------------------------------------------------- /tests/integrationtests/TestFixture.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * (C) 2016 - 2021 KISTLER INSTRUMENTE AG, Winterthur, Switzerland 3 | * (C) 2016 - 2024 Stanislav Angelovic 4 | * 5 | * @file TestFixture.cpp 6 | * 7 | * Created on: May 23, 2020 8 | * Project: sdbus-c++ 9 | * Description: High-level D-Bus IPC C++ library based on sd-bus 10 | * 11 | * This file is part of sdbus-c++. 12 | * 13 | * sdbus-c++ is free software; you can redistribute it and/or modify it 14 | * under the terms of the GNU Lesser General Public License as published by 15 | * the Free Software Foundation, either version 2.1 of the License, or 16 | * (at your option) any later version. 17 | * 18 | * sdbus-c++ is distributed in the hope that it will be useful, 19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 | * GNU Lesser General Public License for more details. 22 | * 23 | * You should have received a copy of the GNU Lesser General Public License 24 | * along with sdbus-c++. If not, see . 25 | */ 26 | 27 | #include "TestFixture.h" 28 | 29 | namespace sdbus { namespace test { 30 | 31 | std::unique_ptr BaseTestFixture::s_adaptorConnection = sdbus::createBusConnection(); 32 | std::unique_ptr BaseTestFixture::s_proxyConnection = sdbus::createBusConnection(); 33 | 34 | #ifndef SDBUS_basu // sd_event integration is not supported in basu-based sdbus-c++ 35 | 36 | std::thread TestFixture::s_adaptorEventLoopThread{}; 37 | std::thread TestFixture::s_proxyEventLoopThread{}; 38 | sd_event *TestFixture::s_adaptorSdEvent{}; 39 | sd_event *TestFixture::s_proxySdEvent{}; 40 | int TestFixture::s_eventExitFd{-1}; 41 | 42 | #endif // SDBUS_basu 43 | 44 | }} 45 | -------------------------------------------------------------------------------- /tests/integrationtests/files/org.sdbuscpp.integrationtests.conf: -------------------------------------------------------------------------------- 1 | 3 | 4 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /tests/integrationtests/org.sdbuscpp.integrationtests.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | -------------------------------------------------------------------------------- /tests/integrationtests/sdbus-c++-integration-tests.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * (C) 2016 - 2021 KISTLER INSTRUMENTE AG, Winterthur, Switzerland 3 | * (C) 2016 - 2024 Stanislav Angelovic 4 | * 5 | * @file sdbus-c++-integration-tests.cpp 6 | * 7 | * Created on: Jan 2, 2017 8 | * Project: sdbus-c++ 9 | * Description: High-level D-Bus IPC C++ library based on sd-bus 10 | * 11 | * This file is part of sdbus-c++. 12 | * 13 | * sdbus-c++ is free software; you can redistribute it and/or modify it 14 | * under the terms of the GNU Lesser General Public License as published by 15 | * the Free Software Foundation, either version 2.1 of the License, or 16 | * (at your option) any later version. 17 | * 18 | * sdbus-c++ is distributed in the hope that it will be useful, 19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 | * GNU Lesser General Public License for more details. 22 | * 23 | * You should have received a copy of the GNU Lesser General Public License 24 | * along with sdbus-c++. If not, see . 25 | */ 26 | 27 | #include "gmock/gmock.h" 28 | 29 | int main(int argc, char **argv) 30 | { 31 | ::testing::InitGoogleMock(&argc, argv); 32 | 33 | return RUN_ALL_TESTS(); 34 | } 35 | -------------------------------------------------------------------------------- /tests/perftests/client.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * (C) 2016 - 2021 KISTLER INSTRUMENTE AG, Winterthur, Switzerland 3 | * (C) 2016 - 2024 Stanislav Angelovic 4 | * 5 | * @file client.cpp 6 | * 7 | * Created on: Jan 25, 2019 8 | * Project: sdbus-c++ 9 | * Description: High-level D-Bus IPC C++ library based on sd-bus 10 | * 11 | * This file is part of sdbus-c++. 12 | * 13 | * sdbus-c++ is free software; you can redistribute it and/or modify it 14 | * under the terms of the GNU Lesser General Public License as published by 15 | * the Free Software Foundation, either version 2.1 of the License, or 16 | * (at your option) any later version. 17 | * 18 | * sdbus-c++ is distributed in the hope that it will be useful, 19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 | * GNU Lesser General Public License for more details. 22 | * 23 | * You should have received a copy of the GNU Lesser General Public License 24 | * along with sdbus-c++. If not, see . 25 | */ 26 | 27 | #include "perftests-proxy.h" 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | 39 | using namespace std::chrono_literals; 40 | 41 | uint64_t totalDuration = 0; 42 | 43 | class PerftestProxy final : public sdbus::ProxyInterfaces 44 | { 45 | public: 46 | PerftestProxy(sdbus::ServiceName destination, sdbus::ObjectPath objectPath) 47 | : ProxyInterfaces(std::move(destination), std::move(objectPath)) 48 | { 49 | registerProxy(); 50 | } 51 | 52 | ~PerftestProxy() 53 | { 54 | unregisterProxy(); 55 | } 56 | 57 | protected: 58 | virtual void onDataSignal([[maybe_unused]] const std::string& data) override 59 | { 60 | static unsigned int counter = 0; 61 | static std::chrono::time_point startTime; 62 | 63 | assert(data.size() == m_msgSize); 64 | 65 | ++counter; 66 | 67 | if (counter == 1) 68 | startTime = std::chrono::steady_clock::now(); 69 | else if (counter == m_msgCount) 70 | { 71 | auto stopTime = std::chrono::steady_clock::now(); 72 | auto duration = std::chrono::duration_cast(stopTime - startTime).count(); 73 | totalDuration += duration; 74 | std::cout << "Received " << m_msgCount << " signals in: " << duration << " ms" << std::endl; 75 | counter = 0; 76 | } 77 | } 78 | 79 | public: 80 | unsigned int m_msgSize{}; 81 | unsigned int m_msgCount{}; 82 | }; 83 | 84 | std::string createRandomString(size_t length) 85 | { 86 | auto randchar = []() -> char 87 | { 88 | const char charset[] = 89 | "0123456789" 90 | "ABCDEFGHIJKLMNOPQRSTUVWXYZ" 91 | "abcdefghijklmnopqrstuvwxyz"; 92 | const size_t max_index = (sizeof(charset) - 1); 93 | return charset[ rand() % max_index ]; 94 | }; 95 | std::string str(length, 0); 96 | std::generate_n(str.begin(), length, randchar); 97 | return str; 98 | } 99 | 100 | 101 | //----------------------------------------- 102 | int main(int /*argc*/, char */*argv*/[]) 103 | { 104 | sdbus::ServiceName destination{"org.sdbuscpp.perftests"}; 105 | sdbus::ObjectPath objectPath{"/org/sdbuscpp/perftests"}; 106 | PerftestProxy client(std::move(destination), std::move(objectPath)); 107 | 108 | const unsigned int repetitions{20}; 109 | unsigned int msgCount = 1000; 110 | unsigned int msgSize{}; 111 | 112 | msgSize = 20; 113 | std::cout << "** Measuring signals of size " << msgSize << " bytes (" << repetitions << " repetitions)..." << std::endl << std::endl; 114 | client.m_msgCount = msgCount; client.m_msgSize = msgSize; 115 | for (unsigned int r = 0; r < repetitions; ++r) 116 | { 117 | client.sendDataSignals(msgCount, msgSize); 118 | 119 | std::this_thread::sleep_for(1000ms); 120 | } 121 | 122 | std::cout << "AVERAGE: " << (totalDuration/repetitions) << " ms" << std::endl; 123 | totalDuration = 0; 124 | 125 | msgSize = 1000; 126 | std::cout << std::endl << "** Measuring signals of size " << msgSize << " bytes (" << repetitions << " repetitions)..." << std::endl << std::endl; 127 | client.m_msgCount = msgCount; client.m_msgSize = msgSize; 128 | for (unsigned int r = 0; r < repetitions; ++r) 129 | { 130 | client.sendDataSignals(msgCount, msgSize); 131 | 132 | std::this_thread::sleep_for(1000ms); 133 | } 134 | 135 | std::cout << "AVERAGE: " << (totalDuration/repetitions) << " ms" << std::endl; 136 | totalDuration = 0; 137 | 138 | msgSize = 20; 139 | std::cout << std::endl << "** Measuring method calls of size " << msgSize << " bytes (" << repetitions << " repetitions)..." << std::endl << std::endl; 140 | for (unsigned int r = 0; r < repetitions; ++r) 141 | { 142 | auto str1 = createRandomString(msgSize/2); 143 | auto str2 = createRandomString(msgSize/2); 144 | 145 | auto startTime = std::chrono::steady_clock::now(); 146 | for (unsigned int i = 0; i < msgCount; i++) 147 | { 148 | auto result = client.concatenateTwoStrings(str1, str2); 149 | 150 | assert(result.size() == str1.size() + str2.size()); 151 | assert(result.size() == msgSize); 152 | } 153 | auto stopTime = std::chrono::steady_clock::now(); 154 | auto duration = std::chrono::duration_cast(stopTime - startTime).count(); 155 | totalDuration += duration; 156 | std::cout << "Called " << msgCount << " methods in: " << duration << " ms" << std::endl; 157 | 158 | std::this_thread::sleep_for(1000ms); 159 | } 160 | 161 | std::cout << "AVERAGE: " << (totalDuration/repetitions) << " ms" << std::endl; 162 | totalDuration = 0; 163 | 164 | msgSize = 1000; 165 | std::cout << std::endl << "** Measuring method calls of size " << msgSize << " bytes (" << repetitions << " repetitions)..." << std::endl << std::endl; 166 | for (unsigned int r = 0; r < repetitions; ++r) 167 | { 168 | auto str1 = createRandomString(msgSize/2); 169 | auto str2 = createRandomString(msgSize/2); 170 | 171 | auto startTime = std::chrono::steady_clock::now(); 172 | for (unsigned int i = 0; i < msgCount; i++) 173 | { 174 | auto result = client.concatenateTwoStrings(str1, str2); 175 | 176 | assert(result.size() == str1.size() + str2.size()); 177 | assert(result.size() == msgSize); 178 | } 179 | auto stopTime = std::chrono::steady_clock::now(); 180 | auto duration = std::chrono::duration_cast(stopTime - startTime).count(); 181 | totalDuration += duration; 182 | std::cout << "Called " << msgCount << " methods in: " << duration << " ms" << std::endl; 183 | 184 | std::this_thread::sleep_for(1000ms); 185 | } 186 | 187 | std::cout << "AVERAGE: " << (totalDuration/repetitions) << " ms" << std::endl; 188 | totalDuration = 0; 189 | 190 | return 0; 191 | } 192 | -------------------------------------------------------------------------------- /tests/perftests/files/org.sdbuscpp.perftests.conf: -------------------------------------------------------------------------------- 1 | 3 | 4 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /tests/perftests/org.sdbuscpp.perftests.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /tests/perftests/perftests-adaptor.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * This file was automatically generated by sdbus-c++-xml2cpp; DO NOT EDIT! 4 | */ 5 | 6 | #ifndef __sdbuscpp__perftests_adaptor_h__adaptor__H__ 7 | #define __sdbuscpp__perftests_adaptor_h__adaptor__H__ 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | namespace org { 14 | namespace sdbuscpp { 15 | 16 | class perftests_adaptor 17 | { 18 | public: 19 | static constexpr const char* INTERFACE_NAME = "org.sdbuscpp.perftests"; 20 | 21 | protected: 22 | perftests_adaptor(sdbus::IObject& object) 23 | : m_object(object) 24 | { 25 | } 26 | 27 | perftests_adaptor(const perftests_adaptor&) = delete; 28 | perftests_adaptor& operator=(const perftests_adaptor&) = delete; 29 | perftests_adaptor(perftests_adaptor&&) = delete; 30 | perftests_adaptor& operator=(perftests_adaptor&&) = delete; 31 | 32 | ~perftests_adaptor() = default; 33 | 34 | void registerAdaptor() 35 | { 36 | m_object.addVTable( sdbus::registerMethod("sendDataSignals").withInputParamNames("numberOfSignals", "signalMsgSize").implementedAs([this](const uint32_t& numberOfSignals, const uint32_t& signalMsgSize){ return this->sendDataSignals(numberOfSignals, signalMsgSize); }) 37 | , sdbus::registerMethod("concatenateTwoStrings").withInputParamNames("string1", "string2").withOutputParamNames("result").implementedAs([this](const std::string& string1, const std::string& string2){ return this->concatenateTwoStrings(string1, string2); }) 38 | , sdbus::registerSignal("dataSignal").withParameters("data") 39 | ).forInterface(INTERFACE_NAME); 40 | } 41 | 42 | public: 43 | void emitDataSignal(const std::string& data) 44 | { 45 | m_object.emitSignal("dataSignal").onInterface(INTERFACE_NAME).withArguments(data); 46 | } 47 | 48 | private: 49 | virtual void sendDataSignals(const uint32_t& numberOfSignals, const uint32_t& signalMsgSize) = 0; 50 | virtual std::string concatenateTwoStrings(const std::string& string1, const std::string& string2) = 0; 51 | 52 | private: 53 | sdbus::IObject& m_object; 54 | }; 55 | 56 | }} // namespaces 57 | 58 | #endif 59 | -------------------------------------------------------------------------------- /tests/perftests/perftests-proxy.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * This file was automatically generated by sdbus-c++-xml2cpp; DO NOT EDIT! 4 | */ 5 | 6 | #ifndef __sdbuscpp__perftests_proxy_h__proxy__H__ 7 | #define __sdbuscpp__perftests_proxy_h__proxy__H__ 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | namespace org { 14 | namespace sdbuscpp { 15 | 16 | class perftests_proxy 17 | { 18 | public: 19 | static constexpr const char* INTERFACE_NAME = "org.sdbuscpp.perftests"; 20 | 21 | protected: 22 | perftests_proxy(sdbus::IProxy& proxy) 23 | : m_proxy(proxy) 24 | { 25 | } 26 | 27 | perftests_proxy(const perftests_proxy&) = delete; 28 | perftests_proxy& operator=(const perftests_proxy&) = delete; 29 | perftests_proxy(perftests_proxy&&) = delete; 30 | perftests_proxy& operator=(perftests_proxy&&) = delete; 31 | 32 | ~perftests_proxy() = default; 33 | 34 | void registerProxy() 35 | { 36 | m_proxy.uponSignal("dataSignal").onInterface(INTERFACE_NAME).call([this](const std::string& data){ this->onDataSignal(data); }); 37 | } 38 | 39 | virtual void onDataSignal(const std::string& data) = 0; 40 | 41 | public: 42 | void sendDataSignals(const uint32_t& numberOfSignals, const uint32_t& signalMsgSize) 43 | { 44 | m_proxy.callMethod("sendDataSignals").onInterface(INTERFACE_NAME).withArguments(numberOfSignals, signalMsgSize); 45 | } 46 | 47 | std::string concatenateTwoStrings(const std::string& string1, const std::string& string2) 48 | { 49 | std::string result; 50 | m_proxy.callMethod("concatenateTwoStrings").onInterface(INTERFACE_NAME).withArguments(string1, string2).storeResultsTo(result); 51 | return result; 52 | } 53 | 54 | private: 55 | sdbus::IProxy& m_proxy; 56 | }; 57 | 58 | }} // namespaces 59 | 60 | #endif 61 | -------------------------------------------------------------------------------- /tests/perftests/server.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * (C) 2016 - 2021 KISTLER INSTRUMENTE AG, Winterthur, Switzerland 3 | * (C) 2016 - 2024 Stanislav Angelovic 4 | * 5 | * @file server.cpp 6 | * 7 | * Created on: Jan 25, 2019 8 | * Project: sdbus-c++ 9 | * Description: High-level D-Bus IPC C++ library based on sd-bus 10 | * 11 | * This file is part of sdbus-c++. 12 | * 13 | * sdbus-c++ is free software; you can redistribute it and/or modify it 14 | * under the terms of the GNU Lesser General Public License as published by 15 | * the Free Software Foundation, either version 2.1 of the License, or 16 | * (at your option) any later version. 17 | * 18 | * sdbus-c++ is distributed in the hope that it will be useful, 19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 | * GNU Lesser General Public License for more details. 22 | * 23 | * You should have received a copy of the GNU Lesser General Public License 24 | * along with sdbus-c++. If not, see . 25 | */ 26 | 27 | #include "perftests-adaptor.h" 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | 36 | using namespace std::chrono_literals; 37 | 38 | std::string createRandomString(size_t length); 39 | 40 | class PerftestAdaptor final : public sdbus::AdaptorInterfaces 41 | { 42 | public: 43 | PerftestAdaptor(sdbus::IConnection& connection, sdbus::ObjectPath objectPath) 44 | : AdaptorInterfaces(connection, std::move(objectPath)) 45 | { 46 | registerAdaptor(); 47 | } 48 | 49 | ~PerftestAdaptor() 50 | { 51 | unregisterAdaptor(); 52 | } 53 | 54 | protected: 55 | virtual void sendDataSignals(const uint32_t& numberOfSignals, const uint32_t& signalMsgSize) override 56 | { 57 | auto data = createRandomString(signalMsgSize); 58 | 59 | auto start_time = std::chrono::steady_clock::now(); 60 | for (uint32_t i = 0; i < numberOfSignals; ++i) 61 | { 62 | // Emit signal 63 | emitDataSignal(data); 64 | } 65 | auto stop_time = std::chrono::steady_clock::now(); 66 | std::cout << "Server sent " << numberOfSignals << " signals in: " << std::chrono::duration_cast(stop_time - start_time).count() << " ms" << std::endl; 67 | } 68 | 69 | virtual std::string concatenateTwoStrings(const std::string& string1, const std::string& string2) override 70 | { 71 | return string1 + string2; 72 | } 73 | }; 74 | 75 | std::string createRandomString(size_t length) 76 | { 77 | auto randchar = []() -> char 78 | { 79 | const char charset[] = 80 | "0123456789" 81 | "ABCDEFGHIJKLMNOPQRSTUVWXYZ" 82 | "abcdefghijklmnopqrstuvwxyz"; 83 | const size_t max_index = (sizeof(charset) - 1); 84 | return charset[ rand() % max_index ]; 85 | }; 86 | std::string str(length, 0); 87 | std::generate_n(str.begin(), length, randchar); 88 | return str; 89 | } 90 | 91 | 92 | //----------------------------------------- 93 | int main(int /*argc*/, char */*argv*/[]) 94 | { 95 | sdbus::ServiceName serviceName{"org.sdbuscpp.perftests"}; 96 | auto connection = sdbus::createSystemBusConnection(serviceName); 97 | 98 | sdbus::ObjectPath objectPath{"/org/sdbuscpp/perftests"}; 99 | PerftestAdaptor server(*connection, std::move(objectPath)); 100 | 101 | connection->enterEventLoop(); 102 | } 103 | -------------------------------------------------------------------------------- /tests/stresstests/celsius-thermometer-adaptor.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * This file was automatically generated by sdbus-c++-xml2cpp; DO NOT EDIT! 4 | */ 5 | 6 | #ifndef __sdbuscpp__celsius_thermometer_adaptor_h__adaptor__H__ 7 | #define __sdbuscpp__celsius_thermometer_adaptor_h__adaptor__H__ 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | namespace org { 14 | namespace sdbuscpp { 15 | namespace stresstests { 16 | namespace celsius { 17 | 18 | class thermometer_adaptor 19 | { 20 | public: 21 | static constexpr const char* INTERFACE_NAME = "org.sdbuscpp.stresstests.celsius.thermometer"; 22 | 23 | protected: 24 | thermometer_adaptor(sdbus::IObject& object) 25 | : m_object(object) 26 | { 27 | } 28 | 29 | thermometer_adaptor(const thermometer_adaptor&) = delete; 30 | thermometer_adaptor& operator=(const thermometer_adaptor&) = delete; 31 | thermometer_adaptor(thermometer_adaptor&&) = delete; 32 | thermometer_adaptor& operator=(thermometer_adaptor&&) = delete; 33 | 34 | ~thermometer_adaptor() = default; 35 | 36 | void registerAdaptor() 37 | { 38 | m_object.addVTable(sdbus::registerMethod("getCurrentTemperature").withOutputParamNames("result").implementedAs([this](){ return this->getCurrentTemperature(); })).forInterface(INTERFACE_NAME); 39 | } 40 | 41 | private: 42 | virtual uint32_t getCurrentTemperature() = 0; 43 | 44 | private: 45 | sdbus::IObject& m_object; 46 | }; 47 | 48 | }}}} // namespaces 49 | 50 | #endif 51 | -------------------------------------------------------------------------------- /tests/stresstests/celsius-thermometer-proxy.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * This file was automatically generated by sdbus-c++-xml2cpp; DO NOT EDIT! 4 | */ 5 | 6 | #ifndef __sdbuscpp__celsius_thermometer_proxy_h__proxy__H__ 7 | #define __sdbuscpp__celsius_thermometer_proxy_h__proxy__H__ 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | namespace org { 14 | namespace sdbuscpp { 15 | namespace stresstests { 16 | namespace celsius { 17 | 18 | class thermometer_proxy 19 | { 20 | public: 21 | static constexpr const char* INTERFACE_NAME = "org.sdbuscpp.stresstests.celsius.thermometer"; 22 | 23 | protected: 24 | thermometer_proxy(sdbus::IProxy& proxy) 25 | : m_proxy(proxy) 26 | { 27 | } 28 | 29 | thermometer_proxy(const thermometer_proxy&) = delete; 30 | thermometer_proxy& operator=(const thermometer_proxy&) = delete; 31 | thermometer_proxy(thermometer_proxy&&) = delete; 32 | thermometer_proxy& operator=(thermometer_proxy&&) = delete; 33 | 34 | ~thermometer_proxy() = default; 35 | 36 | void registerProxy() 37 | { 38 | } 39 | 40 | public: 41 | uint32_t getCurrentTemperature() 42 | { 43 | uint32_t result; 44 | m_proxy.callMethod("getCurrentTemperature").onInterface(INTERFACE_NAME).storeResultsTo(result); 45 | return result; 46 | } 47 | 48 | private: 49 | sdbus::IProxy& m_proxy; 50 | }; 51 | 52 | }}}} // namespaces 53 | 54 | #endif 55 | -------------------------------------------------------------------------------- /tests/stresstests/concatenator-adaptor.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * This file was automatically generated by sdbus-c++-xml2cpp; DO NOT EDIT! 4 | */ 5 | 6 | #ifndef __sdbuscpp__concatenator_adaptor_h__adaptor__H__ 7 | #define __sdbuscpp__concatenator_adaptor_h__adaptor__H__ 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | namespace org { 14 | namespace sdbuscpp { 15 | namespace stresstests { 16 | 17 | class concatenator_adaptor 18 | { 19 | public: 20 | static constexpr const char* INTERFACE_NAME = "org.sdbuscpp.stresstests.concatenator"; 21 | 22 | protected: 23 | concatenator_adaptor(sdbus::IObject& object) 24 | : m_object(object) 25 | { 26 | } 27 | 28 | concatenator_adaptor(const concatenator_adaptor&) = delete; 29 | concatenator_adaptor& operator=(const concatenator_adaptor&) = delete; 30 | concatenator_adaptor(concatenator_adaptor&&) = delete; 31 | concatenator_adaptor& operator=(concatenator_adaptor&&) = delete; 32 | 33 | ~concatenator_adaptor() = default; 34 | 35 | void registerAdaptor() 36 | { 37 | m_object.addVTable( sdbus::registerMethod("concatenate").withInputParamNames("params").withOutputParamNames("result").implementedAs([this](sdbus::Result&& result, std::map params){ this->concatenate(std::move(result), std::move(params)); }) 38 | , sdbus::registerSignal("concatenatedSignal").withParameters("concatenatedString") 39 | ).forInterface(INTERFACE_NAME); 40 | } 41 | 42 | public: 43 | void emitConcatenatedSignal(const std::string& concatenatedString) 44 | { 45 | m_object.emitSignal("concatenatedSignal").onInterface(INTERFACE_NAME).withArguments(concatenatedString); 46 | } 47 | 48 | private: 49 | virtual void concatenate(sdbus::Result&& result, std::map params) = 0; 50 | 51 | private: 52 | sdbus::IObject& m_object; 53 | }; 54 | 55 | }}} // namespaces 56 | 57 | #endif 58 | -------------------------------------------------------------------------------- /tests/stresstests/concatenator-proxy.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * This file was automatically generated by sdbus-c++-xml2cpp; DO NOT EDIT! 4 | */ 5 | 6 | #ifndef __sdbuscpp__concatenator_proxy_h__proxy__H__ 7 | #define __sdbuscpp__concatenator_proxy_h__proxy__H__ 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | namespace org { 14 | namespace sdbuscpp { 15 | namespace stresstests { 16 | 17 | class concatenator_proxy 18 | { 19 | public: 20 | static constexpr const char* INTERFACE_NAME = "org.sdbuscpp.stresstests.concatenator"; 21 | 22 | protected: 23 | concatenator_proxy(sdbus::IProxy& proxy) 24 | : m_proxy(proxy) 25 | { 26 | } 27 | 28 | concatenator_proxy(const concatenator_proxy&) = delete; 29 | concatenator_proxy& operator=(const concatenator_proxy&) = delete; 30 | concatenator_proxy(concatenator_proxy&&) = delete; 31 | concatenator_proxy& operator=(concatenator_proxy&&) = delete; 32 | 33 | ~concatenator_proxy() = default; 34 | 35 | void registerProxy() 36 | { 37 | m_proxy.uponSignal("concatenatedSignal").onInterface(INTERFACE_NAME).call([this](const std::string& concatenatedString){ this->onConcatenatedSignal(concatenatedString); }); 38 | } 39 | 40 | virtual void onConcatenatedSignal(const std::string& concatenatedString) = 0; 41 | 42 | virtual void onConcatenateReply(const std::string& result, std::optional error) = 0; 43 | 44 | public: 45 | sdbus::PendingAsyncCall concatenate(const std::map& params) 46 | { 47 | return m_proxy.callMethodAsync("concatenate").onInterface(INTERFACE_NAME).withArguments(params).uponReplyInvoke([this](std::optional error, const std::string& result){ this->onConcatenateReply(result, std::move(error)); }); 48 | } 49 | 50 | private: 51 | sdbus::IProxy& m_proxy; 52 | }; 53 | 54 | }}} // namespaces 55 | 56 | #endif 57 | -------------------------------------------------------------------------------- /tests/stresstests/fahrenheit-thermometer-adaptor.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * This file was automatically generated by sdbus-c++-xml2cpp; DO NOT EDIT! 4 | */ 5 | 6 | #ifndef __sdbuscpp__fahrenheit_thermometer_adaptor_h__adaptor__H__ 7 | #define __sdbuscpp__fahrenheit_thermometer_adaptor_h__adaptor__H__ 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | namespace org { 14 | namespace sdbuscpp { 15 | namespace stresstests { 16 | namespace fahrenheit { 17 | 18 | class thermometer_adaptor 19 | { 20 | public: 21 | static constexpr const char* INTERFACE_NAME = "org.sdbuscpp.stresstests.fahrenheit.thermometer"; 22 | 23 | protected: 24 | thermometer_adaptor(sdbus::IObject& object) 25 | : m_object(object) 26 | { 27 | } 28 | 29 | thermometer_adaptor(const thermometer_adaptor&) = delete; 30 | thermometer_adaptor& operator=(const thermometer_adaptor&) = delete; 31 | thermometer_adaptor(thermometer_adaptor&&) = delete; 32 | thermometer_adaptor& operator=(thermometer_adaptor&&) = delete; 33 | 34 | ~thermometer_adaptor() = default; 35 | 36 | void registerAdaptor() 37 | { 38 | m_object.addVTable(sdbus::registerMethod("getCurrentTemperature").withOutputParamNames("result").implementedAs([this](){ return this->getCurrentTemperature(); })).forInterface(INTERFACE_NAME); 39 | } 40 | 41 | private: 42 | virtual uint32_t getCurrentTemperature() = 0; 43 | 44 | private: 45 | sdbus::IObject& m_object; 46 | }; 47 | 48 | }}}} // namespaces 49 | 50 | namespace org { 51 | namespace sdbuscpp { 52 | namespace stresstests { 53 | namespace fahrenheit { 54 | namespace thermometer { 55 | 56 | class factory_adaptor 57 | { 58 | public: 59 | static constexpr const char* INTERFACE_NAME = "org.sdbuscpp.stresstests.fahrenheit.thermometer.factory"; 60 | 61 | protected: 62 | factory_adaptor(sdbus::IObject& object) 63 | : m_object(object) 64 | { 65 | } 66 | 67 | factory_adaptor(const factory_adaptor&) = delete; 68 | factory_adaptor& operator=(const factory_adaptor&) = delete; 69 | factory_adaptor(factory_adaptor&&) = delete; 70 | factory_adaptor& operator=(factory_adaptor&&) = delete; 71 | 72 | ~factory_adaptor() = default; 73 | 74 | void registerAdaptor() 75 | { 76 | m_object.addVTable( sdbus::registerMethod("createDelegateObject").withOutputParamNames("delegate").implementedAs([this](sdbus::Result&& result){ this->createDelegateObject(std::move(result)); }) 77 | , sdbus::registerMethod("destroyDelegateObject").withInputParamNames("delegate").implementedAs([this](sdbus::Result<>&& result, sdbus::ObjectPath delegate){ this->destroyDelegateObject(std::move(result), std::move(delegate)); }).withNoReply() 78 | ).forInterface(INTERFACE_NAME); 79 | } 80 | 81 | private: 82 | virtual void createDelegateObject(sdbus::Result&& result) = 0; 83 | virtual void destroyDelegateObject(sdbus::Result<>&& result, sdbus::ObjectPath delegate) = 0; 84 | 85 | private: 86 | sdbus::IObject& m_object; 87 | }; 88 | 89 | }}}}} // namespaces 90 | 91 | #endif 92 | -------------------------------------------------------------------------------- /tests/stresstests/fahrenheit-thermometer-proxy.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * This file was automatically generated by sdbus-c++-xml2cpp; DO NOT EDIT! 4 | */ 5 | 6 | #ifndef __sdbuscpp__fahrenheit_thermometer_proxy_h__proxy__H__ 7 | #define __sdbuscpp__fahrenheit_thermometer_proxy_h__proxy__H__ 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | namespace org { 14 | namespace sdbuscpp { 15 | namespace stresstests { 16 | namespace fahrenheit { 17 | 18 | class thermometer_proxy 19 | { 20 | public: 21 | static constexpr const char* INTERFACE_NAME = "org.sdbuscpp.stresstests.fahrenheit.thermometer"; 22 | 23 | protected: 24 | thermometer_proxy(sdbus::IProxy& proxy) 25 | : m_proxy(proxy) 26 | { 27 | } 28 | 29 | thermometer_proxy(const thermometer_proxy&) = delete; 30 | thermometer_proxy& operator=(const thermometer_proxy&) = delete; 31 | thermometer_proxy(thermometer_proxy&&) = delete; 32 | thermometer_proxy& operator=(thermometer_proxy&&) = delete; 33 | 34 | ~thermometer_proxy() = default; 35 | 36 | void registerProxy() 37 | { 38 | } 39 | 40 | public: 41 | uint32_t getCurrentTemperature() 42 | { 43 | uint32_t result; 44 | m_proxy.callMethod("getCurrentTemperature").onInterface(INTERFACE_NAME).storeResultsTo(result); 45 | return result; 46 | } 47 | 48 | private: 49 | sdbus::IProxy& m_proxy; 50 | }; 51 | 52 | }}}} // namespaces 53 | 54 | namespace org { 55 | namespace sdbuscpp { 56 | namespace stresstests { 57 | namespace fahrenheit { 58 | namespace thermometer { 59 | 60 | class factory_proxy 61 | { 62 | public: 63 | static constexpr const char* INTERFACE_NAME = "org.sdbuscpp.stresstests.fahrenheit.thermometer.factory"; 64 | 65 | protected: 66 | factory_proxy(sdbus::IProxy& proxy) 67 | : m_proxy(proxy) 68 | { 69 | } 70 | 71 | factory_proxy(const factory_proxy&) = delete; 72 | factory_proxy& operator=(const factory_proxy&) = delete; 73 | factory_proxy(factory_proxy&&) = delete; 74 | factory_proxy& operator=(factory_proxy&&) = delete; 75 | 76 | ~factory_proxy() = default; 77 | 78 | void registerProxy() 79 | { 80 | } 81 | 82 | public: 83 | sdbus::ObjectPath createDelegateObject() 84 | { 85 | sdbus::ObjectPath result; 86 | m_proxy.callMethod("createDelegateObject").onInterface(INTERFACE_NAME).storeResultsTo(result); 87 | return result; 88 | } 89 | 90 | void destroyDelegateObject(const sdbus::ObjectPath& delegate) 91 | { 92 | m_proxy.callMethod("destroyDelegateObject").onInterface(INTERFACE_NAME).withArguments(delegate).dontExpectReply(); 93 | } 94 | 95 | private: 96 | sdbus::IProxy& m_proxy; 97 | }; 98 | 99 | }}}}} // namespaces 100 | 101 | #endif 102 | -------------------------------------------------------------------------------- /tests/stresstests/files/org.sdbuscpp.stresstests.conf: -------------------------------------------------------------------------------- 1 | 3 | 4 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /tests/stresstests/org.sdbuscpp.stresstest.celsius.thermometer.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /tests/stresstests/org.sdbuscpp.stresstest.concatenator.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /tests/stresstests/org.sdbuscpp.stresstest.fahrenheit.thermometer.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /tests/unittests/PollData_test.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * (C) 2016 - 2021 KISTLER INSTRUMENTE AG, Winterthur, Switzerland 3 | * (C) 2016 - 2024 Stanislav Angelovic 4 | * 5 | * @file PollData_test.cpp 6 | * 7 | * Created on: Jan 19, 2023 8 | * Project: sdbus-c++ 9 | * Description: High-level D-Bus IPC C++ library based on sd-bus 10 | * 11 | * This file is part of sdbus-c++. 12 | * 13 | * sdbus-c++ is free software; you can redistribute it and/or modify it 14 | * under the terms of the GNU Lesser General Public License as published by 15 | * the Free Software Foundation, either version 2.1 of the License, or 16 | * (at your option) any later version. 17 | * 18 | * sdbus-c++ is distributed in the hope that it will be useful, 19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 | * GNU Lesser General Public License for more details. 22 | * 23 | * You should have received a copy of the GNU Lesser General Public License 24 | * along with sdbus-c++. If not, see . 25 | */ 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | using ::testing::Eq; 33 | using ::testing::Ge; 34 | using ::testing::Le; 35 | using ::testing::AllOf; 36 | using namespace std::string_literals; 37 | using namespace std::chrono_literals; 38 | 39 | /*-------------------------------------*/ 40 | /* -- TEST CASES -- */ 41 | /*-------------------------------------*/ 42 | 43 | TEST(PollData, ReturnsZeroRelativeTimeoutForZeroAbsoluteTimeout) 44 | { 45 | sdbus::IConnection::PollData pd; 46 | pd.timeout = std::chrono::microseconds::zero(); 47 | 48 | auto relativeTimeout = pd.getRelativeTimeout(); 49 | 50 | EXPECT_THAT(relativeTimeout, Eq(std::chrono::microseconds::zero())); 51 | } 52 | 53 | TEST(PollData, ReturnsZeroPollTimeoutForZeroAbsoluteTimeout) 54 | { 55 | sdbus::IConnection::PollData pd; 56 | pd.timeout = std::chrono::microseconds::zero(); 57 | 58 | auto pollTimeout = pd.getPollTimeout(); 59 | 60 | EXPECT_THAT(pollTimeout, Eq(0)); 61 | } 62 | 63 | TEST(PollData, ReturnsInfiniteRelativeTimeoutForInfiniteAbsoluteTimeout) 64 | { 65 | sdbus::IConnection::PollData pd; 66 | pd.timeout = std::chrono::microseconds::max(); 67 | 68 | auto relativeTimeout = pd.getRelativeTimeout(); 69 | 70 | EXPECT_THAT(relativeTimeout, Eq(std::chrono::microseconds::max())); 71 | } 72 | 73 | TEST(PollData, ReturnsNegativePollTimeoutForInfiniteAbsoluteTimeout) 74 | { 75 | sdbus::IConnection::PollData pd; 76 | pd.timeout = std::chrono::microseconds::max(); 77 | 78 | auto pollTimeout = pd.getPollTimeout(); 79 | 80 | EXPECT_THAT(pollTimeout, Eq(-1)); 81 | } 82 | 83 | TEST(PollData, ReturnsZeroRelativeTimeoutForPastAbsoluteTimeout) 84 | { 85 | sdbus::IConnection::PollData pd; 86 | auto past = std::chrono::steady_clock::now() - 10s; 87 | pd.timeout = std::chrono::duration_cast(past.time_since_epoch()); 88 | 89 | auto relativeTimeout = pd.getRelativeTimeout(); 90 | 91 | EXPECT_THAT(relativeTimeout, Eq(0us)); 92 | } 93 | 94 | TEST(PollData, ReturnsZeroPollTimeoutForPastAbsoluteTimeout) 95 | { 96 | sdbus::IConnection::PollData pd; 97 | auto past = std::chrono::steady_clock::now() - 10s; 98 | pd.timeout = std::chrono::duration_cast(past.time_since_epoch()); 99 | 100 | auto pollTimeout = pd.getPollTimeout(); 101 | 102 | EXPECT_THAT(pollTimeout, Eq(0)); 103 | } 104 | 105 | TEST(PollData, ReturnsCorrectRelativeTimeoutForFutureAbsoluteTimeout) 106 | { 107 | sdbus::IConnection::PollData pd; 108 | auto future = std::chrono::steady_clock::now() + 1s; 109 | pd.timeout = std::chrono::duration_cast(future.time_since_epoch()); 110 | 111 | auto relativeTimeout = pd.getRelativeTimeout(); 112 | 113 | EXPECT_THAT(relativeTimeout, AllOf(Ge(900ms), Le(1100ms))); 114 | } 115 | 116 | TEST(PollData, ReturnsCorrectPollTimeoutForFutureAbsoluteTimeout) 117 | { 118 | sdbus::IConnection::PollData pd; 119 | auto future = std::chrono::steady_clock::now() + 1s; 120 | pd.timeout = std::chrono::duration_cast(future.time_since_epoch()); 121 | 122 | auto pollTimeout = pd.getPollTimeout(); 123 | 124 | EXPECT_THAT(pollTimeout, AllOf(Ge(900), Le(1100))); 125 | } 126 | -------------------------------------------------------------------------------- /tests/unittests/mocks/SdBusMock.h: -------------------------------------------------------------------------------- 1 | /** 2 | * (C) 2016 - 2021 KISTLER INSTRUMENTE AG, Winterthur, Switzerland 3 | * (C) 2016 - 2024 Stanislav Angelovic 4 | * 5 | * @file SdBusMock.h 6 | * @author Ardazishvili Roman (ardazishvili.roman@yandex.ru) 7 | * 8 | * Created on: Mar 12, 2019 9 | * Project: sdbus-c++ 10 | * Description: High-level D-Bus IPC C++ library based on sd-bus 11 | * 12 | * This file is part of sdbus-c++. 13 | * 14 | * sdbus-c++ is free software; you can redistribute it and/or modify it 15 | * under the terms of the GNU Lesser General Public License as published by 16 | * the Free Software Foundation, either version 2.1 of the License, or 17 | * (at your option) any later version. 18 | * 19 | * sdbus-c++ is distributed in the hope that it will be useful, 20 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 21 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 | * GNU Lesser General Public License for more details. 23 | * 24 | * You should have received a copy of the GNU Lesser General Public License 25 | * along with sdbus-c++. If not, see . 26 | */ 27 | 28 | #ifndef SDBUS_CXX_SDBUS_MOCK_H 29 | #define SDBUS_CXX_SDBUS_MOCK_H 30 | 31 | #include "ISdBus.h" 32 | 33 | #include 34 | 35 | class SdBusMock : public sdbus::internal::ISdBus 36 | { 37 | public: 38 | MOCK_METHOD1(sd_bus_message_ref, sd_bus_message*(sd_bus_message *m)); 39 | MOCK_METHOD1(sd_bus_message_unref, sd_bus_message*(sd_bus_message *m)); 40 | 41 | MOCK_METHOD3(sd_bus_send, int(sd_bus *bus, sd_bus_message *m, uint64_t *cookie)); 42 | MOCK_METHOD5(sd_bus_call, int(sd_bus *bus, sd_bus_message *m, uint64_t usec, sd_bus_error *ret_error, sd_bus_message **reply)); 43 | MOCK_METHOD6(sd_bus_call_async, int(sd_bus *bus, sd_bus_slot **slot, sd_bus_message *m, sd_bus_message_handler_t callback, void *userdata, uint64_t usec)); 44 | 45 | MOCK_METHOD3(sd_bus_message_new, int(sd_bus *bus, sd_bus_message **m, uint8_t type)); 46 | MOCK_METHOD6(sd_bus_message_new_method_call, int(sd_bus *bus, sd_bus_message **m, const char *destination, const char *path, const char *interface, const char *member)); 47 | MOCK_METHOD5(sd_bus_message_new_signal, int(sd_bus *bus, sd_bus_message **m, const char *path, const char *interface, const char *member)); 48 | MOCK_METHOD2(sd_bus_message_new_method_return, int(sd_bus_message *call, sd_bus_message **m)); 49 | MOCK_METHOD3(sd_bus_message_new_method_error, int(sd_bus_message *call, sd_bus_message **m, const sd_bus_error *e)); 50 | 51 | MOCK_METHOD2(sd_bus_set_method_call_timeout, int(sd_bus *bus, uint64_t usec)); 52 | MOCK_METHOD2(sd_bus_get_method_call_timeout, int(sd_bus *bus, uint64_t *ret)); 53 | 54 | MOCK_METHOD4(sd_bus_emit_properties_changed_strv, int(sd_bus *bus, const char *path, const char *interface, char **names)); 55 | MOCK_METHOD2(sd_bus_emit_object_added, int(sd_bus *bus, const char *path)); 56 | MOCK_METHOD2(sd_bus_emit_object_removed, int(sd_bus *bus, const char *path)); 57 | MOCK_METHOD3(sd_bus_emit_interfaces_added_strv, int(sd_bus *bus, const char *path, char **interfaces)); 58 | MOCK_METHOD3(sd_bus_emit_interfaces_removed_strv, int(sd_bus *bus, const char *path, char **interfaces)); 59 | 60 | MOCK_METHOD1(sd_bus_open, int(sd_bus **ret)); 61 | MOCK_METHOD1(sd_bus_open_system, int(sd_bus **ret)); 62 | MOCK_METHOD1(sd_bus_open_user, int(sd_bus **ret)); 63 | MOCK_METHOD2(sd_bus_open_user_with_address, int(sd_bus **ret, const char* address)); 64 | MOCK_METHOD2(sd_bus_open_system_remote, int(sd_bus **ret, const char *host)); 65 | MOCK_METHOD2(sd_bus_open_direct, int(sd_bus **ret, const char* address)); 66 | MOCK_METHOD2(sd_bus_open_direct, int(sd_bus **ret, int fd)); 67 | MOCK_METHOD2(sd_bus_open_server, int(sd_bus **ret, int fd)); 68 | MOCK_METHOD3(sd_bus_request_name, int(sd_bus *bus, const char *name, uint64_t flags)); 69 | MOCK_METHOD2(sd_bus_release_name, int(sd_bus *bus, const char *name)); 70 | MOCK_METHOD2(sd_bus_get_unique_name, int(sd_bus *bus, const char **name)); 71 | MOCK_METHOD6(sd_bus_add_object_vtable, int(sd_bus *bus, sd_bus_slot **slot, const char *path, const char *interface, const sd_bus_vtable *vtable, void *userdata)); 72 | MOCK_METHOD3(sd_bus_add_object_manager, int(sd_bus *bus, sd_bus_slot **slot, const char *path)); 73 | MOCK_METHOD5(sd_bus_add_match, int(sd_bus *bus, sd_bus_slot **slot, const char *match, sd_bus_message_handler_t callback, void *userdata)); 74 | MOCK_METHOD6(sd_bus_add_match_async, int(sd_bus *bus, sd_bus_slot **slot, const char *match, sd_bus_message_handler_t callback, sd_bus_message_handler_t install_callback, void *userdata)); 75 | MOCK_METHOD8(sd_bus_match_signal, int(sd_bus *bus, sd_bus_slot **ret, const char *sender, const char *path, const char *interface, const char *member, sd_bus_message_handler_t callback, void *userdata)); 76 | MOCK_METHOD1(sd_bus_slot_unref, sd_bus_slot*(sd_bus_slot *slot)); 77 | 78 | MOCK_METHOD1(sd_bus_new, int(sd_bus **ret)); 79 | MOCK_METHOD1(sd_bus_start, int(sd_bus *bus)); 80 | 81 | MOCK_METHOD2(sd_bus_process, int(sd_bus *bus, sd_bus_message **r)); 82 | MOCK_METHOD1(sd_bus_get_current_message, sd_bus_message*(sd_bus *bus)); 83 | MOCK_METHOD2(sd_bus_get_poll_data, int(sd_bus *bus, PollData* data)); 84 | MOCK_METHOD3(sd_bus_get_n_queued, int(sd_bus *bus, uint64_t *read, uint64_t* write)); 85 | MOCK_METHOD1(sd_bus_flush, int(sd_bus *bus)); 86 | MOCK_METHOD1(sd_bus_flush_close_unref, sd_bus *(sd_bus *bus)); 87 | MOCK_METHOD1(sd_bus_close_unref, sd_bus *(sd_bus *bus)); 88 | 89 | MOCK_METHOD2(sd_bus_message_set_destination, int(sd_bus_message *m, const char *destination)); 90 | 91 | MOCK_METHOD3(sd_bus_query_sender_creds, int(sd_bus_message *, uint64_t, sd_bus_creds **)); 92 | MOCK_METHOD1(sd_bus_creds_ref, sd_bus_creds*(sd_bus_creds *)); 93 | MOCK_METHOD1(sd_bus_creds_unref, sd_bus_creds*(sd_bus_creds *)); 94 | 95 | MOCK_METHOD2(sd_bus_creds_get_pid, int(sd_bus_creds *, pid_t *)); 96 | MOCK_METHOD2(sd_bus_creds_get_uid, int(sd_bus_creds *, uid_t *)); 97 | MOCK_METHOD2(sd_bus_creds_get_euid, int(sd_bus_creds *, uid_t *)); 98 | MOCK_METHOD2(sd_bus_creds_get_gid, int(sd_bus_creds *, gid_t *)); 99 | MOCK_METHOD2(sd_bus_creds_get_egid, int(sd_bus_creds *, gid_t *)); 100 | MOCK_METHOD2(sd_bus_creds_get_supplementary_gids, int(sd_bus_creds *, const gid_t **)); 101 | MOCK_METHOD2(sd_bus_creds_get_selinux_context, int(sd_bus_creds *, const char **)); 102 | }; 103 | 104 | #endif //SDBUS_CXX_SDBUS_MOCK_H 105 | -------------------------------------------------------------------------------- /tests/unittests/sdbus-c++-unit-tests.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * (C) 2016 - 2021 KISTLER INSTRUMENTE AG, Winterthur, Switzerland 3 | * (C) 2016 - 2024 Stanislav Angelovic 4 | * 5 | * @file sdbus-c++-unit-tests.cpp 6 | * 7 | * Created on: Nov 27, 2016 8 | * Project: sdbus-c++ 9 | * Description: High-level D-Bus IPC C++ library based on sd-bus 10 | * 11 | * This file is part of sdbus-c++. 12 | * 13 | * sdbus-c++ is free software; you can redistribute it and/or modify it 14 | * under the terms of the GNU Lesser General Public License as published by 15 | * the Free Software Foundation, either version 2.1 of the License, or 16 | * (at your option) any later version. 17 | * 18 | * sdbus-c++ is distributed in the hope that it will be useful, 19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 | * GNU Lesser General Public License for more details. 22 | * 23 | * You should have received a copy of the GNU Lesser General Public License 24 | * along with sdbus-c++. If not, see . 25 | */ 26 | 27 | #include "gmock/gmock.h" 28 | 29 | int main(int argc, char **argv) 30 | { 31 | ::testing::InitGoogleMock(&argc, argv); 32 | 33 | return RUN_ALL_TESTS(); 34 | } 35 | -------------------------------------------------------------------------------- /tools/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | #------------------------------- 2 | # PROJECT INFORMATION 3 | #------------------------------- 4 | 5 | cmake_minimum_required(VERSION 3.5) 6 | 7 | project(sdbus-c++-tools VERSION 2.1.0) 8 | 9 | include(GNUInstallDirs) 10 | 11 | #------------------------------- 12 | # PERFORMING CHECKS 13 | #------------------------------- 14 | 15 | find_package(EXPAT REQUIRED) 16 | 17 | #------------------------------- 18 | # SOURCE FILES CONFIGURATION 19 | #------------------------------- 20 | 21 | set(SDBUSCPP_XML2CPP_SRCS 22 | xml2cpp-codegen/xml2cpp.cpp 23 | xml2cpp-codegen/xml.h 24 | xml2cpp-codegen/xml.cpp 25 | xml2cpp-codegen/generator_utils.h 26 | xml2cpp-codegen/generator_utils.cpp 27 | xml2cpp-codegen/BaseGenerator.h 28 | xml2cpp-codegen/BaseGenerator.cpp 29 | xml2cpp-codegen/AdaptorGenerator.h 30 | xml2cpp-codegen/AdaptorGenerator.cpp 31 | xml2cpp-codegen/ProxyGenerator.h 32 | xml2cpp-codegen/ProxyGenerator.cpp) 33 | 34 | #------------------------------- 35 | # GENERAL COMPILER CONFIGURATION 36 | #------------------------------- 37 | 38 | set(CMAKE_CXX_STANDARD 14) 39 | 40 | #---------------------------------- 41 | # EXECUTABLE BUILD INFORMATION 42 | #---------------------------------- 43 | 44 | add_executable(sdbus-c++-xml2cpp ${SDBUSCPP_XML2CPP_SRCS}) 45 | target_link_libraries (sdbus-c++-xml2cpp ${EXPAT_LIBRARIES}) 46 | target_include_directories(sdbus-c++-xml2cpp PRIVATE ${EXPAT_INCLUDE_DIRS}) 47 | target_compile_definitions(sdbus-c++-xml2cpp PRIVATE SDBUS_XML2CPP_VERSION="${CMAKE_PROJECT_VERSION}") 48 | 49 | #---------------------------------- 50 | # CMAKE CONFIG & PACKAGE CONFIG 51 | #---------------------------------- 52 | 53 | include(CMakePackageConfigHelpers) 54 | 55 | configure_package_config_file(cmake/sdbus-c++-tools-config.cmake.in cmake/sdbus-c++-tools-config.cmake 56 | INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/sdbus-c++) 57 | write_basic_package_version_file(cmake/sdbus-c++-tools-config-version.cmake COMPATIBILITY SameMajorVersion) 58 | 59 | configure_file(pkgconfig/sdbus-c++-tools.pc.in pkgconfig/sdbus-c++-tools.pc @ONLY) 60 | 61 | #---------------------------------- 62 | # INSTALLATION 63 | #---------------------------------- 64 | 65 | if(NOT DEFINED SDBUSCPP_INSTALL) 66 | set(SDBUSCPP_INSTALL ON) 67 | endif() 68 | 69 | if (SDBUSCPP_INSTALL) 70 | install(TARGETS sdbus-c++-xml2cpp 71 | EXPORT sdbus-c++-tools-targets 72 | DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT sdbus-c++-dev) 73 | install(EXPORT sdbus-c++-tools-targets 74 | DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/sdbus-c++-tools 75 | NAMESPACE SDBusCpp:: 76 | COMPONENT sdbus-c++-dev) 77 | install(FILES ${CMAKE_CURRENT_BINARY_DIR}/cmake/sdbus-c++-tools-config.cmake 78 | ${CMAKE_CURRENT_BINARY_DIR}/cmake/sdbus-c++-tools-config-version.cmake 79 | DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/sdbus-c++-tools 80 | COMPONENT sdbus-c++-dev) 81 | install(FILES ${CMAKE_CURRENT_BINARY_DIR}/pkgconfig/sdbus-c++-tools.pc 82 | DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig COMPONENT sdbus-c++-dev) 83 | endif() 84 | -------------------------------------------------------------------------------- /tools/cmake/sdbus-c++-tools-config.cmake.in: -------------------------------------------------------------------------------- 1 | @PACKAGE_INIT@ 2 | 3 | include("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@-targets.cmake") 4 | check_required_components("sdbus-c++-xml2cpp") 5 | -------------------------------------------------------------------------------- /tools/pkgconfig/sdbus-c++-tools.pc.in: -------------------------------------------------------------------------------- 1 | prefix=@CMAKE_INSTALL_PREFIX@ 2 | exec_prefix=@CMAKE_INSTALL_PREFIX@ 3 | libdir=@CMAKE_INSTALL_FULL_LIBDIR@ 4 | includedir=@CMAKE_INSTALL_FULL_INCLUDEDIR@ 5 | 6 | Name: @PROJECT_NAME@ 7 | Description: Stub generator tool for sdbus-c++ library 8 | Version: @SDBUSCPP_VERSION@ 9 | -------------------------------------------------------------------------------- /tools/xml2cpp-codegen/AdaptorGenerator.h: -------------------------------------------------------------------------------- 1 | /** 2 | * (C) 2016 - 2021 KISTLER INSTRUMENTE AG, Winterthur, Switzerland 3 | * (C) 2016 - 2024 Stanislav Angelovic 4 | * 5 | * @file AdaptorGenerator.h 6 | * 7 | * Created on: Feb 1, 2017 8 | * Project: sdbus-c++ 9 | * Description: High-level D-Bus IPC C++ library based on sd-bus 10 | * 11 | * This file is part of sdbus-c++. 12 | * 13 | * sdbus-c++ is free software; you can redistribute it and/or modify it 14 | * under the terms of the GNU Lesser General Public License as published by 15 | * the Free Software Foundation, either version 2.1 of the License, or 16 | * (at your option) any later version. 17 | * 18 | * sdbus-c++ is distributed in the hope that it will be useful, 19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 | * GNU Lesser General Public License for more details. 22 | * 23 | * You should have received a copy of the GNU Lesser General Public License 24 | * along with sdbus-c++. If not, see . 25 | */ 26 | 27 | #ifndef __SDBUSCPP_TOOLS_ADAPTOR_GENERATOR_H 28 | #define __SDBUSCPP_TOOLS_ADAPTOR_GENERATOR_H 29 | 30 | // Own headers 31 | #include "xml.h" 32 | #include "BaseGenerator.h" 33 | 34 | // STL 35 | #include 36 | #include 37 | 38 | class AdaptorGenerator : public BaseGenerator 39 | { 40 | protected: 41 | /** 42 | * Transform xml to adaptor code 43 | * @param doc 44 | * @param filename 45 | * @return 0 if ok 46 | */ 47 | int transformXmlToFileImpl(const sdbuscpp::xml::Document& doc, const char* filename) const override; 48 | 49 | private: 50 | /** 51 | * Generate source code for interface 52 | * @param interface 53 | * @return source code 54 | */ 55 | std::string processInterface(sdbuscpp::xml::Node& interface) const; 56 | 57 | /** 58 | * Generate source code for methods 59 | * @param methods 60 | * @return tuple: registration of methods, declaration of abstract methods 61 | */ 62 | std::tuple, std::string> processMethods(const sdbuscpp::xml::Nodes& methods) const; 63 | 64 | /** 65 | * Generate source code for signals 66 | * @param signals 67 | * @return tuple: registration of signals, definition of signal methods 68 | */ 69 | std::tuple, std::string> processSignals(const sdbuscpp::xml::Nodes& signals) const; 70 | 71 | /** 72 | * Generate source code for properties 73 | * @param properties 74 | * @return tuple: registration of properties, declaration of property accessor virtual methods 75 | */ 76 | std::tuple, std::string> processProperties(const sdbuscpp::xml::Nodes& properties) const; 77 | 78 | std::string createVTableRegistration(const std::string& annotationRegistration, 79 | const std::vector& methodRegistrations, 80 | const std::vector& signalRegistrations, 81 | const std::vector& propertyRegistrations) const; 82 | 83 | /** 84 | * Get annotations listed for a given node 85 | * @param node 86 | * @return map of annotation names to their values 87 | */ 88 | std::map getAnnotations(sdbuscpp::xml::Node& node) const; 89 | 90 | /** 91 | * Get flag for property update behavior annotation value 92 | * @param annotationValue 93 | * @return flag 94 | */ 95 | std::string propertyAnnotationToFlag(const std::string& annotationValue) const; 96 | }; 97 | 98 | 99 | 100 | #endif //__SDBUSCPP_TOOLS_ADAPTOR_GENERATOR_H 101 | -------------------------------------------------------------------------------- /tools/xml2cpp-codegen/BaseGenerator.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * (C) 2016 - 2021 KISTLER INSTRUMENTE AG, Winterthur, Switzerland 3 | * (C) 2016 - 2024 Stanislav Angelovic 4 | * 5 | * @file BaseGenerator.cpp 6 | * 7 | * Created on: Feb 1, 2017 8 | * Project: sdbus-c++ 9 | * Description: High-level D-Bus IPC C++ library based on sd-bus 10 | * 11 | * This file is part of sdbus-c++. 12 | * 13 | * sdbus-c++ is free software; you can redistribute it and/or modify it 14 | * under the terms of the GNU Lesser General Public License as published by 15 | * the Free Software Foundation, either version 2.1 of the License, or 16 | * (at your option) any later version. 17 | * 18 | * sdbus-c++ is distributed in the hope that it will be useful, 19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 | * GNU Lesser General Public License for more details. 22 | * 23 | * You should have received a copy of the GNU Lesser General Public License 24 | * along with sdbus-c++. If not, see . 25 | */ 26 | 27 | // Own 28 | #include "generator_utils.h" 29 | #include "BaseGenerator.h" 30 | 31 | // STL 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | 39 | 40 | using std::endl; 41 | 42 | using sdbuscpp::xml::Document; 43 | using sdbuscpp::xml::Node; 44 | using sdbuscpp::xml::Nodes; 45 | 46 | 47 | int BaseGenerator::transformXmlToFile(const Document& doc, const char* filename) const 48 | { 49 | return transformXmlToFileImpl(doc, filename); 50 | } 51 | 52 | 53 | int BaseGenerator::writeToFile(const char* filename, const std::string& data) const 54 | { 55 | std::ofstream file(filename); 56 | if (file.fail()) 57 | { 58 | std::cerr << "Unable to write file " << filename << endl; 59 | return 1; 60 | } 61 | 62 | file << data; 63 | file.close(); 64 | return 0; 65 | } 66 | 67 | std::string BaseGenerator::createHeader(const char* filename, const StubType& stubType) const 68 | { 69 | std::ostringstream head; 70 | head << getHeaderComment(); 71 | 72 | std::string specialization = stubType == StubType::ADAPTOR ? "adaptor" : "proxy"; 73 | 74 | std::string cond_comp{"__sdbuscpp__" + underscorize(filename) 75 | + "__" + specialization + "__H__"}; 76 | 77 | head << "#ifndef " << cond_comp << endl 78 | << "#define " << cond_comp << endl << endl; 79 | 80 | head << "#include " << endl 81 | << "#include " << endl 82 | << "#include " << endl 83 | << endl; 84 | 85 | return head.str(); 86 | } 87 | 88 | std::tuple BaseGenerator::generateNamespaces(const std::string& ifaceName) const 89 | { 90 | std::stringstream ss{ifaceName}; 91 | std::ostringstream body; 92 | unsigned count{0}; 93 | 94 | // prints the namespaces X and Y defined with 95 | while (ss.str().find('.', ss.tellg()) != std::string::npos) 96 | { 97 | std::string nspace; 98 | getline(ss, nspace, '.'); 99 | nspace = mangle_name(nspace); 100 | body << "namespace " << nspace << " {" << endl; 101 | ++count; 102 | } 103 | body << endl; 104 | 105 | return std::make_tuple(count, body.str()); 106 | } 107 | 108 | 109 | std::tuple BaseGenerator::argsToNamesAndTypes(const Nodes& args, bool async) const 110 | { 111 | std::ostringstream argSS, argTypeSS, typeSS, argStringsSS; 112 | 113 | for (size_t i = 0; i < args.size(); ++i) 114 | { 115 | auto arg = args.at(i); 116 | if (i > 0) 117 | { 118 | argSS << ", "; 119 | argStringsSS << ", "; 120 | argTypeSS << ", "; 121 | typeSS << ", "; 122 | } 123 | 124 | auto argName = arg->get("name"); 125 | if (argName.empty()) 126 | { 127 | argName = "arg" + std::to_string(i); 128 | } 129 | auto argNameSafe = mangle_name(argName); 130 | auto type = signature_to_type(arg->get("type")); 131 | argStringsSS << "\"" << argName << "\""; 132 | if (!async) 133 | { 134 | argSS << argNameSafe; 135 | argTypeSS << "const " << type << "& " << argNameSafe; 136 | } 137 | else 138 | { 139 | argSS << "std::move(" << argNameSafe << ")"; 140 | argTypeSS << type << " " << argNameSafe; 141 | } 142 | typeSS << type; 143 | } 144 | 145 | return std::make_tuple(argSS.str(), argTypeSS.str(), typeSS.str(), argStringsSS.str()); 146 | } 147 | 148 | /** 149 | * 150 | */ 151 | std::string BaseGenerator::outArgsToType(const Nodes& args, bool bareList) const 152 | { 153 | std::ostringstream retTypeSS; 154 | 155 | if (args.size() == 0) 156 | { 157 | if (bareList) 158 | return ""; 159 | 160 | retTypeSS << "void"; 161 | } 162 | else if (args.size() == 1) 163 | { 164 | const auto& arg = *args.begin(); 165 | retTypeSS << signature_to_type(arg->get("type")); 166 | } 167 | else if (args.size() >= 2) 168 | { 169 | if (!bareList) 170 | retTypeSS << "std::tuple<"; 171 | 172 | bool firstArg = true; 173 | for (const auto& arg : args) 174 | { 175 | if (firstArg) firstArg = false; else retTypeSS << ", "; 176 | retTypeSS << signature_to_type(arg->get("type")); 177 | } 178 | 179 | if (!bareList) 180 | retTypeSS << ">"; 181 | } 182 | 183 | return retTypeSS.str(); 184 | } 185 | -------------------------------------------------------------------------------- /tools/xml2cpp-codegen/BaseGenerator.h: -------------------------------------------------------------------------------- 1 | /** 2 | * (C) 2016 - 2021 KISTLER INSTRUMENTE AG, Winterthur, Switzerland 3 | * (C) 2016 - 2024 Stanislav Angelovic 4 | * 5 | * @file BaseGenerator.h 6 | * 7 | * Created on: Feb 1, 2017 8 | * Project: sdbus-c++ 9 | * Description: High-level D-Bus IPC C++ library based on sd-bus 10 | * 11 | * This file is part of sdbus-c++. 12 | * 13 | * sdbus-c++ is free software; you can redistribute it and/or modify it 14 | * under the terms of the GNU Lesser General Public License as published by 15 | * the Free Software Foundation, either version 2.1 of the License, or 16 | * (at your option) any later version. 17 | * 18 | * sdbus-c++ is distributed in the hope that it will be useful, 19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 | * GNU Lesser General Public License for more details. 22 | * 23 | * You should have received a copy of the GNU Lesser General Public License 24 | * along with sdbus-c++. If not, see . 25 | */ 26 | 27 | #ifndef __SDBUSCPP_TOOLS_BASE_GENERATOR_H 28 | #define __SDBUSCPP_TOOLS_BASE_GENERATOR_H 29 | 30 | // Own headers 31 | #include "xml.h" 32 | 33 | // STL 34 | #include 35 | #include 36 | 37 | class BaseGenerator 38 | { 39 | 40 | public: 41 | int transformXmlToFile(const sdbuscpp::xml::Document& doc, const char* filename) const; 42 | 43 | protected: 44 | enum class StubType 45 | { 46 | ADAPTOR, 47 | PROXY 48 | }; 49 | 50 | constexpr static const char *tab = " "; 51 | 52 | virtual ~BaseGenerator() {} 53 | 54 | /** 55 | * Implementation of public function that is provided by inherited class 56 | * @param doc 57 | * @param filename 58 | * @return 59 | */ 60 | virtual int transformXmlToFileImpl(const sdbuscpp::xml::Document& doc, const char* filename) const = 0; 61 | 62 | 63 | /** 64 | * Write data to file 65 | * @param filename Written file 66 | * @param data Data to write 67 | * @return 0 if ok 68 | */ 69 | int writeToFile(const char* filename, const std::string& data) const; 70 | 71 | /** 72 | * Crete header of file - include guard, includes 73 | * @param filename 74 | * @param stubType 75 | * @return 76 | */ 77 | std::string createHeader(const char* filename, const StubType& stubType) const; 78 | 79 | /** 80 | * Namespaces according to the interface name 81 | * @param ifaceName 82 | * @return tuple: count of namespaces, string with code 83 | */ 84 | std::tuple generateNamespaces(const std::string& ifaceName) const; 85 | 86 | /** 87 | * Transform arguments into source code 88 | * @param args 89 | * @return tuple: argument names, argument types and names, argument types 90 | */ 91 | std::tuple argsToNamesAndTypes(const sdbuscpp::xml::Nodes& args, bool async = false) const; 92 | 93 | /** 94 | * Output arguments to return type 95 | * @param args 96 | * @return return type 97 | */ 98 | std::string outArgsToType(const sdbuscpp::xml::Nodes& args, bool bareList = false) const; 99 | 100 | }; 101 | 102 | 103 | 104 | #endif //__SDBUSCPP_TOOLS_BASE_GENERATOR_H 105 | -------------------------------------------------------------------------------- /tools/xml2cpp-codegen/ProxyGenerator.h: -------------------------------------------------------------------------------- 1 | /** 2 | * (C) 2016 - 2021 KISTLER INSTRUMENTE AG, Winterthur, Switzerland 3 | * (C) 2016 - 2024 Stanislav Angelovic 4 | * 5 | * @file ProxyGenerator.h 6 | * 7 | * Created on: Feb 1, 2017 8 | * Project: sdbus-c++ 9 | * Description: High-level D-Bus IPC C++ library based on sd-bus 10 | * 11 | * This file is part of sdbus-c++. 12 | * 13 | * sdbus-c++ is free software; you can redistribute it and/or modify it 14 | * under the terms of the GNU Lesser General Public License as published by 15 | * the Free Software Foundation, either version 2.1 of the License, or 16 | * (at your option) any later version. 17 | * 18 | * sdbus-c++ is distributed in the hope that it will be useful, 19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 | * GNU Lesser General Public License for more details. 22 | * 23 | * You should have received a copy of the GNU Lesser General Public License 24 | * along with sdbus-c++. If not, see . 25 | */ 26 | 27 | #ifndef __SDBUSCPP_TOOLS_PROXY_GENERATOR_H 28 | #define __SDBUSCPP_TOOLS_PROXY_GENERATOR_H 29 | 30 | // Own headers 31 | #include "xml.h" 32 | #include "BaseGenerator.h" 33 | 34 | // STL 35 | #include 36 | 37 | class ProxyGenerator : public BaseGenerator 38 | { 39 | protected: 40 | /** 41 | * Transform xml to proxy code 42 | * @param doc 43 | * @param filename 44 | * @return 0 if ok 45 | */ 46 | int transformXmlToFileImpl(const sdbuscpp::xml::Document& doc, const char* filename) const override; 47 | 48 | private: 49 | 50 | /** 51 | * Generate source code for interface 52 | * @param interface 53 | * @return source code 54 | */ 55 | std::string processInterface(sdbuscpp::xml::Node& interface) const; 56 | 57 | /** 58 | * Generate method calls 59 | * @param methods 60 | * @return tuple: definition of methods, declaration of virtual async reply handlers 61 | */ 62 | std::tuple processMethods(const sdbuscpp::xml::Nodes& methods) const; 63 | 64 | /** 65 | * Generate code for handling signals 66 | * @param signals 67 | * @return tuple: registration, declaration of virtual methods 68 | */ 69 | std::tuple processSignals(const sdbuscpp::xml::Nodes& signals) const; 70 | 71 | /** 72 | * Generate calls for properties 73 | * @param properties 74 | * @return source code 75 | */ 76 | std::tuple processProperties(const sdbuscpp::xml::Nodes& properties) const; 77 | 78 | }; 79 | 80 | 81 | 82 | #endif //__SDBUSCPP_TOOLS_PROXY_GENERATOR_H 83 | -------------------------------------------------------------------------------- /tools/xml2cpp-codegen/generator_utils.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Inspired by: http://dbus-cplusplus.sourceforge.net/ 3 | */ 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | #include "generator_utils.h" 10 | #include "reserved_names.h" 11 | 12 | 13 | std::string underscorize(const std::string& str) 14 | { 15 | std::string res = str; 16 | for (unsigned int i = 0; i < res.length(); ++i) 17 | { 18 | if (!isalpha(res[i]) && !isdigit(res[i])) 19 | { 20 | res[i] = '_'; 21 | } 22 | } 23 | return res; 24 | } 25 | 26 | std::string stub_name(const std::string& name) 27 | { 28 | return "_" + underscorize(name) + "_stub"; 29 | } 30 | 31 | const char *atomic_type_to_string(char t) 32 | { 33 | static std::map atos 34 | { 35 | { 'y', "uint8_t" }, 36 | { 'b', "bool" }, 37 | { 'n', "int16_t" }, 38 | { 'q', "uint16_t" }, 39 | { 'i', "int32_t" }, 40 | { 'u', "uint32_t" }, 41 | { 'x', "int64_t" }, 42 | { 't', "uint64_t" }, 43 | { 'd', "double" }, 44 | { 's', "std::string" }, 45 | { 'o', "sdbus::ObjectPath" }, 46 | { 'g', "sdbus::Signature" }, 47 | { 'v', "sdbus::Variant" }, 48 | { 'h', "sdbus::UnixFd" }, 49 | { '\0', "" } 50 | }; 51 | 52 | if (atos.count(t)) 53 | { 54 | return atos[t]; 55 | } 56 | 57 | return nullptr; 58 | } 59 | 60 | static void _parse_signature(const std::string &signature, std::string &type, unsigned int &i, bool only_once = false) 61 | { 62 | for (; i < signature.length(); ++i) 63 | { 64 | switch (signature[i]) 65 | { 66 | case 'a': 67 | { 68 | switch (signature[++i]) 69 | { 70 | case '{': 71 | { 72 | type += "std::map<"; 73 | ++i; 74 | _parse_signature(signature, type, i); 75 | type += ">"; 76 | 77 | break; 78 | } 79 | case '(': 80 | { 81 | type += "std::vector 9 | #include 10 | #include 11 | 12 | const char *atomic_type_to_string(char t); 13 | 14 | std::string stub_name(const std::string& name); 15 | 16 | std::string signature_to_type(const std::string& signature); 17 | 18 | std::string underscorize(const std::string& str); 19 | 20 | constexpr const char* getHeaderComment() noexcept { return "\n/*\n * This file was automatically generated by sdbus-c++-xml2cpp; DO NOT EDIT!\n */\n\n"; } 21 | 22 | std::string mangle_name (const std::string& name); 23 | 24 | #endif //__SDBUSCPP_TOOLS_GENERATOR_UTILS_H 25 | -------------------------------------------------------------------------------- /tools/xml2cpp-codegen/reserved_names.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | static const std::set reserved_names = { 4 | // c++ keywords taken from https://en.cppreference.com/w/cpp/keyword 5 | "alignas", 6 | "alignof", 7 | "and", 8 | "and_eq", 9 | "asm", 10 | "atomic_cancel", 11 | "atomic_commit", 12 | "atomic_noexcept", 13 | "auto", 14 | "bitand", 15 | "bitor", 16 | "bool", 17 | "break", 18 | "case", 19 | "catch", 20 | "char", 21 | "char8_t", 22 | "char16_t", 23 | "char32_t", 24 | "class", 25 | "compl", 26 | "concept", 27 | "const", 28 | "consteval", 29 | "constexpr", 30 | "constinit", 31 | "const_cast", 32 | "continue", 33 | "co_await", 34 | "co_return", 35 | "co_yield", 36 | "decltype", 37 | "default", 38 | "delete", 39 | "do", 40 | "double", 41 | "dynamic_cast", 42 | "else", 43 | "enum", 44 | "explicit", 45 | "export", 46 | "extern", 47 | "false", 48 | "float", 49 | "for", 50 | "friend", 51 | "goto", 52 | "if", 53 | "inline", 54 | "int", 55 | "long", 56 | "mutable", 57 | "namespace", 58 | "new", 59 | "noexcept", 60 | "not", 61 | "not_eq", 62 | "nullptr", 63 | "operator", 64 | "or", 65 | "or_eq", 66 | "private", 67 | "protected", 68 | "public", 69 | "reflexpr", 70 | "register", 71 | "reinterpret_cast", 72 | "requires", 73 | "return", 74 | "short", 75 | "signed", 76 | "sizeof", 77 | "static", 78 | "static_assert", 79 | "static_cast", 80 | "struct", 81 | "switch", 82 | "synchronized", 83 | "template", 84 | "this", 85 | "thread_local", 86 | "throw", 87 | "true", 88 | "try", 89 | "typedef", 90 | "typeid", 91 | "typename", 92 | "union", 93 | "unsigned", 94 | "using", 95 | "virtual", 96 | "void", 97 | "volatile", 98 | "wchar_t", 99 | "while", 100 | "xor", 101 | "xor_eq", 102 | // common defines 103 | "NULL" 104 | }; 105 | -------------------------------------------------------------------------------- /tools/xml2cpp-codegen/xml.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Inspired by: http://dbus-cplusplus.sourceforge.net/ 3 | */ 4 | 5 | #ifndef __SDBUSCPP_TOOLS_XML_H 6 | #define __SDBUSCPP_TOOLS_XML_H 7 | 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | namespace sdbuscpp 18 | { 19 | namespace xml 20 | { 21 | 22 | class Error : public std::exception 23 | { 24 | public: 25 | 26 | Error(const char *error, int line, int column); 27 | 28 | ~Error() {} 29 | 30 | const char *what() const noexcept { return m_error.c_str(); } 31 | 32 | private: 33 | std::string m_error; 34 | }; 35 | 36 | 37 | class Node; 38 | 39 | class Nodes : public std::vector 40 | { 41 | public: 42 | Nodes operator[](const std::string &key) const; 43 | Nodes select(const std::string &attr, const std::string &value) const; 44 | }; 45 | 46 | class Node 47 | { 48 | public: 49 | 50 | using Attributes = std::map; 51 | using Children = std::vector; 52 | 53 | std::string name; 54 | std::string cdata; 55 | Children children; 56 | 57 | Node(std::string n, Attributes a) : 58 | name(n), 59 | m_attrs(a) 60 | {} 61 | 62 | Node(const char* n, const char** a = nullptr); 63 | 64 | Nodes operator[](const std::string& key); 65 | 66 | std::string get(const std::string& attribute) const; 67 | 68 | void set(const std::string &attribute, std::string value); 69 | 70 | std::string to_xml() const; 71 | 72 | Node& add(Node child) 73 | { 74 | children.push_back(child); 75 | return children.back(); 76 | } 77 | 78 | private: 79 | 80 | void _raw_xml(std::string& xml, int& depth) const; 81 | 82 | Attributes m_attrs; 83 | }; 84 | 85 | class Document 86 | { 87 | public: 88 | struct Expat; 89 | 90 | Node* root; 91 | 92 | Document(); 93 | ~Document(); 94 | 95 | Document(const std::string& xml); 96 | 97 | void from_xml(const std::string& xml); 98 | 99 | std::string to_xml() const; 100 | 101 | private: 102 | 103 | int m_depth; 104 | }; 105 | 106 | } // namespace xml 107 | 108 | } // namespace sdbuscpp 109 | 110 | std::istream &operator >> (std::istream &, sdbuscpp::xml::Document &); 111 | std::ostream &operator << (std::ostream &, sdbuscpp::xml::Document &); 112 | 113 | #endif//__SDBUSCPP_TOOLS_XML_H 114 | --------------------------------------------------------------------------------