pax_global_header00006660000000000000000000000064140701330470014511gustar00rootroot0000000000000052 comment=5e4094dad7470a975898480dd6ff86953344aa76 dbus-cpp-5.0.3/000077500000000000000000000000001407013304700132335ustar00rootroot00000000000000dbus-cpp-5.0.3/CMakeLists.txt000066400000000000000000000061541407013304700160010ustar00rootroot00000000000000# Copyright © 2013 Canonical Ltd. # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License version 3 as # published by the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # # Authored by: Thomas Voss cmake_minimum_required(VERSION 2.8) project(dbus-cpp) set(DBUS_CPP_VERSION_MAJOR 5) set(DBUS_CPP_VERSION_MINOR 0) set(DBUS_CPP_VERSION_PATCH 3) message(STATUS "${CMAKE_PROJECT_NAME} ${DBUS_CPP_VERSION_MAJOR}.${DBUS_CPP_VERSION_MINOR}.${DBUS_CPP_VERSION_PATCH}") find_package(Boost COMPONENTS filesystem program_options system REQUIRED) find_package(LibXml2 REQUIRED) find_package(PkgConfig REQUIRED) pkg_check_modules(DBUS dbus-1) pkg_check_modules(PROCESS_CPP process-cpp) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake) include(cmake/EnableCoverageReport.cmake) include(cmake/PrePush.cmake) include(GNUInstallDirs) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror -Wall -Wextra -fvisibility=hidden -fPIC -pthread") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Werror -Wall -fno-strict-aliasing -fvisibility=hidden -fvisibility-inlines-hidden -Wextra -fPIC -pthread") set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS}") # We leverage GCC's sanitize functionality set( DBUS_CPP_SANITIZE None CACHE STRING "Enables sanitizer functionality if set to a value in {address, leak}") if((${DBUS_CPP_SANITIZE} STREQUAL "address") OR (${DBUS_CPP_SANITIZE} STREQUAL "leak")) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=${DBUS_CPP_SANITIZE}") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=${DBUS_CPP_SANITIZE}") endif() ##################################################################### # Enable code coverage calculation with gcov/gcovr/lcov # Usage: # * Switch build type to coverage (use ccmake or cmake-gui) # * Invoke make, make test, make coverage # * Find html report in subdir coveragereport # * Find xml report feasible for jenkins in coverage.xml ##################################################################### IF(CMAKE_BUILD_TYPE MATCHES [cC][oO][vV][eE][rR][aA][gG][eE]) SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ftest-coverage -fprofile-arcs" ) SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ftest-coverage -fprofile-arcs" ) SET(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -ftest-coverage -fprofile-arcs" ) SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -ftest-coverage -fprofile-arcs" ) ENDIF(CMAKE_BUILD_TYPE MATCHES [cC][oO][vV][eE][rR][aA][gG][eE]) include(CTest) include_directories( include ${LIBXML2_INCLUDE_DIR} ) add_subdirectory(data) add_subdirectory(doc) add_subdirectory(examples) add_subdirectory(include) add_subdirectory(src) add_subdirectory(tests) enable_coverage_report(benchmark) dbus-cpp-5.0.3/COPYING.GPL000066400000000000000000000432541407013304700147170ustar00rootroot00000000000000 GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. dbus-cpp-5.0.3/COPYING.LGPL000066400000000000000000000167431407013304700150360ustar00rootroot00000000000000 GNU LESSER GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. This version of the GNU Lesser General Public License incorporates the terms and conditions of version 3 of the GNU General Public License, supplemented by the additional permissions listed below. 0. Additional Definitions. As used herein, "this License" refers to version 3 of the GNU Lesser General Public License, and the "GNU GPL" refers to version 3 of the GNU General Public License. "The Library" refers to a covered work governed by this License, other than an Application or a Combined Work as defined below. An "Application" is any work that makes use of an interface provided by the Library, but which is not otherwise based on the Library. Defining a subclass of a class defined by the Library is deemed a mode of using an interface provided by the Library. A "Combined Work" is a work produced by combining or linking an Application with the Library. The particular version of the Library with which the Combined Work was made is also called the "Linked Version". The "Minimal Corresponding Source" for a Combined Work means the Corresponding Source for the Combined Work, excluding any source code for portions of the Combined Work that, considered in isolation, are based on the Application, and not on the Linked Version. The "Corresponding Application Code" for a Combined Work means the object code and/or source code for the Application, including any data and utility programs needed for reproducing the Combined Work from the Application, but excluding the System Libraries of the Combined Work. 1. Exception to Section 3 of the GNU GPL. You may convey a covered work under sections 3 and 4 of this License without being bound by section 3 of the GNU GPL. 2. Conveying Modified Versions. If you modify a copy of the Library, and, in your modifications, a facility refers to a function or data to be supplied by an Application that uses the facility (other than as an argument passed when the facility is invoked), then you may convey a copy of the modified version: a) under this License, provided that you make a good faith effort to ensure that, in the event an Application does not supply the function or data, the facility still operates, and performs whatever part of its purpose remains meaningful, or b) under the GNU GPL, with none of the additional permissions of this License applicable to that copy. 3. Object Code Incorporating Material from Library Header Files. The object code form of an Application may incorporate material from a header file that is part of the Library. You may convey such object code under terms of your choice, provided that, if the incorporated material is not limited to numerical parameters, data structure layouts and accessors, or small macros, inline functions and templates (ten or fewer lines in length), you do both of the following: a) Give prominent notice with each copy of the object code that the Library is used in it and that the Library and its use are covered by this License. b) Accompany the object code with a copy of the GNU GPL and this license document. 4. Combined Works. You may convey a Combined Work under terms of your choice that, taken together, effectively do not restrict modification of the portions of the Library contained in the Combined Work and reverse engineering for debugging such modifications, if you also do each of the following: a) Give prominent notice with each copy of the Combined Work that the Library is used in it and that the Library and its use are covered by this License. b) Accompany the Combined Work with a copy of the GNU GPL and this license document. c) For a Combined Work that displays copyright notices during execution, include the copyright notice for the Library among these notices, as well as a reference directing the user to the copies of the GNU GPL and this license document. d) Do one of the following: 0) Convey the Minimal Corresponding Source under the terms of this License, and the Corresponding Application Code in a form suitable for, and under terms that permit, the user to recombine or relink the Application with a modified version of the Linked Version to produce a modified Combined Work, in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source. 1) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (a) uses at run time a copy of the Library already present on the user's computer system, and (b) will operate properly with a modified version of the Library that is interface-compatible with the Linked Version. e) Provide Installation Information, but only if you would otherwise be required to provide such information under section 6 of the GNU GPL, and only to the extent that such information is necessary to install and execute a modified version of the Combined Work produced by recombining or relinking the Application with a modified version of the Linked Version. (If you use option 4d0, the Installation Information must accompany the Minimal Corresponding Source and Corresponding Application Code. If you use option 4d1, you must provide the Installation Information in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source.) 5. Combined Libraries. You may place library facilities that are a work based on the Library side by side in a single library together with other library facilities that are not Applications and are not covered by this License, and convey such a combined library under terms of your choice, if you do both of the following: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities, conveyed under the terms of this License. b) Give prominent notice with the combined library that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 6. Revised Versions of the GNU Lesser General Public License. The Free Software Foundation may publish revised and/or new versions of the GNU Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library as you received it specifies that a certain numbered version of the GNU Lesser General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that published version or of any later version published by the Free Software Foundation. If the Library as you received it does not specify a version number of the GNU Lesser General Public License, you may choose any version of the GNU Lesser General Public License ever published by the Free Software Foundation. If the Library as you received it specifies that a proxy can decide whether future versions of the GNU Lesser General Public License shall apply, that proxy's public statement of acceptance of any version is permanent authorization for you to choose that version for the Library. dbus-cpp-5.0.3/cmake/000077500000000000000000000000001407013304700143135ustar00rootroot00000000000000dbus-cpp-5.0.3/cmake/EnableCoverageReport.cmake000066400000000000000000000153751407013304700213660ustar00rootroot00000000000000# - Creates a special coverage build type and target on GCC. # # Defines a function ENABLE_COVERAGE_REPORT which generates the coverage target # for selected targets. Optional arguments to this function are used to filter # unwanted results using globbing expressions. Moreover targets with tests for # the source code can be specified to trigger regenerating the report if the # test has changed # # ENABLE_COVERAGE_REPORT(TARGETS target... [FILTER filter...] [TESTS test targets...]) # # To generate a coverage report first build the project with # CMAKE_BUILD_TYPE=coverage, then call make test and afterwards make coverage. # # The coverage report is based on gcov. Depending on the availability of lcov # a HTML report will be generated and/or an XML report of gcovr is found. # The generated coverage target executes all found solutions. Special targets # exist to create e.g. only the xml report: coverage-xml. # # Copyright (C) 2010 by Johannes Wienke # # This program is free software; you can redistribute it # and/or modify it under the terms of the GNU General # Public License as published by the Free Software Foundation; # either version 2, or (at your option) # any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # INCLUDE(ParseArguments) FIND_PACKAGE(Lcov) FIND_PACKAGE(gcovr) FUNCTION(ENABLE_COVERAGE_REPORT) # argument parsing PARSE_ARGUMENTS(ARG "FILTER;TARGETS;TESTS" "" ${ARGN}) SET(COVERAGE_RAW_FILE "${CMAKE_BINARY_DIR}/coverage.raw.info") SET(COVERAGE_FILTERED_FILE "${CMAKE_BINARY_DIR}/coverage.info") SET(COVERAGE_REPORT_DIR "${CMAKE_BINARY_DIR}/coveragereport") SET(COVERAGE_XML_FILE "${CMAKE_BINARY_DIR}/coverage.xml") SET(COVERAGE_XML_COMMAND_FILE "${CMAKE_BINARY_DIR}/coverage-xml.cmake") # decide if there is any tool to create coverage data SET(TOOL_FOUND FALSE) IF(LCOV_FOUND OR GCOVR_FOUND) SET(TOOL_FOUND TRUE) ENDIF() IF(NOT TOOL_FOUND) MESSAGE(STATUS "Cannot enable coverage targets because neither lcov nor gcovr are found.") ENDIF() STRING(TOLOWER "${CMAKE_BUILD_TYPE}" COVERAGE_BUILD_TYPE) IF(CMAKE_COMPILER_IS_GNUCXX AND TOOL_FOUND AND "${COVERAGE_BUILD_TYPE}" MATCHES "coverage") MESSAGE(STATUS "Coverage support enabled for targets: ${ARG_TARGETS}") # create coverage build type SET(CMAKE_CXX_FLAGS_COVERAGE ${CMAKE_CXX_FLAGS_DEBUG} PARENT_SCOPE) SET(CMAKE_C_FLAGS_COVERAGE ${CMAKE_C_FLAGS_DEBUG} PARENT_SCOPE) SET(CMAKE_CONFIGURATION_TYPES ${CMAKE_CONFIGURATION_TYPES} coverage PARENT_SCOPE) # instrument targets SET_TARGET_PROPERTIES(${ARG_TARGETS} PROPERTIES COMPILE_FLAGS --coverage LINK_FLAGS --coverage) # html report IF (LCOV_FOUND) MESSAGE(STATUS "Enabling HTML coverage report") # set up coverage target ADD_CUSTOM_COMMAND(OUTPUT ${COVERAGE_RAW_FILE} COMMAND ${LCOV_EXECUTABLE} -c -d ${CMAKE_BINARY_DIR} -o ${COVERAGE_RAW_FILE} WORKING_DIRECTORY ${CMAKE_BINARY_DIR} COMMENT "Collecting coverage data" DEPENDS ${ARG_TARGETS} ${ARG_TESTS} VERBATIM) # filter unwanted stuff LIST(LENGTH ARG_FILTER FILTER_LENGTH) IF(${FILTER_LENGTH} GREATER 0) SET(FILTER COMMAND ${LCOV_EXECUTABLE}) FOREACH(F ${ARG_FILTER}) SET(FILTER ${FILTER} -r ${COVERAGE_FILTERED_FILE} ${F}) ENDFOREACH() SET(FILTER ${FILTER} -o ${COVERAGE_FILTERED_FILE}) ELSE() SET(FILTER "") ENDIF() ADD_CUSTOM_COMMAND(OUTPUT ${COVERAGE_FILTERED_FILE} COMMAND ${LCOV_EXECUTABLE} -e ${COVERAGE_RAW_FILE} "${CMAKE_SOURCE_DIR}*" -o ${COVERAGE_FILTERED_FILE} ${FILTER} DEPENDS ${COVERAGE_RAW_FILE} COMMENT "Filtering recorded coverage data for project-relevant entries" VERBATIM) ADD_CUSTOM_COMMAND(OUTPUT ${COVERAGE_REPORT_DIR} COMMAND ${CMAKE_COMMAND} -E make_directory ${COVERAGE_REPORT_DIR} COMMAND ${GENHTML_EXECUTABLE} --legend --show-details -t "${PROJECT_NAME} test coverage" -o ${COVERAGE_REPORT_DIR} ${COVERAGE_FILTERED_FILE} DEPENDS ${COVERAGE_FILTERED_FILE} COMMENT "Generating HTML coverage report in ${COVERAGE_REPORT_DIR}" VERBATIM) ADD_CUSTOM_TARGET(coverage-html DEPENDS ${COVERAGE_REPORT_DIR}) ENDIF() # xml coverage report IF(GCOVR_FOUND) MESSAGE(STATUS "Enabling XML coverage report") # gcovr cannot write directly to a file so the execution needs to # be wrapped in a cmake file that generates the file output FILE(WRITE ${COVERAGE_XML_COMMAND_FILE} "SET(ENV{LANG} en)\n") FILE(APPEND ${COVERAGE_XML_COMMAND_FILE} "EXECUTE_PROCESS(COMMAND \"${GCOVR_EXECUTABLE}\" --exclude=tests.* --exclude=obj-.* --exclude=cmake.* -x -r \"${CMAKE_SOURCE_DIR}\" OUTPUT_FILE \"${COVERAGE_XML_FILE}\" WORKING_DIRECTORY \"${CMAKE_BINARY_DIR}\")\n") ADD_CUSTOM_COMMAND(OUTPUT ${COVERAGE_XML_FILE} COMMAND ${CMAKE_COMMAND} ARGS -P ${COVERAGE_XML_COMMAND_FILE} COMMENT "Generating coverage XML report" VERBATIM) ADD_CUSTOM_TARGET(coverage-xml DEPENDS ${COVERAGE_XML_FILE}) ENDIF() # provide a global coverage target executing both steps if available SET(GLOBAL_DEPENDS "") IF(LCOV_FOUND) LIST(APPEND GLOBAL_DEPENDS ${COVERAGE_REPORT_DIR}) ENDIF() IF(GCOVR_FOUND) LIST(APPEND GLOBAL_DEPENDS ${COVERAGE_XML_FILE}) ENDIF() IF(LCOV_FOUND OR GCOVR_FOUND) ADD_CUSTOM_TARGET(coverage DEPENDS ${GLOBAL_DEPENDS}) ENDIF() ENDIF() ENDFUNCTION() dbus-cpp-5.0.3/cmake/FindGtest.cmake000066400000000000000000000033721407013304700172110ustar00rootroot00000000000000include(ExternalProject) include(FindPackageHandleStandardArgs) #gtest set(GTEST_INSTALL_DIR /usr/src/gmock/gtest/include) find_path(GTEST_INCLUDE_DIR gtest/gtest.h HINTS ${GTEST_INSTALL_DIR}) #gmock find_path(GMOCK_INSTALL_DIR gmock/CMakeLists.txt HINTS /usr/src) if(${GMOCK_INSTALL_DIR} STREQUAL "GMOCK_INSTALL_DIR-NOTFOUND") message(FATAL_ERROR "google-mock package not found") endif() set(GMOCK_INSTALL_DIR ${GMOCK_INSTALL_DIR}/gmock) find_path(GMOCK_INCLUDE_DIR gmock/gmock.h) set(GMOCK_PREFIX gmock) set(GMOCK_BINARY_DIR ${CMAKE_BINARY_DIR}/${GMOCK_PREFIX}/libs) set(GTEST_BINARY_DIR ${GMOCK_BINARY_DIR}/gtest) set(GTEST_CMAKE_ARGS "") if (${MIR_IS_CROSS_COMPILING}) set(GTEST_CMAKE_ARGS -DCMAKE_TOOLCHAIN_FILE=${CMAKE_MODULE_PATH}/LinuxCrossCompile.cmake) endif() ExternalProject_Add( GMock #where to build in source tree PREFIX ${GMOCK_PREFIX} #where the source is external to the project SOURCE_DIR ${GMOCK_INSTALL_DIR} #forward the compilers to the subproject so cross-arch builds work CMAKE_ARGS ${GTEST_CMAKE_ARGS} BINARY_DIR ${GMOCK_BINARY_DIR} #we don't need to install, so skip INSTALL_COMMAND "" ) set(GMOCK_LIBRARY ${GMOCK_BINARY_DIR}/libgmock.a) set(GMOCK_MAIN_LIBRARY ${GMOCK_BINARY_DIR}/libgmock_main.a) set(GMOCK_BOTH_LIBRARIES ${GMOCK_LIBRARY} ${GMOCK_MAIN_LIBRARY}) set(GTEST_LIBRARY ${GTEST_BINARY_DIR}/libgtest.a) set(GTEST_MAIN_LIBRARY ${GTEST_BINARY_DIR}/libgtest_main.a) set(GTEST_BOTH_LIBRARIES ${GTEST_LIBRARY} ${GTEST_MAIN_LIBRARY}) set(GTEST_ALL_LIBRARIES ${GTEST_BOTH_LIBRARIES} ${GMOCK_BOTH_LIBRARIES}) find_package_handle_standard_args(GTest DEFAULT_MSG GMOCK_INCLUDE_DIR GTEST_INCLUDE_DIR) dbus-cpp-5.0.3/cmake/FindLcov.cmake000066400000000000000000000017201407013304700170210ustar00rootroot00000000000000# - Find lcov # Will define: # # LCOV_EXECUTABLE - the lcov binary # GENHTML_EXECUTABLE - the genhtml executable # # Copyright (C) 2010 by Johannes Wienke # # This program is free software; you can redistribute it # and/or modify it under the terms of the GNU General # Public License as published by the Free Software Foundation; # either version 2, or (at your option) # any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # INCLUDE(FindPackageHandleStandardArgs) FIND_PROGRAM(LCOV_EXECUTABLE lcov) FIND_PROGRAM(GENHTML_EXECUTABLE genhtml) FIND_PACKAGE_HANDLE_STANDARD_ARGS(Lcov DEFAULT_MSG LCOV_EXECUTABLE GENHTML_EXECUTABLE) # only visible in advanced view MARK_AS_ADVANCED(LCOV_EXECUTABLE GENHTML_EXECUTABLE) dbus-cpp-5.0.3/cmake/Findgcovr.cmake000066400000000000000000000017021407013304700172360ustar00rootroot00000000000000# - Find gcovr scrip # Will define: # # GCOVR_EXECUTABLE - the gcovr script # # Uses: # # GCOVR_ROOT - root to search for the script # # Copyright (C) 2011 by Johannes Wienke # # This program is free software; you can redistribute it # and/or modify it under the terms of the GNU General # Public License as published by the Free Software Foundation; # either version 2, or (at your option) # any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # INCLUDE(FindPackageHandleStandardArgs) FIND_PROGRAM(GCOVR_EXECUTABLE gcovr HINTS ${GCOVR_ROOT} "${GCOVR_ROOT}/bin") FIND_PACKAGE_HANDLE_STANDARD_ARGS(gcovr DEFAULT_MSG GCOVR_EXECUTABLE) # only visible in advanced view MARK_AS_ADVANCED(GCOVR_EXECUTABLE) dbus-cpp-5.0.3/cmake/ParseArguments.cmake000066400000000000000000000034061407013304700202600ustar00rootroot00000000000000# Parse arguments passed to a function into several lists separated by # upper-case identifiers and options that do not have an associated list e.g.: # # SET(arguments # hello OPTION3 world # LIST3 foo bar # OPTION2 # LIST1 fuz baz # ) # PARSE_ARGUMENTS(ARG "LIST1;LIST2;LIST3" "OPTION1;OPTION2;OPTION3" ${arguments}) # # results in 7 distinct variables: # * ARG_DEFAULT_ARGS: hello;world # * ARG_LIST1: fuz;baz # * ARG_LIST2: # * ARG_LIST3: foo;bar # * ARG_OPTION1: FALSE # * ARG_OPTION2: TRUE # * ARG_OPTION3: TRUE # # taken from http://www.cmake.org/Wiki/CMakeMacroParseArguments MACRO(PARSE_ARGUMENTS prefix arg_names option_names) SET(DEFAULT_ARGS) FOREACH(arg_name ${arg_names}) SET(${prefix}_${arg_name}) ENDFOREACH(arg_name) FOREACH(option ${option_names}) SET(${prefix}_${option} FALSE) ENDFOREACH(option) SET(current_arg_name DEFAULT_ARGS) SET(current_arg_list) FOREACH(arg ${ARGN}) SET(larg_names ${arg_names}) LIST(FIND larg_names "${arg}" is_arg_name) IF (is_arg_name GREATER -1) SET(${prefix}_${current_arg_name} ${current_arg_list}) SET(current_arg_name ${arg}) SET(current_arg_list) ELSE (is_arg_name GREATER -1) SET(loption_names ${option_names}) LIST(FIND loption_names "${arg}" is_option) IF (is_option GREATER -1) SET(${prefix}_${arg} TRUE) ELSE (is_option GREATER -1) SET(current_arg_list ${current_arg_list} ${arg}) ENDIF (is_option GREATER -1) ENDIF (is_arg_name GREATER -1) ENDFOREACH(arg) SET(${prefix}_${current_arg_name} ${current_arg_list}) ENDMACRO(PARSE_ARGUMENTS) dbus-cpp-5.0.3/cmake/PrePush.cmake000066400000000000000000000072761407013304700167170ustar00rootroot00000000000000####################################################################### # A convenience target that carries out the following steps: # - Apply astyle to all source files of interest. # - Build & test in a chroot, comparable setup to CI/Autolanding # and ppa builders. Will fail if new files have not been added. # - Build & test for android. # # NOTE: This target is very sensitive to the availability of all # all required dependencies. For that, we prefer to fail the # target if deps are missing to make the problem very visible. # # TODO: # - Wire up the style-check target once we have reached a state # where trunk actually passes the style check. ####################################################################### add_custom_target( pre-push WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} ) ####################################################################### # Add target for running astyle with the correct options # ####################################################################### find_program(ASTYLE_EXECUTABLE astyle) if (ASTYLE_EXECUTABLE) add_custom_target( astyle ${ASTYLE_EXECUTABLE} --style=allman -s4 --indent=spaces=4 --pad-header --align-pointer=type --recursive ${CMAKE_SOURCE_DIR}/include/*.h COMMAND ${ASTYLE_EXECUTABLE} --recursive --style=allman -s4 --indent=spaces=4 --pad-header --align-pointer=type ${CMAKE_SOURCE_DIR}/tests/*.cpp COMMAND ${ASTYLE_EXECUTABLE} --recursive --style=allman -s4 --indent=spaces=4 --pad-header --align-pointer=type ${CMAKE_SOURCE_DIR}/examples/*.h ${CMAKE_CURRENT_SOURCE_DIR}/examples/*.cpp VERBATIM ) endif (ASTYLE_EXECUTABLE) ####################################################################### # Add target for creating a source tarball with bzr export # ####################################################################### add_custom_target( pre-push-source-tarball COMMAND rm -rf pre-push-build-area COMMAND mkdir pre-push-build-area COMMAND bzr export --root pre-push pre-push-build-area/${PROJECT_NAME}_${DBUS_CPP_VERSION_MAJOR}.${DBUS_CPP_VERSION_MAJOR}.${DBUS_CPP_VERSION_MAJOR}.orig.tar.bz2 ${CMAKE_SOURCE_DIR} WORKING_DIRECTORY ${CMAKE_BINARY_DIR} COMMENT "Preparing source tarball for pre-push build & test" ) ####################################################################### # Add target for extracting source tarball for pdebuild # ####################################################################### add_custom_target( extract-pre-push-tarball COMMAND tar -xf {PROJECT_NAME}_${DBUS_CPP_VERSION_MAJOR}.${DBUS_CPP_VERSION_MAJOR}.${DBUS_CPP_VERSION_MAJOR}.orig.tar.bz2 WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/pre-push-build-area VERBATIM ) ####################################################################### # Builds & tests the last committed revision of the current branch # ####################################################################### find_program(PDEBUILD_EXECUTABLE pdebuild) if(NOT PDEBUILD_EXECUTABLE) message(STATUS "pdebuild NOT found, pre-push is going to FAIL") endif() add_custom_target( pdebuild COMMAND ${PDEBUILD_EXECUTABLE} WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/pre-push-build-area/pre-push COMMENT "Building & testing in chroot'd environment" VERBATIM ) ####################################################################### # pdebuild: make tarball -> extract to build area -> pdebuild # # android-build: invoke cross-compile script # ####################################################################### add_dependencies(extract-pre-push-tarball pre-push-source-tarball) add_dependencies(pdebuild extract-pre-push-tarball) add_dependencies(pre-push pdebuild android-build) dbus-cpp-5.0.3/data/000077500000000000000000000000001407013304700141445ustar00rootroot00000000000000dbus-cpp-5.0.3/data/CMakeLists.txt000066400000000000000000000021041407013304700167010ustar00rootroot00000000000000# Copyright © 2013 Canonical Ltd. # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License version 3 as # published by the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # # Authored by: Thomas Voss configure_file( dbus-cpp.pc.in dbus-cpp.pc @ONLY ) install( FILES ${CMAKE_CURRENT_BINARY_DIR}/dbus-cpp.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig ) message(STATUS "Installing session and system bus config files to ${CMAKE_INSTALL_DATAROOTDIR}/dbus-cpp") install( FILES ${CMAKE_CURRENT_SOURCE_DIR}/session.conf ${CMAKE_CURRENT_SOURCE_DIR}/system.conf DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/dbus-cpp/" ) dbus-cpp-5.0.3/data/dbus-cpp.pc.in000066400000000000000000000006171407013304700166160ustar00rootroot00000000000000prefix=@CMAKE_INSTALL_PREFIX@ exec_prefix=${prefix} libdir=${exec_prefix}/lib includedir=${exec_prefix}/include Name: @CMAKE_PROJECT_NAME@ Description: A DBus binding to C++11, relying on generic programming to abstract away from type systems. Version: @DBUS_CPP_VERSION_MAJOR@.@DBUS_CPP_VERSION_MINOR@.@DBUS_CPP_VERSION_PATCH@ Cflags: -I${includedir} Libs: -L${libdir} -ldbus-cpp Requires: dbus-1dbus-cpp-5.0.3/data/session.conf000066400000000000000000000031551407013304700165020ustar00rootroot00000000000000 session unix:tmpdir=/tmp 60000 1000000000 1000000000 1000000000 120000 240000 100000 10000 100000 10000 50000 50000 50000 300000 dbus-cpp-5.0.3/data/system.conf000066400000000000000000000012321407013304700163350ustar00rootroot00000000000000 system unix:tmpdir=/tmp dbus-cpp-5.0.3/debian/000077500000000000000000000000001407013304700144555ustar00rootroot00000000000000dbus-cpp-5.0.3/debian/Jenkinsfile000066400000000000000000000006511407013304700166430ustar00rootroot00000000000000@Library('ubports-build-tools') _ buildAndProvideDebianPackage() // Or if the package consists entirely of arch-independent packages: // (optional optimization, will confuse BlueOcean's live view at build stage) // buildAndProvideDebianPackage(/* isArchIndependent */ true) // Optionally, to skip building on some architectures (amd64 is always built): // buildAndProvideDebianPackage(false, /* ignoredArchs */ ['arm64']) dbus-cpp-5.0.3/debian/changelog000066400000000000000000000361151407013304700163350ustar00rootroot00000000000000dbus-cpp (5.0.3) UNRELEASED; urgency=medium * Release version 5.0.3. -- Rodney Dawes Fri, 11 Jun 2021 13:32:58 -0400 dbus-cpp (5.0.1+ubports) bionic; urgency=medium * Imported to UBports -- UBports auto importer Mon, 09 Apr 2018 14:49:45 +0200 dbus-cpp (5.0.0+18.04.20171031-0ubuntu1) bionic; urgency=medium [ Łukasz 'sil2100' Zemczak ] * Fix FTBFS on bionic by switching to use cmake-extras and not enforcing -pedantic anymore as current gtest macros do not follow strict standards anymore. -- Łukasz Zemczak Tue, 31 Oct 2017 19:11:23 +0000 dbus-cpp (5.0.0+16.10.20160809-0ubuntu1) yakkety; urgency=medium * Fix signal emission on dbus::ServiceWatcher. -- Thomas Voß Tue, 09 Aug 2016 07:31:30 +0000 dbus-cpp (5.0.0+15.10.20151021.1-0ubuntu1) wily; urgency=medium [ CI Train Bot ] * No-change rebuild. -- Thomas Voß Wed, 21 Oct 2015 08:00:51 +0000 dbus-cpp (5.0.0-0ubuntu3) wily; urgency=medium * Bump revision as the archive has 5.0.0-0ubuntu2 -- Thomas Voß Tue, 20 Oct 2015 17:03:52 +0200 dbus-cpp (5.0.0) wily; urgency=medium * Bump major revision to account for toolchain update. Fixes LP:#1452322 -- Thomas Voß Tue, 21 Jul 2015 12:36:46 +0200 dbus-cpp (4.3.0+15.04.20160114.2-0ubuntu1) vivid; urgency=medium [ CI Train Bot ] * debian/libdbus-cpp4.symbols.32bit: update to released version. * debian/libdbus-cpp4.symbols.64bit: update to released version. [ Thomas Voß ] * Add a proper operator<< for dbus::Message::Type. (LP: #1524131) -- Thomas Voß Thu, 14 Jan 2016 21:51:19 +0000 dbus-cpp (4.3.0+15.04.20160112-0ubuntu1) vivid; urgency=medium * Only run dbus_shutdown if explicitly requested by env var. (LP: #1422304, #1526877) -- Thomas Voß Tue, 12 Jan 2016 16:28:02 +0000 dbus-cpp (4.3.0+15.04.20151126-0ubuntu1) vivid; urgency=medium [ CI Train Bot ] * New rebuild forced. [ Thomas Voß ] * Ensure that Signal with non-void argument types correctly narrow their match rules. (LP: #1480877) -- Thomas Voß Thu, 26 Nov 2015 07:31:37 +0000 dbus-cpp (4.3.0+15.04.20151023-0ubuntu1) vivid; urgency=medium [ CI Train Bot ] * New rebuild forced. [ Thomas Voß ] * Do not cache emitted values for stub signals. (LP: #1509285) -- Jim Hodapp Fri, 23 Oct 2015 10:01:27 +0000 dbus-cpp (4.3.0+15.04.20151020-0ubuntu1) vivid; urgency=medium [ Manuel de la Pena ] * Ensure that the signals are correctly emitted for when the services appear and go. -- Thomas Voß Tue, 20 Oct 2015 10:55:11 +0000 dbus-cpp (4.3.0+15.04.20150505-0ubuntu1) vivid; urgency=medium [ CI Train Bot ] * debian/libdbus-cpp4.symbols.32bit: update to released version. * debian/libdbus-cpp4.symbols.64bit: update to released version. [ Thomas Voß ] * core::dbus::Fixture: Provide access to the address of the spawned session/system bus instances. -- CI Train Bot Tue, 05 May 2015 08:24:49 +0000 dbus-cpp (4.3.0+15.04.20150415-0ubuntu1) vivid; urgency=medium [ Thomas Voß ] * DBus daemon lives in /usr/bin now. -- CI Train Bot Wed, 15 Apr 2015 09:51:18 +0000 dbus-cpp (4.3.0+15.04.20150123-0ubuntu1) vivid; urgency=low [ thomas-voss ] * We ref on construction, so decrement the ref count by 1 to 1 prior to returning. (LP: #1396985) -- Ubuntu daily release Fri, 23 Jan 2015 09:56:06 +0000 dbus-cpp (4.3.0+15.04.20141110-0ubuntu1) vivid; urgency=medium [ Thomas Voss ] * Ensure Signal::~Signal is exception safe. -- Ubuntu daily release Mon, 10 Nov 2014 12:31:09 +0000 dbus-cpp (4.2.0+15.04.20141105-0ubuntu1) vivid; urgency=medium [ Thomas Voss ] * Make core::dbus::Signal::~Signal respect the noexcept guarantee. -- Ubuntu daily release Wed, 05 Nov 2014 07:51:06 +0000 dbus-cpp (4.1.0+15.04.20141104-0ubuntu1) vivid; urgency=low * New rebuild forced -- Ubuntu daily release Tue, 04 Nov 2014 04:23:34 +0000 dbus-cpp (4.1.0+14.10.20141031~rtm-0ubuntu1) 14.09; urgency=low [ thomas-voss ] * Relax timeout on org.freedesktop.Properties::{GetAll, Get, Set}. with timeout set to 30 sec (LP: #1361642) [ Kevin Gunn ] * Relax timeout on org.freedesktop.Properties::{GetAll, Get, Set}. with timeout set to 30 sec (LP: #1361642) -- Ubuntu daily release Fri, 31 Oct 2014 07:51:25 +0000 dbus-cpp (4.1.0+14.10.20141030~rtm-0ubuntu1) 14.09; urgency=medium [ Thomas Voss ] * Ensure that dead objects are correctly cleaning up their connections to the signal router. * Robustify against dangling objects. -- Ubuntu daily release Thu, 30 Oct 2014 14:01:09 +0000 dbus-cpp (4.0.0+14.10.20141006-0ubuntu1) utopic; urgency=low [ thomas-voss ] * Fix another race when setting up a pending call notification on another thread than the one driving the event loop. Introduce an option to enable sanitizers. -- Ubuntu daily release Mon, 06 Oct 2014 15:55:53 +0000 dbus-cpp (4.0.0+14.10.20141002.1-0ubuntu1) utopic; urgency=low [ thomas-voss ] * Always unref pending calls, add load test to ensure correct behavior. Make sure that timeouts are never notified after destruction. (LP: #1367836) -- Ubuntu daily release Thu, 02 Oct 2014 20:49:03 +0000 dbus-cpp (4.0.0+14.10.20140917-0ubuntu1) utopic; urgency=low [ thomas-voss ] * Factor out dbus-specific environment variable names into compile- time constants. Make sure that environment variables are unset prior to setting. -- Ubuntu daily release Wed, 17 Sep 2014 11:47:45 +0000 dbus-cpp (4.0.0+14.10.20140909-0ubuntu1) utopic; urgency=low [ thomas-voss ] * Make sure that signature for int64 types is calculated correctly. -- Ubuntu daily release Tue, 09 Sep 2014 18:31:44 +0000 dbus-cpp (4.0.0+14.10.20140808-0ubuntu1) utopic; urgency=low [ thomas-voss ] * Ensure that property changed signals are only subscribed to once. -- Ubuntu daily release Fri, 08 Aug 2014 02:05:51 +0000 dbus-cpp (4.0.0+14.10.20140730-0ubuntu1) utopic; urgency=low [ Ubuntu daily release ] * debian/libdbus-cpp4.symbols.32bit: auto-update to released version * debian/libdbus-cpp4.symbols.64bit: auto-update to released version [ thomas-voss ] * Make sure that dbus daemon instances fired up for testing are torn down after a configurable timeout. (LP: #1326200) * Make sure that core::dbus::Service::Service(...) interprets return values of dbus_bus_request_name correctly. (LP: #1329211) -- Ubuntu daily release Wed, 30 Jul 2014 16:12:30 +0000 dbus-cpp (4.0.0+14.10.20140718-0ubuntu2) utopic; urgency=medium * No-change rebuild to get dbgsyms for all binaries onto ddebs.ubuntu.com -- Steve Langasek Thu, 24 Jul 2014 12:12:39 -0700 dbus-cpp (4.0.0+14.10.20140718-0ubuntu1) utopic; urgency=medium [ Thomas Voß ] * Bump major revision and so name to account for toolchain update. -- Ubuntu daily release Fri, 18 Jul 2014 12:24:18 +0000 dbus-cpp (3.1.0+14.10.20140716.1-0ubuntu1) utopic; urgency=medium [ Thomas Voß ] * Bumping revision to force build-dependency. -- Ubuntu daily release Wed, 16 Jul 2014 20:19:01 +0000 dbus-cpp (3.1.0+14.10.20140711-0ubuntu1) utopic; urgency=medium [ Manuel de la Pena ] * Provide a new make_executor method to allow to pass the io_service. [ Ubuntu daily release ] * debian/*symbols: auto-update new symbols to released version -- Ubuntu daily release Fri, 11 Jul 2014 13:53:03 +0000 dbus-cpp (3.0.0+14.10.20140709.2-0ubuntu1) utopic; urgency=low [ Ubuntu daily release ] * New rebuild forced [ Antti Kaijanmäki ] * Fix read-only property PropertiesChanged updates. (LP: #1339589) -- Ubuntu daily release Wed, 09 Jul 2014 10:15:33 +0000 dbus-cpp (3.0.0+14.10.20140612-0ubuntu1) utopic; urgency=low [ Manuel de la Peña ] * Provide useful macros to be used by developers so that less code has to be written to define methods, properties and signals. -- Ubuntu daily release Thu, 12 Jun 2014 11:08:49 +0000 dbus-cpp (3.0.0+14.10.20140604-0ubuntu1) utopic; urgency=low [ Jussi Pakkanen ] * Remove unnecessary std::moves in return statements. -- Ubuntu daily release Wed, 04 Jun 2014 07:29:10 +0000 dbus-cpp (3.0.0+14.10.20140507-0ubuntu1) utopic; urgency=medium [ Thomas Voß ] * Version bump, switching to GCC 4.8. [ Ubuntu daily release ] * New rebuild forced -- Ubuntu daily release Wed, 07 May 2014 09:54:12 +0000 dbus-cpp (2.0.0+14.04.20140326-0ubuntu1) trusty; urgency=low * New rebuild forced -- Ubuntu daily release Wed, 26 Mar 2014 18:03:49 +0000 dbus-cpp (2.0.0+14.04.20140322-0ubuntu1) trusty; urgency=low [ CI bot ] * Resync trunk [ Robert Bruce Park ] * Do not build-dep explicitly on specific g++ version for ppc64-el. [ thomas-voss ] * Do not build-dep explicitly on specific g++ version for ppc64-el. -- Ubuntu daily release Sat, 22 Mar 2014 09:42:35 +0000 dbus-cpp (2.0.0+14.04.20140310-0ubuntu1) trusty; urgency=medium [ Pete Woods ] * Change the way signals register match rules -> ABI version bump * Mark symbols that only appear when built under Jenkins as optional. [ Ubuntu daily release ] * debian/*symbols: auto-update new symbols to released version * New rebuild forced [ thomas-voss ] * Make sure that signals call about_to_be_destroyed. Make core::dbus::Signal report that it is about to be destructed. Add a thread-safe lifetime constrained object cache & accompanying tests. * Add dbus as runtime dependency for libdbus-cpp-dev. (LP: #1272191) * Don't exit on dbus connection close. * Remove local versions of cross-process-sync and fork-and-run. * Switch to release build type for production builds. * Small adjustments to the symbols file. * Try to create symbols files for each architecture, not caring for too much redundancy. It's really hard to maintain those otherwise. * Add a test for racyness and provide an alternative to _and_block. [ Antti Kaijanmäki ] * Fix stack corruption in core::dbus::Message::pop_boolean(). * Fix Signal::emit(). * Fix deadlock in MessageRouter. [ Łukasz 'sil2100' Zemczak ] * Try to create symbols files for each architecture, not caring for too much redundancy. It's really hard to maintain those otherwise. -- Ubuntu daily release Mon, 10 Mar 2014 09:20:09 +0000 dbus-cpp (1.0.0+14.04.20140123.1-0ubuntu1) trusty; urgency=medium [ Thomas Voß ] * Force compilation against GCC 4.7. Account for toolchain differences. [ Łukasz 'sil2100' Zemczak ] * Drop symbols file as a last minute decision. The ABI is not stable and different between architectures. This change won't be merged in trunk. shlibs -V is used in the meantime. -- Lukasz 'sil2100' Zemczak Wed, 05 Feb 2014 13:42:44 +0000 dbus-cpp (1.0.0+14.04.20140123-0ubuntu1) trusty; urgency=low [ Thomas Voß ] * Manual version bump. [ Ubuntu daily release ] * debian/*symbols: auto-update new symbols to released version [ thomas-voss ] * Update fork_and_run method ensuring that the test process does not get corrupted. Fix emission of signals carrying values. Remove duplicate setup of message handler for get and set on property. * Fix property handling. Fix pkgconfig setup to make sure that clients of the library correctly link to it. * Add fixture for testing purposes. * Fix map decoding. * Make sure that the map is cleared initially. * Make sure that expectations not being met fails cross-process test cases. Add a class SigTermCatcher to ease cross-process testing. * Add operator!= for types::ObjectPath. * Fix signal creation to always return unique instances. Add test case to prevent from regressions. * Clean up patch and augment test case. Refactor Variant to rely on an encoder and decoder functor. * Switch type for ArgumentType::byte to std::uint8_t as per DBus spec. (LP: #1270843) * Add test-cases for same object, same interface, different & same member signals. * Add sender to match rule for event filtering. * Add a thread-safe lifetime constrained object cache & accompanying tests. * Fix paths to default system and session bus config files. [ Antti Kaijanmäki ] * Add Object::path() to get the ObjectPath for an Object. * Fix signal creation to always return unique instances. Add test case to prevent from regressions. [ Łukasz 'sil2100' Zemczak ] * Merge all symbols file into one file with arch-conditional symbols in it. It should be good this way. [ Ubuntu daily release ] * Automatic snapshot from revision 31 -- Ubuntu daily release Thu, 23 Jan 2014 15:53:27 +0000 dbus-cpp (0.0.1+13.10.20130904-0ubuntu2) trusty; urgency=low * No change rebuild for Boost 1.54 transition. -- Dmitrijs Ledkovs Mon, 21 Oct 2013 14:52:42 +0100 dbus-cpp (0.0.1+13.10.20130904-0ubuntu1) saucy; urgency=low [ thomas-voss ] * Drop lcov dependency. (LP: #1218896) [ Ubuntu daily release ] * Automatic snapshot from revision 12 -- Ubuntu daily release Wed, 04 Sep 2013 02:32:09 +0000 dbus-cpp (0.0.1daily13.06.18-0ubuntu1) saucy; urgency=low * Automatic snapshot from revision 10 -- Ubuntu daily release Tue, 18 Jun 2013 02:02:20 +0000 dbus-cpp (0.0.1daily13.06.17-0ubuntu1) saucy; urgency=low * Automatic snapshot from revision 9 -- Ubuntu daily release Mon, 17 Jun 2013 02:02:03 +0000 dbus-cpp (0.0.1daily13.06.14.1-0ubuntu1) saucy; urgency=low [ Łukasz 'sil2100' Zemczak ] * debian/rules, debian/control, debian/compat, debian/copyright: - Modifications related to compliance with our packaging standards * Disable tests during build for powerpc, as those are currently broken * Automatic snapshot from revision 5 (bootstrap) [ Timo Jyrinki ] * Add copyright headers, fix lintian errors, use @ubuntu.com maintainer address, enable multi-arch. [ Ubuntu daily release ] * Automatic snapshot from revision 8 -- Ubuntu daily release Fri, 14 Jun 2013 15:25:24 +0000 dbus-cpp (0.0.1-0ubuntu1) raring; urgency=low * Initial release -- Thomas Voß Mon, 06 May 2013 11:43:05 +0200 dbus-cpp-5.0.3/debian/compat000066400000000000000000000000021407013304700156530ustar00rootroot000000000000009 dbus-cpp-5.0.3/debian/control000066400000000000000000000044161407013304700160650ustar00rootroot00000000000000Source: dbus-cpp Priority: optional Maintainer: UBports Foundation Build-Depends: cmake, cmake-extras, dbus, debhelper (>= 9), doxygen, google-mock, libboost-filesystem-dev, libboost-system-dev, libboost-program-options-dev, libdbus-1-dev, libgtest-dev, libprocess-cpp-dev, libproperties-cpp-dev, libxml2-dev, lsb-release, Standards-Version: 3.9.5 Section: libs Homepage: https://gitlab.com/ubports/core/lib-cpp/dbus-cpp Vcs-Browser: https://gitlab.com/ubports/core/lib-cpp/dbus-cpp/-/tree/main Package: libdbus-cpp5 Section: libdevel Architecture: any Multi-Arch: same Depends: ${misc:Depends}, ${shlibs:Depends}, Description: header-only dbus-binding leveraging C++-11 A header-only dbus-binding leveraging C++-11, relying on compile-time polymorphism to integrate with arbitrary type systems. Runtime portions to bind to different event loops. Package: dbus-cpp-bin Section: libdevel Architecture: any Multi-Arch: foreign Depends: ${misc:Depends}, ${shlibs:Depends}, libdbus-cpp5 (= ${binary:Version}) Description: header-only dbus-binding leveraging C++-11 Protocol compiler and generator to automatically generate protocol headers from introspection XML. Package: libdbus-cpp-dev Section: libdevel Architecture: any Multi-Arch: same Depends: ${misc:Depends}, ${shlibs:Depends}, dbus, libboost-dev, libdbus-1-dev, libdbus-cpp5 (= ${binary:Version}), libproperties-cpp-dev, Replaces: dbus-cpp-dev Conflicts: dbus-cpp-dev Provides: dbus-cpp-dev Description: header-only dbus-binding leveraging C++-11 A header-only dbus-binding leveraging C++-11, relying on compile-time polymorphism to integrate with arbitrary type systems. Package: dbus-cpp-dev-examples Section: x11 Architecture: any Multi-Arch: same Depends: ${misc:Depends}, ${shlibs:Depends}, Description: header-only dbus-binding leveraging C++-11, example binaries A header-only dbus-binding leveraging C++-11, relying on compile-time polymorphism to integrate with arbitrary type systems. . This package provides examples. dbus-cpp-5.0.3/debian/copyright000066400000000000000000000026701407013304700164150ustar00rootroot00000000000000Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ Upstream-Name: dbus-cpp Source: http://launchpad.net/dbus-cpp Files: cmake/* Copyright: 2010-2011 Johannes Wienke License: GPL-2+ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. . This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. . On Debian systems, the full text of the GNU General Public License version 2 can be found in the file `/usr/share/common-licenses/GPL-2'. Files: * Copyright: 2013 Canonical Ltd. License: LGPL-3 This program is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License version 3 as published by the Free Software Foundation. . This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. . On Debian systems, the full text of the GNU Lesser General Public License version 3 can be found in the file `/usr/share/common-licenses/LGPL-3'. dbus-cpp-5.0.3/debian/dbus-cpp-bin.install000066400000000000000000000000121407013304700203210ustar00rootroot00000000000000usr/bin/* dbus-cpp-5.0.3/debian/dbus-cpp-dev-examples.install000066400000000000000000000000361407013304700221510ustar00rootroot00000000000000usr/lib/*/dbus-cpp/examples/* dbus-cpp-5.0.3/debian/libdbus-cpp-dev.install000066400000000000000000000001341407013304700210230ustar00rootroot00000000000000usr/include/* usr/lib/*/libdbus-cpp.so usr/lib/*/pkgconfig/dbus-cpp.pc usr/share/dbus-cpp/* dbus-cpp-5.0.3/debian/libdbus-cpp5.install000066400000000000000000000000331407013304700203320ustar00rootroot00000000000000usr/lib/*/libdbus-cpp.so.* dbus-cpp-5.0.3/debian/rules000077500000000000000000000005121407013304700155330ustar00rootroot00000000000000#!/usr/bin/make -f # -*- makefile -*- # Uncomment this to turn on verbose mode. export DH_VERBOSE=1 include /usr/share/dpkg/default.mk export DPKG_GENSYMBOLS_CHECK_LEVEL=4 %: dh $@ --parallel --fail-missing override_dh_auto_configure: dh_auto_configure -- -DCMAKE_INSTALL_LIBEXECDIR=/usr/lib/$(DEB_HOST_MULTIARCH)/dbus-cpp dbus-cpp-5.0.3/doc/000077500000000000000000000000001407013304700140005ustar00rootroot00000000000000dbus-cpp-5.0.3/doc/CMakeLists.txt000066400000000000000000000024601407013304700165420ustar00rootroot00000000000000# Copyright © 2013 Canonical Ltd. # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License version 3 as # published by the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # # Authored by: Thomas Voss option( DBUS_CPP_ENABLE_DOC_GENERATION "Generate package documentation with doxygen" OFF ) if (DBUS_CPP_ENABLE_DOC_GENERATION) find_package(Doxygen) if (DOXYGEN_FOUND) configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile @ONLY) add_custom_target(doc ALL ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} COMMENT "Generating API documentation with Doxygen" VERBATIM) install( DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/html DESTINATION share/${CMAKE_PROJECT_NAME}/doc) endif (DOXYGEN_FOUND) endif (DBUS_CPP_ENABLE_DOC_GENERATION) dbus-cpp-5.0.3/doc/Doxyfile.in000066400000000000000000002345511407013304700161250ustar00rootroot00000000000000# Doxyfile 1.8.3.1 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project. # # All text after a hash (#) is considered a comment and will be ignored. # The format is: # TAG = value [value, ...] # For lists items can also be appended using: # TAG += value [value, ...] # Values that contain spaces should be placed between quotes (" "). #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- # This tag specifies the encoding used for all characters in the config file # that follow. The default is UTF-8 which is also the encoding used for all # text before the first occurrence of this tag. Doxygen uses libiconv (or the # iconv built into libc) for the transcoding. See # http://www.gnu.org/software/libiconv for the list of possible encodings. DOXYFILE_ENCODING = UTF-8 # The PROJECT_NAME tag is a single word (or sequence of words) that should # identify the project. Note that if you do not use Doxywizard you need # to put quotes around the project name if it contains spaces. PROJECT_NAME = @CMAKE_PROJECT_NAME@ # The PROJECT_NUMBER tag can be used to enter a project or revision number. # This could be handy for archiving the generated documentation or # if some version control system is used. PROJECT_NUMBER = @DBUS_CPP_VERSION_MAJOR@.@DBUS_CPP_VERSION_MINOR@.@DBUS_CPP_VERSION_PATCH@ # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer # a quick idea about the purpose of the project. Keep the description short. PROJECT_BRIEF = "A simple convenience library for using DBus in C++11." # With the PROJECT_LOGO tag one can specify an logo or icon that is # included in the documentation. The maximum height of the logo should not # exceed 55 pixels and the maximum width should not exceed 200 pixels. # Doxygen will copy the logo to the output directory. PROJECT_LOGO = # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) # base path where the generated documentation will be put. # If a relative path is entered, it will be relative to the location # where doxygen was started. If left blank the current directory will be used. OUTPUT_DIRECTORY = # If the CREATE_SUBDIRS tag is set to YES, then doxygen will create # 4096 sub-directories (in 2 levels) under the output directory of each output # format and will distribute the generated files over these directories. # Enabling this option can be useful when feeding doxygen a huge amount of # source files, where putting all generated files in the same directory would # otherwise cause performance problems for the file system. CREATE_SUBDIRS = NO # The OUTPUT_LANGUAGE tag is used to specify the language in which all # documentation generated by doxygen is written. Doxygen will use this # information to generate all constant output in the proper language. # The default language is English, other supported languages are: # Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, # Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German, # Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English # messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, # Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak, # Slovene, Spanish, Swedish, Ukrainian, and Vietnamese. OUTPUT_LANGUAGE = English # If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will # include brief member descriptions after the members that are listed in # the file and class documentation (similar to JavaDoc). # Set to NO to disable this. BRIEF_MEMBER_DESC = YES # If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend # the brief description of a member or function before the detailed description. # Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the # brief descriptions will be completely suppressed. REPEAT_BRIEF = YES # This tag implements a quasi-intelligent brief description abbreviator # that is used to form the text in various listings. Each string # in this list, if found as the leading text of the brief description, will be # stripped from the text and the result after processing the whole list, is # used as the annotated text. Otherwise, the brief description is used as-is. # If left blank, the following values are used ("$name" is automatically # replaced with the name of the entity): "The $name class" "The $name widget" # "The $name file" "is" "provides" "specifies" "contains" # "represents" "a" "an" "the" ABBREVIATE_BRIEF = # If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then # Doxygen will generate a detailed section even if there is only a brief # description. ALWAYS_DETAILED_SEC = NO # If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all # inherited members of a class in the documentation of that class as if those # members were ordinary class members. Constructors, destructors and assignment # operators of the base classes will not be shown. INLINE_INHERITED_MEMB = NO # If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full # path before files name in the file list and in the header files. If set # to NO the shortest path that makes the file name unique will be used. FULL_PATH_NAMES = YES # If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag # can be used to strip a user-defined part of the path. Stripping is # only done if one of the specified strings matches the left-hand part of # the path. The tag can be used to show relative paths in the file list. # If left blank the directory from which doxygen is run is used as the # path to strip. Note that you specify absolute paths here, but also # relative paths, which will be relative from the directory where doxygen is # started. STRIP_FROM_PATH = # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of # the path mentioned in the documentation of a class, which tells # the reader which header file to include in order to use a class. # If left blank only the name of the header file containing the class # definition is used. Otherwise one should specify the include paths that # are normally passed to the compiler using the -I flag. STRIP_FROM_INC_PATH = # If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter # (but less readable) file names. This can be useful if your file system # doesn't support long names like on DOS, Mac, or CD-ROM. SHORT_NAMES = NO # If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen # will interpret the first line (until the first dot) of a JavaDoc-style # comment as the brief description. If set to NO, the JavaDoc # comments will behave just like regular Qt-style comments # (thus requiring an explicit @brief command for a brief description.) JAVADOC_AUTOBRIEF = NO # If the QT_AUTOBRIEF tag is set to YES then Doxygen will # interpret the first line (until the first dot) of a Qt-style # comment as the brief description. If set to NO, the comments # will behave just like regular Qt-style comments (thus requiring # an explicit \brief command for a brief description.) QT_AUTOBRIEF = NO # The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen # treat a multi-line C++ special comment block (i.e. a block of //! or /// # comments) as a brief description. This used to be the default behaviour. # The new default is to treat a multi-line C++ comment block as a detailed # description. Set this tag to YES if you prefer the old behaviour instead. MULTILINE_CPP_IS_BRIEF = NO # If the INHERIT_DOCS tag is set to YES (the default) then an undocumented # member inherits the documentation from any documented member that it # re-implements. INHERIT_DOCS = YES # If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce # a new page for each member. If set to NO, the documentation of a member will # be part of the file/class/namespace that contains it. SEPARATE_MEMBER_PAGES = NO # The TAB_SIZE tag can be used to set the number of spaces in a tab. # Doxygen uses this value to replace tabs by spaces in code fragments. TAB_SIZE = 4 # This tag can be used to specify a number of aliases that acts # as commands in the documentation. An alias has the form "name=value". # For example adding "sideeffect=\par Side Effects:\n" will allow you to # put the command \sideeffect (or @sideeffect) in the documentation, which # will result in a user-defined paragraph with heading "Side Effects:". # You can put \n's in the value part of an alias to insert newlines. ALIASES = # This tag can be used to specify a number of word-keyword mappings (TCL only). # A mapping has the form "name=value". For example adding # "class=itcl::class" will allow you to use the command class in the # itcl::class meaning. TCL_SUBST = # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C # sources only. Doxygen will then generate output that is more tailored for C. # For instance, some of the names that are used will be different. The list # of all members will be omitted, etc. OPTIMIZE_OUTPUT_FOR_C = NO # Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java # sources only. Doxygen will then generate output that is more tailored for # Java. For instance, namespaces will be presented as packages, qualified # scopes will look different, etc. OPTIMIZE_OUTPUT_JAVA = NO # Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran # sources only. Doxygen will then generate output that is more tailored for # Fortran. OPTIMIZE_FOR_FORTRAN = NO # Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL # sources. Doxygen will then generate output that is tailored for # VHDL. OPTIMIZE_OUTPUT_VHDL = NO # Doxygen selects the parser to use depending on the extension of the files it # parses. With this tag you can assign which parser to use for a given # extension. Doxygen has a built-in mapping, but you can override or extend it # using this tag. The format is ext=language, where ext is a file extension, # and language is one of the parsers supported by doxygen: IDL, Java, # Javascript, CSharp, C, C++, D, PHP, Objective-C, Python, Fortran, VHDL, C, # C++. For instance to make doxygen treat .inc files as Fortran files (default # is PHP), and .f files as C (default is Fortran), use: inc=Fortran f=C. Note # that for custom extensions you also need to set FILE_PATTERNS otherwise the # files are not read by doxygen. EXTENSION_MAPPING = # If MARKDOWN_SUPPORT is enabled (the default) then doxygen pre-processes all # comments according to the Markdown format, which allows for more readable # documentation. See http://daringfireball.net/projects/markdown/ for details. # The output of markdown processing is further processed by doxygen, so you # can mix doxygen, HTML, and XML commands with Markdown formatting. # Disable only in case of backward compatibilities issues. MARKDOWN_SUPPORT = YES # When enabled doxygen tries to link words that correspond to documented classes, # or namespaces to their corresponding documentation. Such a link can be # prevented in individual cases by by putting a % sign in front of the word or # globally by setting AUTOLINK_SUPPORT to NO. AUTOLINK_SUPPORT = YES # If you use STL classes (i.e. std::string, std::vector, etc.) but do not want # to include (a tag file for) the STL sources as input, then you should # set this tag to YES in order to let doxygen match functions declarations and # definitions whose arguments contain STL classes (e.g. func(std::string); v.s. # func(std::string) {}). This also makes the inheritance and collaboration # diagrams that involve STL classes more complete and accurate. BUILTIN_STL_SUPPORT = YES # If you use Microsoft's C++/CLI language, you should set this option to YES to # enable parsing support. CPP_CLI_SUPPORT = NO # Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. # Doxygen will parse them like normal C++ but will assume all classes use public # instead of private inheritance when no explicit protection keyword is present. SIP_SUPPORT = NO # For Microsoft's IDL there are propget and propput attributes to indicate # getter and setter methods for a property. Setting this option to YES (the # default) will make doxygen replace the get and set methods by a property in # the documentation. This will only work if the methods are indeed getting or # setting a simple type. If this is not the case, or you want to show the # methods anyway, you should set this option to NO. IDL_PROPERTY_SUPPORT = YES # If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC # tag is set to YES, then doxygen will reuse the documentation of the first # member in the group (if any) for the other members of the group. By default # all members of a group must be documented explicitly. DISTRIBUTE_GROUP_DOC = NO # Set the SUBGROUPING tag to YES (the default) to allow class member groups of # the same type (for instance a group of public functions) to be put as a # subgroup of that type (e.g. under the Public Functions section). Set it to # NO to prevent subgrouping. Alternatively, this can be done per class using # the \nosubgrouping command. SUBGROUPING = YES # When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and # unions are shown inside the group in which they are included (e.g. using # @ingroup) instead of on a separate page (for HTML and Man pages) or # section (for LaTeX and RTF). INLINE_GROUPED_CLASSES = NO # When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and # unions with only public data fields will be shown inline in the documentation # of the scope in which they are defined (i.e. file, namespace, or group # documentation), provided this scope is documented. If set to NO (the default), # structs, classes, and unions are shown on a separate page (for HTML and Man # pages) or section (for LaTeX and RTF). INLINE_SIMPLE_STRUCTS = NO # When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum # is documented as struct, union, or enum with the name of the typedef. So # typedef struct TypeS {} TypeT, will appear in the documentation as a struct # with name TypeT. When disabled the typedef will appear as a member of a file, # namespace, or class. And the struct will be named TypeS. This can typically # be useful for C code in case the coding convention dictates that all compound # types are typedef'ed and only the typedef is referenced, never the tag name. TYPEDEF_HIDES_STRUCT = NO # The SYMBOL_CACHE_SIZE determines the size of the internal cache use to # determine which symbols to keep in memory and which to flush to disk. # When the cache is full, less often used symbols will be written to disk. # For small to medium size projects (<1000 input files) the default value is # probably good enough. For larger projects a too small cache size can cause # doxygen to be busy swapping symbols to and from disk most of the time # causing a significant performance penalty. # If the system has enough physical memory increasing the cache will improve the # performance by keeping more symbols in memory. Note that the value works on # a logarithmic scale so increasing the size by one will roughly double the # memory usage. The cache size is given by this formula: # 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, # corresponding to a cache size of 2^16 = 65536 symbols. SYMBOL_CACHE_SIZE = 0 # Similar to the SYMBOL_CACHE_SIZE the size of the symbol lookup cache can be # set using LOOKUP_CACHE_SIZE. This cache is used to resolve symbols given # their name and scope. Since this can be an expensive process and often the # same symbol appear multiple times in the code, doxygen keeps a cache of # pre-resolved symbols. If the cache is too small doxygen will become slower. # If the cache is too large, memory is wasted. The cache size is given by this # formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range is 0..9, the default is 0, # corresponding to a cache size of 2^16 = 65536 symbols. LOOKUP_CACHE_SIZE = 0 #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- # If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in # documentation are documented, even if no documentation was available. # Private class members and static file members will be hidden unless # the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES EXTRACT_ALL = YES # If the EXTRACT_PRIVATE tag is set to YES all private members of a class # will be included in the documentation. EXTRACT_PRIVATE = NO # If the EXTRACT_PACKAGE tag is set to YES all members with package or internal # scope will be included in the documentation. EXTRACT_PACKAGE = NO # If the EXTRACT_STATIC tag is set to YES all static members of a file # will be included in the documentation. EXTRACT_STATIC = NO # If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) # defined locally in source files will be included in the documentation. # If set to NO only classes defined in header files are included. EXTRACT_LOCAL_CLASSES = YES # This flag is only useful for Objective-C code. When set to YES local # methods, which are defined in the implementation section but not in # the interface are included in the documentation. # If set to NO (the default) only methods in the interface are included. EXTRACT_LOCAL_METHODS = NO # If this flag is set to YES, the members of anonymous namespaces will be # extracted and appear in the documentation as a namespace called # 'anonymous_namespace{file}', where file will be replaced with the base # name of the file that contains the anonymous namespace. By default # anonymous namespaces are hidden. EXTRACT_ANON_NSPACES = NO # If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all # undocumented members of documented classes, files or namespaces. # If set to NO (the default) these members will be included in the # various overviews, but no documentation section is generated. # This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_MEMBERS = NO # If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all # undocumented classes that are normally visible in the class hierarchy. # If set to NO (the default) these classes will be included in the various # overviews. This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_CLASSES = NO # If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all # friend (class|struct|union) declarations. # If set to NO (the default) these declarations will be included in the # documentation. HIDE_FRIEND_COMPOUNDS = NO # If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any # documentation blocks found inside the body of a function. # If set to NO (the default) these blocks will be appended to the # function's detailed documentation block. HIDE_IN_BODY_DOCS = NO # The INTERNAL_DOCS tag determines if documentation # that is typed after a \internal command is included. If the tag is set # to NO (the default) then the documentation will be excluded. # Set it to YES to include the internal documentation. INTERNAL_DOCS = NO # If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate # file names in lower-case letters. If set to YES upper-case letters are also # allowed. This is useful if you have classes or files whose names only differ # in case and if your file system supports case sensitive file names. Windows # and Mac users are advised to set this option to NO. CASE_SENSE_NAMES = YES # If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen # will show members with their full class and namespace scopes in the # documentation. If set to YES the scope will be hidden. HIDE_SCOPE_NAMES = NO # If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen # will put a list of the files that are included by a file in the documentation # of that file. SHOW_INCLUDE_FILES = YES # If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen # will list include files with double quotes in the documentation # rather than with sharp brackets. FORCE_LOCAL_INCLUDES = NO # If the INLINE_INFO tag is set to YES (the default) then a tag [inline] # is inserted in the documentation for inline members. INLINE_INFO = YES # If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen # will sort the (detailed) documentation of file and class members # alphabetically by member name. If set to NO the members will appear in # declaration order. SORT_MEMBER_DOCS = YES # If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the # brief documentation of file, namespace and class members alphabetically # by member name. If set to NO (the default) the members will appear in # declaration order. SORT_BRIEF_DOCS = NO # If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen # will sort the (brief and detailed) documentation of class members so that # constructors and destructors are listed first. If set to NO (the default) # the constructors will appear in the respective orders defined by # SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. # This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO # and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO. SORT_MEMBERS_CTORS_1ST = NO # If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the # hierarchy of group names into alphabetical order. If set to NO (the default) # the group names will appear in their defined order. SORT_GROUP_NAMES = NO # If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be # sorted by fully-qualified names, including namespaces. If set to # NO (the default), the class list will be sorted only by class name, # not including the namespace part. # Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. # Note: This option applies only to the class list, not to the # alphabetical list. SORT_BY_SCOPE_NAME = NO # If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to # do proper type resolution of all parameters of a function it will reject a # match between the prototype and the implementation of a member function even # if there is only one candidate or it is obvious which candidate to choose # by doing a simple string match. By disabling STRICT_PROTO_MATCHING doxygen # will still accept a match between prototype and implementation in such cases. STRICT_PROTO_MATCHING = NO # The GENERATE_TODOLIST tag can be used to enable (YES) or # disable (NO) the todo list. This list is created by putting \todo # commands in the documentation. GENERATE_TODOLIST = YES # The GENERATE_TESTLIST tag can be used to enable (YES) or # disable (NO) the test list. This list is created by putting \test # commands in the documentation. GENERATE_TESTLIST = YES # The GENERATE_BUGLIST tag can be used to enable (YES) or # disable (NO) the bug list. This list is created by putting \bug # commands in the documentation. GENERATE_BUGLIST = YES # The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or # disable (NO) the deprecated list. This list is created by putting # \deprecated commands in the documentation. GENERATE_DEPRECATEDLIST= YES # The ENABLED_SECTIONS tag can be used to enable conditional # documentation sections, marked by \if section-label ... \endif # and \cond section-label ... \endcond blocks. ENABLED_SECTIONS = # The MAX_INITIALIZER_LINES tag determines the maximum number of lines # the initial value of a variable or macro consists of for it to appear in # the documentation. If the initializer consists of more lines than specified # here it will be hidden. Use a value of 0 to hide initializers completely. # The appearance of the initializer of individual variables and macros in the # documentation can be controlled using \showinitializer or \hideinitializer # command in the documentation regardless of this setting. MAX_INITIALIZER_LINES = 30 # Set the SHOW_USED_FILES tag to NO to disable the list of files generated # at the bottom of the documentation of classes and structs. If set to YES the # list will mention the files that were used to generate the documentation. SHOW_USED_FILES = YES # Set the SHOW_FILES tag to NO to disable the generation of the Files page. # This will remove the Files entry from the Quick Index and from the # Folder Tree View (if specified). The default is YES. SHOW_FILES = YES # Set the SHOW_NAMESPACES tag to NO to disable the generation of the # Namespaces page. # This will remove the Namespaces entry from the Quick Index # and from the Folder Tree View (if specified). The default is YES. SHOW_NAMESPACES = YES # The FILE_VERSION_FILTER tag can be used to specify a program or script that # doxygen should invoke to get the current version for each file (typically from # the version control system). Doxygen will invoke the program by executing (via # popen()) the command , where is the value of # the FILE_VERSION_FILTER tag, and is the name of an input file # provided by doxygen. Whatever the program writes to standard output # is used as the file version. See the manual for examples. FILE_VERSION_FILTER = # The LAYOUT_FILE tag can be used to specify a layout file which will be parsed # by doxygen. The layout file controls the global structure of the generated # output files in an output format independent way. To create the layout file # that represents doxygen's defaults, run doxygen with the -l option. # You can optionally specify a file name after the option, if omitted # DoxygenLayout.xml will be used as the name of the layout file. LAYOUT_FILE = # The CITE_BIB_FILES tag can be used to specify one or more bib files # containing the references data. This must be a list of .bib files. The # .bib extension is automatically appended if omitted. Using this command # requires the bibtex tool to be installed. See also # http://en.wikipedia.org/wiki/BibTeX for more info. For LaTeX the style # of the bibliography can be controlled using LATEX_BIB_STYLE. To use this # feature you need bibtex and perl available in the search path. Do not use # file names with spaces, bibtex cannot handle them. CITE_BIB_FILES = #--------------------------------------------------------------------------- # configuration options related to warning and progress messages #--------------------------------------------------------------------------- # The QUIET tag can be used to turn on/off the messages that are generated # by doxygen. Possible values are YES and NO. If left blank NO is used. QUIET = NO # The WARNINGS tag can be used to turn on/off the warning messages that are # generated by doxygen. Possible values are YES and NO. If left blank # NO is used. WARNINGS = YES # If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings # for undocumented members. If EXTRACT_ALL is set to YES then this flag will # automatically be disabled. WARN_IF_UNDOCUMENTED = YES # If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for # potential errors in the documentation, such as not documenting some # parameters in a documented function, or documenting parameters that # don't exist or using markup commands wrongly. WARN_IF_DOC_ERROR = YES # The WARN_NO_PARAMDOC option can be enabled to get warnings for # functions that are documented, but have no documentation for their parameters # or return value. If set to NO (the default) doxygen will only warn about # wrong or incomplete parameter documentation, but not about the absence of # documentation. WARN_NO_PARAMDOC = NO # The WARN_FORMAT tag determines the format of the warning messages that # doxygen can produce. The string should contain the $file, $line, and $text # tags, which will be replaced by the file and line number from which the # warning originated and the warning text. Optionally the format may contain # $version, which will be replaced by the version of the file (if it could # be obtained via FILE_VERSION_FILTER) WARN_FORMAT = "$file:$line: $text" # The WARN_LOGFILE tag can be used to specify a file to which warning # and error messages should be written. If left blank the output is written # to stderr. WARN_LOGFILE = #--------------------------------------------------------------------------- # configuration options related to the input files #--------------------------------------------------------------------------- # The INPUT tag can be used to specify the files and/or directories that contain # documented source files. You may enter file names like "myfile.cpp" or # directories like "/usr/src/myproject". Separate the files or directories # with spaces. INPUT = @CMAKE_CURRENT_SOURCE_DIR@ @CMAKE_CURRENT_SOURCE_DIR@/../include # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is # also the default input encoding. Doxygen uses libiconv (or the iconv built # into libc) for the transcoding. See http://www.gnu.org/software/libiconv for # the list of possible encodings. INPUT_ENCODING = UTF-8 # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank the following patterns are tested: # *.c *.cc *.cxx *.cpp *.c++ *.d *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh # *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py # *.f90 *.f *.for *.vhd *.vhdl FILE_PATTERNS = # The RECURSIVE tag can be used to turn specify whether or not subdirectories # should be searched for input files as well. Possible values are YES and NO. # If left blank NO is used. RECURSIVE = YES # The EXCLUDE tag can be used to specify files and/or directories that should be # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. # Note that relative paths are relative to the directory from which doxygen is # run. EXCLUDE = # The EXCLUDE_SYMLINKS tag can be used to select whether or not files or # directories that are symbolic links (a Unix file system feature) are excluded # from the input. EXCLUDE_SYMLINKS = NO # If the value of the INPUT tag contains directories, you can use the # EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude # certain files from those directories. Note that the wildcards are matched # against the file with absolute path, so to exclude all test directories # for example use the pattern */test/* EXCLUDE_PATTERNS = # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names # (namespaces, classes, functions, etc.) that should be excluded from the # output. The symbol name can be a fully qualified name, a word, or if the # wildcard * is used, a substring. Examples: ANamespace, AClass, # AClass::ANamespace, ANamespace::*Test EXCLUDE_SYMBOLS = # The EXAMPLE_PATH tag can be used to specify one or more files or # directories that contain example code fragments that are included (see # the \include command). EXAMPLE_PATH = @CMAKE_CURRENT_SOURCE_DIR@/../tests @CMAKE_CURRENT_SOURCE_DIR@/../examples # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank all files are included. EXAMPLE_PATTERNS = # If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be # searched for input files to be used with the \include or \dontinclude # commands irrespective of the value of the RECURSIVE tag. # Possible values are YES and NO. If left blank NO is used. EXAMPLE_RECURSIVE = YES # The IMAGE_PATH tag can be used to specify one or more files or # directories that contain image that are included in the documentation (see # the \image command). IMAGE_PATH = # The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program # by executing (via popen()) the command , where # is the value of the INPUT_FILTER tag, and is the name of an # input file. Doxygen will then use the output that the filter program writes # to standard output. # If FILTER_PATTERNS is specified, this tag will be # ignored. INPUT_FILTER = # The FILTER_PATTERNS tag can be used to specify filters on a per file pattern # basis. # Doxygen will compare the file name with each pattern and apply the # filter if there is a match. # The filters are a list of the form: # pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further # info on how filters are used. If FILTER_PATTERNS is empty or if # non of the patterns match the file name, INPUT_FILTER is applied. FILTER_PATTERNS = # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using # INPUT_FILTER) will be used to filter the input files when producing source # files to browse (i.e. when SOURCE_BROWSER is set to YES). FILTER_SOURCE_FILES = NO # The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file # pattern. A pattern will override the setting for FILTER_PATTERN (if any) # and it is also possible to disable source filtering for a specific pattern # using *.ext= (so without naming a filter). This option only has effect when # FILTER_SOURCE_FILES is enabled. FILTER_SOURCE_PATTERNS = # If the USE_MD_FILE_AS_MAINPAGE tag refers to the name of a markdown file that # is part of the input, its contents will be placed on the main page (index.html). # This can be useful if you have a project on for instance GitHub and want reuse # the introduction page also for the doxygen output. USE_MDFILE_AS_MAINPAGE = @CMAKE_SOURCE_DIR@/README.md #--------------------------------------------------------------------------- # configuration options related to source browsing #--------------------------------------------------------------------------- # If the SOURCE_BROWSER tag is set to YES then a list of source files will # be generated. Documented entities will be cross-referenced with these sources. # Note: To get rid of all source code in the generated output, make sure also # VERBATIM_HEADERS is set to NO. SOURCE_BROWSER = YES # Setting the INLINE_SOURCES tag to YES will include the body # of functions and classes directly in the documentation. INLINE_SOURCES = NO # Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct # doxygen to hide any special comment blocks from generated source code # fragments. Normal C, C++ and Fortran comments will always remain visible. STRIP_CODE_COMMENTS = YES # If the REFERENCED_BY_RELATION tag is set to YES # then for each documented function all documented # functions referencing it will be listed. REFERENCED_BY_RELATION = YES # If the REFERENCES_RELATION tag is set to YES # then for each documented function all documented entities # called/used by that function will be listed. REFERENCES_RELATION = YES # If the REFERENCES_LINK_SOURCE tag is set to YES (the default) # and SOURCE_BROWSER tag is set to YES, then the hyperlinks from # functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will # link to the source code. # Otherwise they will link to the documentation. REFERENCES_LINK_SOURCE = YES # If the USE_HTAGS tag is set to YES then the references to source code # will point to the HTML generated by the htags(1) tool instead of doxygen # built-in source browser. The htags tool is part of GNU's global source # tagging system (see http://www.gnu.org/software/global/global.html). You # will need version 4.8.6 or higher. USE_HTAGS = NO # If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen # will generate a verbatim copy of the header file for each class for # which an include is specified. Set to NO to disable this. VERBATIM_HEADERS = YES #--------------------------------------------------------------------------- # configuration options related to the alphabetical class index #--------------------------------------------------------------------------- # If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index # of all compounds will be generated. Enable this if the project # contains a lot of classes, structs, unions or interfaces. ALPHABETICAL_INDEX = YES # If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then # the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns # in which this list will be split (can be a number in the range [1..20]) COLS_IN_ALPHA_INDEX = 5 # In case all classes in a project start with a common prefix, all # classes will be put under the same header in the alphabetical index. # The IGNORE_PREFIX tag can be used to specify one or more prefixes that # should be ignored while generating the index headers. IGNORE_PREFIX = #--------------------------------------------------------------------------- # configuration options related to the HTML output #--------------------------------------------------------------------------- # If the GENERATE_HTML tag is set to YES (the default) Doxygen will # generate HTML output. GENERATE_HTML = YES # The HTML_OUTPUT tag is used to specify where the HTML docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `html' will be used as the default path. HTML_OUTPUT = html # The HTML_FILE_EXTENSION tag can be used to specify the file extension for # each generated HTML page (for example: .htm,.php,.asp). If it is left blank # doxygen will generate files with .html extension. HTML_FILE_EXTENSION = .html # The HTML_HEADER tag can be used to specify a personal HTML header for # each generated HTML page. If it is left blank doxygen will generate a # standard header. Note that when using a custom header you are responsible # for the proper inclusion of any scripts and style sheets that doxygen # needs, which is dependent on the configuration options used. # It is advised to generate a default header using "doxygen -w html # header.html footer.html stylesheet.css YourConfigFile" and then modify # that header. Note that the header is subject to change so you typically # have to redo this when upgrading to a newer version of doxygen or when # changing the value of configuration settings such as GENERATE_TREEVIEW! HTML_HEADER = # The HTML_FOOTER tag can be used to specify a personal HTML footer for # each generated HTML page. If it is left blank doxygen will generate a # standard footer. HTML_FOOTER = # The HTML_STYLESHEET tag can be used to specify a user-defined cascading # style sheet that is used by each HTML page. It can be used to # fine-tune the look of the HTML output. If left blank doxygen will # generate a default style sheet. Note that it is recommended to use # HTML_EXTRA_STYLESHEET instead of this one, as it is more robust and this # tag will in the future become obsolete. HTML_STYLESHEET = # The HTML_EXTRA_STYLESHEET tag can be used to specify an additional # user-defined cascading style sheet that is included after the standard # style sheets created by doxygen. Using this option one can overrule # certain style aspects. This is preferred over using HTML_STYLESHEET # since it does not replace the standard style sheet and is therefor more # robust against future updates. Doxygen will copy the style sheet file to # the output directory. HTML_EXTRA_STYLESHEET = @CMAKE_CURRENT_SOURCE_DIR@/extra.css # The HTML_EXTRA_FILES tag can be used to specify one or more extra images or # other source files which should be copied to the HTML output directory. Note # that these files will be copied to the base HTML output directory. Use the # $relpath$ marker in the HTML_HEADER and/or HTML_FOOTER files to load these # files. In the HTML_STYLESHEET file, use the file name only. Also note that # the files will be copied as-is; there are no commands or markers available. HTML_EXTRA_FILES = # The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. # Doxygen will adjust the colors in the style sheet and background images # according to this color. Hue is specified as an angle on a colorwheel, # see http://en.wikipedia.org/wiki/Hue for more information. # For instance the value 0 represents red, 60 is yellow, 120 is green, # 180 is cyan, 240 is blue, 300 purple, and 360 is red again. # The allowed range is 0 to 359. HTML_COLORSTYLE_HUE = 220 # The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of # the colors in the HTML output. For a value of 0 the output will use # grayscales only. A value of 255 will produce the most vivid colors. HTML_COLORSTYLE_SAT = 100 # The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to # the luminance component of the colors in the HTML output. Values below # 100 gradually make the output lighter, whereas values above 100 make # the output darker. The value divided by 100 is the actual gamma applied, # so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2, # and 100 does not change the gamma. HTML_COLORSTYLE_GAMMA = 80 # If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML # page will contain the date and time when the page was generated. Setting # this to NO can help when comparing the output of multiple runs. HTML_TIMESTAMP = YES # If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML # documentation will contain sections that can be hidden and shown after the # page has loaded. HTML_DYNAMIC_SECTIONS = YES # With HTML_INDEX_NUM_ENTRIES one can control the preferred number of # entries shown in the various tree structured indices initially; the user # can expand and collapse entries dynamically later on. Doxygen will expand # the tree to such a level that at most the specified number of entries are # visible (unless a fully collapsed tree already exceeds this amount). # So setting the number of entries 1 will produce a full collapsed tree by # default. 0 is a special value representing an infinite number of entries # and will result in a full expanded tree by default. HTML_INDEX_NUM_ENTRIES = 100 # If the GENERATE_DOCSET tag is set to YES, additional index files # will be generated that can be used as input for Apple's Xcode 3 # integrated development environment, introduced with OSX 10.5 (Leopard). # To create a documentation set, doxygen will generate a Makefile in the # HTML output directory. Running make will produce the docset in that # directory and running "make install" will install the docset in # ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find # it at startup. # See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html # for more information. GENERATE_DOCSET = NO # When GENERATE_DOCSET tag is set to YES, this tag determines the name of the # feed. A documentation feed provides an umbrella under which multiple # documentation sets from a single provider (such as a company or product suite) # can be grouped. DOCSET_FEEDNAME = "Doxygen generated docs" # When GENERATE_DOCSET tag is set to YES, this tag specifies a string that # should uniquely identify the documentation set bundle. This should be a # reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen # will append .docset to the name. DOCSET_BUNDLE_ID = org.doxygen.Project # When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely # identify the documentation publisher. This should be a reverse domain-name # style string, e.g. com.mycompany.MyDocSet.documentation. DOCSET_PUBLISHER_ID = org.doxygen.Publisher # The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher. DOCSET_PUBLISHER_NAME = Publisher # If the GENERATE_HTMLHELP tag is set to YES, additional index files # will be generated that can be used as input for tools like the # Microsoft HTML help workshop to generate a compiled HTML help file (.chm) # of the generated HTML documentation. GENERATE_HTMLHELP = NO # If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can # be used to specify the file name of the resulting .chm file. You # can add a path in front of the file if the result should not be # written to the html output directory. CHM_FILE = # If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can # be used to specify the location (absolute path including file name) of # the HTML help compiler (hhc.exe). If non-empty doxygen will try to run # the HTML help compiler on the generated index.hhp. HHC_LOCATION = # If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag # controls if a separate .chi index file is generated (YES) or that # it should be included in the master .chm file (NO). GENERATE_CHI = NO # If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING # is used to encode HtmlHelp index (hhk), content (hhc) and project file # content. CHM_INDEX_ENCODING = # If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag # controls whether a binary table of contents is generated (YES) or a # normal table of contents (NO) in the .chm file. BINARY_TOC = NO # The TOC_EXPAND flag can be set to YES to add extra items for group members # to the contents of the HTML help documentation and to the tree view. TOC_EXPAND = NO # If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and # QHP_VIRTUAL_FOLDER are set, an additional index file will be generated # that can be used as input for Qt's qhelpgenerator to generate a # Qt Compressed Help (.qch) of the generated HTML documentation. GENERATE_QHP = NO # If the QHG_LOCATION tag is specified, the QCH_FILE tag can # be used to specify the file name of the resulting .qch file. # The path specified is relative to the HTML output folder. QCH_FILE = # The QHP_NAMESPACE tag specifies the namespace to use when generating # Qt Help Project output. For more information please see # http://doc.trolltech.com/qthelpproject.html#namespace QHP_NAMESPACE = org.doxygen.Project # The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating # Qt Help Project output. For more information please see # http://doc.trolltech.com/qthelpproject.html#virtual-folders QHP_VIRTUAL_FOLDER = doc # If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to # add. For more information please see # http://doc.trolltech.com/qthelpproject.html#custom-filters QHP_CUST_FILTER_NAME = # The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the # custom filter to add. For more information please see # # Qt Help Project / Custom Filters. QHP_CUST_FILTER_ATTRS = # The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this # project's # filter section matches. # # Qt Help Project / Filter Attributes. QHP_SECT_FILTER_ATTRS = # If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can # be used to specify the location of Qt's qhelpgenerator. # If non-empty doxygen will try to run qhelpgenerator on the generated # .qhp file. QHG_LOCATION = # If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files # will be generated, which together with the HTML files, form an Eclipse help # plugin. To install this plugin and make it available under the help contents # menu in Eclipse, the contents of the directory containing the HTML and XML # files needs to be copied into the plugins directory of eclipse. The name of # the directory within the plugins directory should be the same as # the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before # the help appears. GENERATE_ECLIPSEHELP = NO # A unique identifier for the eclipse help plugin. When installing the plugin # the directory name containing the HTML and XML files should also have # this name. ECLIPSE_DOC_ID = org.doxygen.Project # The DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) # at top of each HTML page. The value NO (the default) enables the index and # the value YES disables it. Since the tabs have the same information as the # navigation tree you can set this option to NO if you already set # GENERATE_TREEVIEW to YES. DISABLE_INDEX = YES # The GENERATE_TREEVIEW tag is used to specify whether a tree-like index # structure should be generated to display hierarchical information. # If the tag value is set to YES, a side panel will be generated # containing a tree-like index structure (just like the one that # is generated for HTML Help). For this to work a browser that supports # JavaScript, DHTML, CSS and frames is required (i.e. any modern browser). # Windows users are probably better off using the HTML help feature. # Since the tree basically has the same information as the tab index you # could consider to set DISABLE_INDEX to NO when enabling this option. GENERATE_TREEVIEW = YES # The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values # (range [0,1..20]) that doxygen will group on one line in the generated HTML # documentation. Note that a value of 0 will completely suppress the enum # values from appearing in the overview section. ENUM_VALUES_PER_LINE = 1 # If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be # used to set the initial width (in pixels) of the frame in which the tree # is shown. TREEVIEW_WIDTH = 250 # When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open # links to external symbols imported via tag files in a separate window. EXT_LINKS_IN_WINDOW = NO # Use this tag to change the font size of Latex formulas included # as images in the HTML documentation. The default is 10. Note that # when you change the font size after a successful doxygen run you need # to manually remove any form_*.png images from the HTML output directory # to force them to be regenerated. FORMULA_FONTSIZE = 10 # Use the FORMULA_TRANPARENT tag to determine whether or not the images # generated for formulas are transparent PNGs. Transparent PNGs are # not supported properly for IE 6.0, but are supported on all modern browsers. # Note that when changing this option you need to delete any form_*.png files # in the HTML output before the changes have effect. FORMULA_TRANSPARENT = YES # Enable the USE_MATHJAX option to render LaTeX formulas using MathJax # (see http://www.mathjax.org) which uses client side Javascript for the # rendering instead of using prerendered bitmaps. Use this if you do not # have LaTeX installed or if you want to formulas look prettier in the HTML # output. When enabled you may also need to install MathJax separately and # configure the path to it using the MATHJAX_RELPATH option. USE_MATHJAX = NO # When MathJax is enabled you can set the default output format to be used for # thA MathJax output. Supported types are HTML-CSS, NativeMML (i.e. MathML) and # SVG. The default value is HTML-CSS, which is slower, but has the best # compatibility. MATHJAX_FORMAT = HTML-CSS # When MathJax is enabled you need to specify the location relative to the # HTML output directory using the MATHJAX_RELPATH option. The destination # directory should contain the MathJax.js script. For instance, if the mathjax # directory is located at the same level as the HTML output directory, then # MATHJAX_RELPATH should be ../mathjax. The default value points to # the MathJax Content Delivery Network so you can quickly see the result without # installing MathJax. # However, it is strongly recommended to install a local # copy of MathJax from http://www.mathjax.org before deployment. MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest # The MATHJAX_EXTENSIONS tag can be used to specify one or MathJax extension # names that should be enabled during MathJax rendering. MATHJAX_EXTENSIONS = # When the SEARCHENGINE tag is enabled doxygen will generate a search box # for the HTML output. The underlying search engine uses javascript # and DHTML and should work on any modern browser. Note that when using # HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets # (GENERATE_DOCSET) there is already a search function so this one should # typically be disabled. For large projects the javascript based search engine # can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution. SEARCHENGINE = NO # When the SERVER_BASED_SEARCH tag is enabled the search engine will be # implemented using a web server instead of a web client using Javascript. # There are two flavours of web server based search depending on the # EXTERNAL_SEARCH setting. When disabled, doxygen will generate a PHP script for # searching and an index file used by the script. When EXTERNAL_SEARCH is # enabled the indexing and searching needs to be provided by external tools. # See the manual for details. SERVER_BASED_SEARCH = NO # When EXTERNAL_SEARCH is enabled doxygen will no longer generate the PHP # script for searching. Instead the search results are written to an XML file # which needs to be processed by an external indexer. Doxygen will invoke an # external search engine pointed to by the SEARCHENGINE_URL option to obtain # the search results. Doxygen ships with an example indexer (doxyindexer) and # search engine (doxysearch.cgi) which are based on the open source search engine # library Xapian. See the manual for configuration details. EXTERNAL_SEARCH = NO # The SEARCHENGINE_URL should point to a search engine hosted by a web server # which will returned the search results when EXTERNAL_SEARCH is enabled. # Doxygen ships with an example search engine (doxysearch) which is based on # the open source search engine library Xapian. See the manual for configuration # details. SEARCHENGINE_URL = # When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed # search data is written to a file for indexing by an external tool. With the # SEARCHDATA_FILE tag the name of this file can be specified. SEARCHDATA_FILE = searchdata.xml # When SERVER_BASED_SEARCH AND EXTERNAL_SEARCH are both enabled the # EXTERNAL_SEARCH_ID tag can be used as an identifier for the project. This is # useful in combination with EXTRA_SEARCH_MAPPINGS to search through multiple # projects and redirect the results back to the right project. EXTERNAL_SEARCH_ID = # The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen # projects other than the one defined by this configuration file, but that are # all added to the same external search index. Each project needs to have a # unique id set via EXTERNAL_SEARCH_ID. The search mapping then maps the id # of to a relative location where the documentation can be found. # The format is: EXTRA_SEARCH_MAPPINGS = id1=loc1 id2=loc2 ... EXTRA_SEARCH_MAPPINGS = #--------------------------------------------------------------------------- # configuration options related to the LaTeX output #--------------------------------------------------------------------------- # If the GENERATE_LATEX tag is set to YES (the default) Doxygen will # generate Latex output. GENERATE_LATEX = NO # The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `latex' will be used as the default path. LATEX_OUTPUT = latex # The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be # invoked. If left blank `latex' will be used as the default command name. # Note that when enabling USE_PDFLATEX this option is only used for # generating bitmaps for formulas in the HTML output, but not in the # Makefile that is written to the output directory. LATEX_CMD_NAME = latex # The MAKEINDEX_CMD_NAME tag can be used to specify the command name to # generate index for LaTeX. If left blank `makeindex' will be used as the # default command name. MAKEINDEX_CMD_NAME = makeindex # If the COMPACT_LATEX tag is set to YES Doxygen generates more compact # LaTeX documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_LATEX = NO # The PAPER_TYPE tag can be used to set the paper type that is used # by the printer. Possible values are: a4, letter, legal and # executive. If left blank a4wide will be used. PAPER_TYPE = a4 # The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX # packages that should be included in the LaTeX output. EXTRA_PACKAGES = # The LATEX_HEADER tag can be used to specify a personal LaTeX header for # the generated latex document. The header should contain everything until # the first chapter. If it is left blank doxygen will generate a # standard header. Notice: only use this tag if you know what you are doing! LATEX_HEADER = # The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for # the generated latex document. The footer should contain everything after # the last chapter. If it is left blank doxygen will generate a # standard footer. Notice: only use this tag if you know what you are doing! LATEX_FOOTER = # If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated # is prepared for conversion to pdf (using ps2pdf). The pdf file will # contain links (just like the HTML output) instead of page references # This makes the output suitable for online browsing using a pdf viewer. PDF_HYPERLINKS = YES # If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of # plain latex in the generated Makefile. Set this option to YES to get a # higher quality PDF documentation. USE_PDFLATEX = YES # If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. # command to the generated LaTeX files. This will instruct LaTeX to keep # running if errors occur, instead of asking the user for help. # This option is also used when generating formulas in HTML. LATEX_BATCHMODE = NO # If LATEX_HIDE_INDICES is set to YES then doxygen will not # include the index chapters (such as File Index, Compound Index, etc.) # in the output. LATEX_HIDE_INDICES = NO # If LATEX_SOURCE_CODE is set to YES then doxygen will include # source code with syntax highlighting in the LaTeX output. # Note that which sources are shown also depends on other settings # such as SOURCE_BROWSER. LATEX_SOURCE_CODE = NO # The LATEX_BIB_STYLE tag can be used to specify the style to use for the # bibliography, e.g. plainnat, or ieeetr. The default style is "plain". See # http://en.wikipedia.org/wiki/BibTeX for more info. LATEX_BIB_STYLE = plain #--------------------------------------------------------------------------- # configuration options related to the RTF output #--------------------------------------------------------------------------- # If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output # The RTF output is optimized for Word 97 and may not look very pretty with # other RTF readers or editors. GENERATE_RTF = NO # The RTF_OUTPUT tag is used to specify where the RTF docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `rtf' will be used as the default path. RTF_OUTPUT = rtf # If the COMPACT_RTF tag is set to YES Doxygen generates more compact # RTF documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_RTF = NO # If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated # will contain hyperlink fields. The RTF file will # contain links (just like the HTML output) instead of page references. # This makes the output suitable for online browsing using WORD or other # programs which support those fields. # Note: wordpad (write) and others do not support links. RTF_HYPERLINKS = NO # Load style sheet definitions from file. Syntax is similar to doxygen's # config file, i.e. a series of assignments. You only have to provide # replacements, missing definitions are set to their default value. RTF_STYLESHEET_FILE = # Set optional variables used in the generation of an rtf document. # Syntax is similar to doxygen's config file. RTF_EXTENSIONS_FILE = #--------------------------------------------------------------------------- # configuration options related to the man page output #--------------------------------------------------------------------------- # If the GENERATE_MAN tag is set to YES (the default) Doxygen will # generate man pages GENERATE_MAN = YES # The MAN_OUTPUT tag is used to specify where the man pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `man' will be used as the default path. MAN_OUTPUT = man # The MAN_EXTENSION tag determines the extension that is added to # the generated man pages (default is the subroutine's section .3) MAN_EXTENSION = .3 # If the MAN_LINKS tag is set to YES and Doxygen generates man output, # then it will generate one additional man file for each entity # documented in the real man page(s). These additional files # only source the real man page, but without them the man command # would be unable to find the correct page. The default is NO. MAN_LINKS = NO #--------------------------------------------------------------------------- # configuration options related to the XML output #--------------------------------------------------------------------------- # If the GENERATE_XML tag is set to YES Doxygen will # generate an XML file that captures the structure of # the code including all documentation. GENERATE_XML = NO # The XML_OUTPUT tag is used to specify where the XML pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `xml' will be used as the default path. XML_OUTPUT = xml # The XML_SCHEMA tag can be used to specify an XML schema, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_SCHEMA = # The XML_DTD tag can be used to specify an XML DTD, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_DTD = # If the XML_PROGRAMLISTING tag is set to YES Doxygen will # dump the program listings (including syntax highlighting # and cross-referencing information) to the XML output. Note that # enabling this will significantly increase the size of the XML output. XML_PROGRAMLISTING = YES #--------------------------------------------------------------------------- # configuration options for the AutoGen Definitions output #--------------------------------------------------------------------------- # If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will # generate an AutoGen Definitions (see autogen.sf.net) file # that captures the structure of the code including all # documentation. Note that this feature is still experimental # and incomplete at the moment. GENERATE_AUTOGEN_DEF = NO #--------------------------------------------------------------------------- # configuration options related to the Perl module output #--------------------------------------------------------------------------- # If the GENERATE_PERLMOD tag is set to YES Doxygen will # generate a Perl module file that captures the structure of # the code including all documentation. Note that this # feature is still experimental and incomplete at the # moment. GENERATE_PERLMOD = NO # If the PERLMOD_LATEX tag is set to YES Doxygen will generate # the necessary Makefile rules, Perl scripts and LaTeX code to be able # to generate PDF and DVI output from the Perl module output. PERLMOD_LATEX = NO # If the PERLMOD_PRETTY tag is set to YES the Perl module output will be # nicely formatted so it can be parsed by a human reader. # This is useful # if you want to understand what is going on. # On the other hand, if this # tag is set to NO the size of the Perl module output will be much smaller # and Perl will parse it just the same. PERLMOD_PRETTY = YES # The names of the make variables in the generated doxyrules.make file # are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. # This is useful so different doxyrules.make files included by the same # Makefile don't overwrite each other's variables. PERLMOD_MAKEVAR_PREFIX = #--------------------------------------------------------------------------- # Configuration options related to the preprocessor #--------------------------------------------------------------------------- # If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will # evaluate all C-preprocessor directives found in the sources and include # files. ENABLE_PREPROCESSING = YES # If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro # names in the source code. If set to NO (the default) only conditional # compilation will be performed. Macro expansion can be done in a controlled # way by setting EXPAND_ONLY_PREDEF to YES. MACRO_EXPANSION = NO # If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES # then the macro expansion is limited to the macros specified with the # PREDEFINED and EXPAND_AS_DEFINED tags. EXPAND_ONLY_PREDEF = NO # If the SEARCH_INCLUDES tag is set to YES (the default) the includes files # pointed to by INCLUDE_PATH will be searched when a #include is found. SEARCH_INCLUDES = YES # The INCLUDE_PATH tag can be used to specify one or more directories that # contain include files that are not input files but should be processed by # the preprocessor. INCLUDE_PATH = # You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard # patterns (like *.h and *.hpp) to filter out the header-files in the # directories. If left blank, the patterns specified with FILE_PATTERNS will # be used. INCLUDE_FILE_PATTERNS = # The PREDEFINED tag can be used to specify one or more macro names that # are defined before the preprocessor is started (similar to the -D option of # gcc). The argument of the tag is a list of macros of the form: name # or name=definition (no spaces). If the definition and the = are # omitted =1 is assumed. To prevent a macro definition from being # undefined via #undef or recursively expanded use the := operator # instead of the = operator. PREDEFINED = # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then # this tag can be used to specify a list of macro names that should be expanded. # The macro definition that is found in the sources will be used. # Use the PREDEFINED tag if you want to use a different macro definition that # overrules the definition found in the source code. EXPAND_AS_DEFINED = # If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then # doxygen's preprocessor will remove all references to function-like macros # that are alone on a line, have an all uppercase name, and do not end with a # semicolon, because these will confuse the parser if not removed. SKIP_FUNCTION_MACROS = YES #--------------------------------------------------------------------------- # Configuration::additions related to external references #--------------------------------------------------------------------------- # The TAGFILES option can be used to specify one or more tagfiles. For each # tag file the location of the external documentation should be added. The # format of a tag file without this location is as follows: # # TAGFILES = file1 file2 ... # Adding location for the tag files is done as follows: # # TAGFILES = file1=loc1 "file2 = loc2" ... # where "loc1" and "loc2" can be relative or absolute paths # or URLs. Note that each tag file must have a unique name (where the name does # NOT include the path). If a tag file is not located in the directory in which # doxygen is run, you must also specify the path to the tagfile here. TAGFILES = # When a file name is specified after GENERATE_TAGFILE, doxygen will create # a tag file that is based on the input files it reads. GENERATE_TAGFILE = # If the ALLEXTERNALS tag is set to YES all external classes will be listed # in the class index. If set to NO only the inherited external classes # will be listed. ALLEXTERNALS = NO # If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed # in the modules index. If set to NO, only the current project's groups will # be listed. EXTERNAL_GROUPS = YES # The PERL_PATH should be the absolute path and name of the perl script # interpreter (i.e. the result of `which perl'). PERL_PATH = /usr/bin/perl #--------------------------------------------------------------------------- # Configuration options related to the dot tool #--------------------------------------------------------------------------- # If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will # generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base # or super classes. Setting the tag to NO turns the diagrams off. Note that # this option also works with HAVE_DOT disabled, but it is recommended to # install and use dot, since it yields more powerful graphs. CLASS_DIAGRAMS = YES # You can define message sequence charts within doxygen comments using the \msc # command. Doxygen will then run the mscgen tool (see # http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the # documentation. The MSCGEN_PATH tag allows you to specify the directory where # the mscgen tool resides. If left empty the tool is assumed to be found in the # default search path. MSCGEN_PATH = # If set to YES, the inheritance and collaboration graphs will hide # inheritance and usage relations if the target is undocumented # or is not a class. HIDE_UNDOC_RELATIONS = NO # If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is # available from the path. This tool is part of Graphviz, a graph visualization # toolkit from AT&T and Lucent Bell Labs. The other options in this section # have no effect if this option is set to NO (the default) HAVE_DOT = YES # The DOT_NUM_THREADS specifies the number of dot invocations doxygen is # allowed to run in parallel. When set to 0 (the default) doxygen will # base this on the number of processors available in the system. You can set it # explicitly to a value larger than 0 to get control over the balance # between CPU load and processing speed. DOT_NUM_THREADS = 0 # By default doxygen will use the Helvetica font for all dot files that # doxygen generates. When you want a differently looking font you can specify # the font name using DOT_FONTNAME. You need to make sure dot is able to find # the font, which can be done by putting it in a standard location or by setting # the DOTFONTPATH environment variable or by setting DOT_FONTPATH to the # directory containing the font. DOT_FONTNAME = Helvetica # The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. # The default size is 10pt. DOT_FONTSIZE = 10 # By default doxygen will tell dot to use the Helvetica font. # If you specify a different font using DOT_FONTNAME you can use DOT_FONTPATH to # set the path where dot can find it. DOT_FONTPATH = # If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect inheritance relations. Setting this tag to YES will force the # CLASS_DIAGRAMS tag to NO. CLASS_GRAPH = YES # If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect implementation dependencies (inheritance, containment, and # class references variables) of the class with other documented classes. COLLABORATION_GRAPH = YES # If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen # will generate a graph for groups, showing the direct groups dependencies GROUP_GRAPHS = YES # If the UML_LOOK tag is set to YES doxygen will generate inheritance and # collaboration diagrams in a style similar to the OMG's Unified Modeling # Language. UML_LOOK = YES # If the UML_LOOK tag is enabled, the fields and methods are shown inside # the class node. If there are many fields or methods and many nodes the # graph may become too big to be useful. The UML_LIMIT_NUM_FIELDS # threshold limits the number of items for each type to make the size more # managable. Set this to 0 for no limit. Note that the threshold may be # exceeded by 50% before the limit is enforced. UML_LIMIT_NUM_FIELDS = 10 # If set to YES, the inheritance and collaboration graphs will show the # relations between templates and their instances. TEMPLATE_RELATIONS = NO # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT # tags are set to YES then doxygen will generate a graph for each documented # file showing the direct and indirect include dependencies of the file with # other documented files. INCLUDE_GRAPH = YES # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and # HAVE_DOT tags are set to YES then doxygen will generate a graph for each # documented header file showing the documented files that directly or # indirectly include this file. INCLUDED_BY_GRAPH = YES # If the CALL_GRAPH and HAVE_DOT options are set to YES then # doxygen will generate a call dependency graph for every global function # or class method. Note that enabling this option will significantly increase # the time of a run. So in most cases it will be better to enable call graphs # for selected functions only using the \callgraph command. CALL_GRAPH = YES # If the CALLER_GRAPH and HAVE_DOT tags are set to YES then # doxygen will generate a caller dependency graph for every global function # or class method. Note that enabling this option will significantly increase # the time of a run. So in most cases it will be better to enable caller # graphs for selected functions only using the \callergraph command. CALLER_GRAPH = NO # If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen # will generate a graphical hierarchy of all classes instead of a textual one. GRAPHICAL_HIERARCHY = YES # If the DIRECTORY_GRAPH and HAVE_DOT tags are set to YES # then doxygen will show the dependencies a directory has on other directories # in a graphical way. The dependency relations are determined by the #include # relations between the files in the directories. DIRECTORY_GRAPH = YES # The DOT_IMAGE_FORMAT tag can be used to set the image format of the images # generated by dot. Possible values are svg, png, jpg, or gif. # If left blank png will be used. If you choose svg you need to set # HTML_FILE_EXTENSION to xhtml in order to make the SVG files # visible in IE 9+ (other browsers do not have this requirement). DOT_IMAGE_FORMAT = png # If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to # enable generation of interactive SVG images that allow zooming and panning. # Note that this requires a modern browser other than Internet Explorer. # Tested and working are Firefox, Chrome, Safari, and Opera. For IE 9+ you # need to set HTML_FILE_EXTENSION to xhtml in order to make the SVG files # visible. Older versions of IE do not have SVG support. INTERACTIVE_SVG = YES # The tag DOT_PATH can be used to specify the path where the dot tool can be # found. If left blank, it is assumed the dot tool can be found in the path. DOT_PATH = # The DOTFILE_DIRS tag can be used to specify one or more directories that # contain dot files that are included in the documentation (see the # \dotfile command). DOTFILE_DIRS = # The MSCFILE_DIRS tag can be used to specify one or more directories that # contain msc files that are included in the documentation (see the # \mscfile command). MSCFILE_DIRS = # The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of # nodes that will be shown in the graph. If the number of nodes in a graph # becomes larger than this value, doxygen will truncate the graph, which is # visualized by representing a node as a red box. Note that doxygen if the # number of direct children of the root node in a graph is already larger than # DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note # that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. DOT_GRAPH_MAX_NODES = 50 # The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the # graphs generated by dot. A depth value of 3 means that only nodes reachable # from the root by following a path via at most 3 edges will be shown. Nodes # that lay further from the root node will be omitted. Note that setting this # option to 1 or 2 may greatly reduce the computation time needed for large # code bases. Also note that the size of a graph can be further restricted by # DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. MAX_DOT_GRAPH_DEPTH = 0 # Set the DOT_TRANSPARENT tag to YES to generate images with a transparent # background. This is disabled by default, because dot on Windows does not # seem to support this out of the box. Warning: Depending on the platform used, # enabling this option may lead to badly anti-aliased labels on the edges of # a graph (i.e. they become hard to read). DOT_TRANSPARENT = YES # Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output # files in one run (i.e. multiple -o and -T options on the command line). This # makes dot run faster, but since only newer versions of dot (>1.8.10) # support this, this feature is disabled by default. DOT_MULTI_TARGETS = YES # If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will # generate a legend page explaining the meaning of the various boxes and # arrows in the dot generated graphs. GENERATE_LEGEND = YES # If the DOT_CLEANUP tag is set to YES (the default) Doxygen will # remove the intermediate dot files that are used to generate # the various graphs. DOT_CLEANUP = YES dbus-cpp-5.0.3/examples/000077500000000000000000000000001407013304700150515ustar00rootroot00000000000000dbus-cpp-5.0.3/examples/CMakeLists.txt000066400000000000000000000014311407013304700176100ustar00rootroot00000000000000# Copyright © 2013 Canonical Ltd. # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License version 3 as # published by the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # # Authored by: Thomas Voss include(GNUInstallDirs) add_subdirectory(benchmark) add_subdirectory(geoclue) add_subdirectory(ofono) add_subdirectory(upower) dbus-cpp-5.0.3/examples/benchmark/000077500000000000000000000000001407013304700170035ustar00rootroot00000000000000dbus-cpp-5.0.3/examples/benchmark/CMakeLists.txt000066400000000000000000000022271407013304700215460ustar00rootroot00000000000000# Copyright © 2013 Canonical Ltd. # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License version 3 as # published by the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # # Authored by: Thomas Voss find_package(PkgConfig) find_package(Boost 1.49 COMPONENTS system) find_package(Threads) pkg_check_modules(DBUS dbus-1) include_directories( ${CMAKE_SOURCE_DIR}/include ${DBUS_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS} ${GTEST_INCLUDE_DIRS} ) add_executable( benchmark main.cpp ) target_link_libraries( benchmark dbus-cpp ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES} ${DBUS_LIBRARIES} ) install( TARGETS benchmark DESTINATION ${CMAKE_INSTALL_LIBEXECDIR}/examples/benchmark/ ) dbus-cpp-5.0.3/examples/benchmark/benchmark_service.h000066400000000000000000000120331407013304700226250ustar00rootroot00000000000000/* * Copyright © 2013 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Thomas Voß */ #ifndef BENCHMARK_SERVICE_H_ #define BENCHMARK_SERVICE_H_ #include #include #include namespace dbus = core::dbus; namespace test { class IBenchmarkService { protected: struct MethodInt64 { typedef IBenchmarkService Interface; inline static const std::string& name() { static const std::string s { "MethodInt64" }; return s; } inline static const std::chrono::milliseconds default_timeout() { return std::chrono::seconds{1}; } }; struct MethodVectorInt32 { typedef IBenchmarkService Interface; inline static const std::string& name() { static const std::string s { "MethodVectorInt32" }; return s; } inline static const std::chrono::milliseconds default_timeout() { return std::chrono::seconds{1}; } }; public: virtual ~IBenchmarkService() = default; virtual int64_t method_int64(int64_t arg) = 0; virtual std::vector method_vector_int32(const std::vector& v) = 0; }; } namespace core { namespace dbus { namespace traits { template<> struct Service { inline static const std::string& interface_name() { static const std::string s { "org.freedesktop.dbus.benchmark.Service" }; return s; } }; } } } namespace test { class BenchmarkServiceStub : public dbus::Stub { public: typedef std::shared_ptr Ptr; BenchmarkServiceStub(const dbus::Bus::Ptr& bus) : dbus::Stub(bus), object(access_service()->object_for_path(dbus::types::ObjectPath("/core/dbus/benchmark/Service"))) { } ~BenchmarkServiceStub() noexcept = default; int64_t method_int64(int64_t arg) { auto result = object->invoke_method_synchronously(arg); if (result.is_error()) throw std::runtime_error(result.error().print()); return result.value(); } std::vector method_vector_int32(const std::vector& arg) { auto result = object->invoke_method_synchronously>(arg); if (result.is_error()) throw std::runtime_error(result.error().print()); return result.value(); } private: dbus::Object::Ptr object; }; class BenchmarkServiceSkeleton : public dbus::Skeleton { public: BenchmarkServiceSkeleton(const dbus::Bus::Ptr& bus) : dbus::Skeleton(bus), object(access_service()->add_object_for_path(dbus::types::ObjectPath("/core/dbus/benchmark/Service"))) { object->install_method_handler( std::bind(&BenchmarkServiceSkeleton::handle_method_int64, this, std::placeholders::_1)); object->install_method_handler( std::bind(&BenchmarkServiceSkeleton::handle_method_vector_int32, this, std::placeholders::_1)); } ~BenchmarkServiceSkeleton() noexcept = default; private: void handle_method_int64(const dbus::Message::Ptr& msg) { int64_t in; msg->reader() >> in; int64_t out = method_int64(in); auto reply = dbus::Message::make_method_return(msg); reply->writer() << out; access_bus()->send(reply); } void handle_method_vector_int32(const dbus::Message::Ptr& msg) { std::vector in; msg->reader() >> in; auto out = method_vector_int32(in); auto reply = dbus::Message::make_method_return(msg); reply->writer() << out; access_bus()->send(reply); } dbus::Object::Ptr object; }; class BenchmarkService : public BenchmarkServiceSkeleton { public: typedef std::shared_ptr Ptr; BenchmarkService(const dbus::Bus::Ptr& bus) : BenchmarkServiceSkeleton(bus) { } int64_t method_int64(int64_t arg) { return arg; } std::vector method_vector_int32(const std::vector& arg) { return arg; } }; } #endif // BENCHMARK_SERVICE_H_ dbus-cpp-5.0.3/examples/benchmark/main.cpp000066400000000000000000000127171407013304700204430ustar00rootroot00000000000000/* * Copyright © 2013 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Thomas Voß */ #include "benchmark_service.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace acc = boost::accumulators; namespace dbus = core::dbus; namespace { dbus::Bus::Ptr the_session_bus() { dbus::Bus::Ptr session_bus = std::make_shared(dbus::WellKnownBus::session); return session_bus; } struct CrossProcessSync { static const int read_fd = 0; static const int write_fd = 1; CrossProcessSync() { if (pipe(fds) < 0) throw std::runtime_error(strerror(errno)); } ~CrossProcessSync() noexcept { ::close(fds[0]); ::close(fds[1]); } void signal_ready() { int value = 42; if (!write(fds[write_fd], std::addressof(value), sizeof(value))) throw std::runtime_error(::strerror(errno)); } void wait_for_signal_ready() { int value; if (!read(fds[read_fd], std::addressof(value), sizeof(value))) throw std::runtime_error(::strerror(errno)); } int fds[2]; }; bool is_child(pid_t pid) { return pid == 0; } int fork_and_run(int argc, char** argv, std::function child, std::function parent) { auto pid = fork(); if (pid < 0) { throw std::runtime_error(std::string("Could not fork child: ") + std::strerror(errno)); } try { if (is_child(pid)) { return child(argc, argv); } return parent(argc, argv, pid); } catch (...) { kill(pid, SIGKILL); } return EXIT_FAILURE; } } int main(int argc, char** argv) { CrossProcessSync cross_process_sync; auto server = [&cross_process_sync](int, char**) { auto bus = the_session_bus(); bus->install_executor(core::dbus::asio::make_executor(bus)); std::thread t1 { [&]() { bus->run(); } }; test::BenchmarkService::Ptr benchmark_service = dbus::announce_service_on_bus(bus); cross_process_sync.signal_ready(); if (t1.joinable()) t1.join(); return EXIT_SUCCESS; }; auto client = [&cross_process_sync](int, char**, pid_t pid) { auto bus = the_session_bus(); cross_process_sync.wait_for_signal_ready(); auto stub = dbus::resolve_service_on_bus(bus); std::ofstream out("dbus_benchmark_int64_t.txt"); acc::accumulator_set > as; std::chrono::high_resolution_clock::time_point before; const int32_t default_value = 42; const unsigned int iteration_count = 10000; for (unsigned int i = 0; i < iteration_count; i++) { before = std::chrono::high_resolution_clock::now(); auto value = stub->method_int64(default_value); if (value != default_value) return EXIT_FAILURE; auto duration = std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - before); out << duration.count() << std::endl; as(duration.count()); } std::cout << "MethodInt64 -> Mean: " << acc::mean(as) << " [µs], std. dev.: " << std::sqrt(acc::lazy_variance(as)) << " [µs]" << std::endl; out.close(); out.open("dbus_benchmark_vector_int32_t.txt"); as = acc::accumulator_set >(); const size_t element_count = 100; std::vector value(element_count, default_value); for (unsigned int i = 0; i < iteration_count; i++) { before = std::chrono::high_resolution_clock::now(); stub->method_vector_int32(value); auto duration = std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - before); out << duration.count() << std::endl; as(duration.count()); } std::cout << "MethodVectorInt32 -> Mean: " << acc::mean(as) << " [µs], std. dev.: " << std::sqrt(acc::lazy_variance(as)) << " [µs]" << std::endl; kill(pid, SIGKILL); return EXIT_SUCCESS; }; return fork_and_run(argc, argv, server, client); } dbus-cpp-5.0.3/examples/geoclue/000077500000000000000000000000001407013304700164745ustar00rootroot00000000000000dbus-cpp-5.0.3/examples/geoclue/CMakeLists.txt000066400000000000000000000022421407013304700212340ustar00rootroot00000000000000# Copyright © 2013 Canonical Ltd. # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License version 3 as # published by the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # # Authored by: Thomas Voss find_package(PkgConfig) find_package(Boost COMPONENTS system) find_package(Threads) pkg_check_modules(DBUS dbus-1) include_directories( ${CMAKE_SOURCE_DIR}/include ${DBUS_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS} ${GTEST_INCLUDE_DIRS} ) add_executable( geoclue main.cpp ) target_link_libraries( geoclue dbus-cpp ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES} ${DBUS_LIBRARIES} ${GTEST_BOTH_LIBRARIES} ) install( TARGETS geoclue DESTINATION ${CMAKE_INSTALL_LIBEXECDIR}/examples/geoclue/ ) dbus-cpp-5.0.3/examples/geoclue/geoclue.h000066400000000000000000000110241407013304700202660ustar00rootroot00000000000000/* * Copyright © 2013 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Thomas Voß */ #ifndef ORG_FREEDESKTOP_GEOCLUE_H_ #define ORG_FREEDESKTOP_GEOCLUE_H_ #include #include #include #include #include #include namespace core { struct Geoclue { struct Master { struct Create { inline static std::string name() { return "Create"; } typedef Master Interface; inline static const std::chrono::milliseconds default_timeout() { return std::chrono::seconds{1}; } }; }; struct MasterClient { struct SetRequirements { inline static std::string name() { return "SetRequirements"; } typedef MasterClient Interface; inline static const std::chrono::milliseconds default_timeout() { return std::chrono::seconds{1}; } }; struct GetAddressProvider { inline static std::string name() { return "GetAddressProvider"; } typedef MasterClient Interface; inline static const std::chrono::milliseconds default_timeout() { return std::chrono::seconds{1}; } }; struct GetPositionProvider { inline static std::string name() { return "GetPositionProvider"; } typedef MasterClient Interface; inline static const std::chrono::milliseconds default_timeout() { return std::chrono::seconds{1}; } }; }; struct Address { struct GetAddress { inline static std::string name() { return "GetAddress"; } typedef Address Interface; inline static const std::chrono::milliseconds default_timeout() { return std::chrono::seconds{1}; } }; }; struct Position { struct GetPosition { inline static std::string name() { return "GetPosition"; } typedef Position Interface; inline static const std::chrono::milliseconds default_timeout() { return std::chrono::seconds{1}; } }; struct Signals { struct PositionChanged { inline static std::string name() { return "PositionChanged"; }; typedef Position Interface; typedef std::tuple>> ArgumentType; }; }; }; }; } namespace core { namespace dbus { namespace traits { template<> struct Service { inline static const std::string& interface_name() { static const std::string s {"org.freedesktop.Geoclue" }; return s; } }; template<> struct Service { inline static const std::string& interface_name() { static const std::string s {"org.freedesktop.Geoclue.Master" }; return s; } }; template<> struct Service { inline static const std::string& interface_name() { static const std::string s {"org.freedesktop.Geoclue.MasterClient" }; return s; } }; template<> struct Service { inline static const std::string& interface_name() { static const std::string s {"org.freedesktop.Geoclue.Address" }; return s; } }; template<> struct Service { inline static const std::string& interface_name() { static const std::string s {"org.freedesktop.Geoclue.Position" }; return s; } }; } } } #endif // ORG_FREEDESKTOP_GEOCLUE_H_ dbus-cpp-5.0.3/examples/geoclue/main.cpp000066400000000000000000000102561407013304700201300ustar00rootroot00000000000000/* * Copyright © 2013 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Thomas Voß */ #include "geoclue.h" #include #include #include #include #include #include #include #include namespace dbus = core::dbus; namespace { dbus::Bus::Ptr the_session_bus() { static dbus::Bus::Ptr session_bus = std::make_shared(dbus::WellKnownBus::session); return session_bus; } } int main(int, char**) { auto bus = the_session_bus(); bus->install_executor(core::dbus::asio::make_executor(bus)); std::thread t {std::bind(&dbus::Bus::run, bus)}; auto ubuntu_geoip = dbus::Service::use_service(bus, "org.freedesktop.Geoclue.Providers.UbuntuGeoIP"); auto ubuntu_geoip_obj = ubuntu_geoip->object_for_path(dbus::types::ObjectPath("/core/Geoclue/Providers/UbuntuGeoIP")); // Connect to signal auto position_changed_signal = ubuntu_geoip_obj->get_signal(); position_changed_signal->connect([](const core::Geoclue::Position::Signals::PositionChanged::ArgumentType&) { std::cout << "core::Geoclue::Position::Signals::PositionChanged" << std::endl; }); // Demonstrates tying tuple values to fields of a custom struct. struct Position { int32_t fields; int32_t timestamp; double latitude; double longitude; double altitude; } p; std::tie(p.fields, p.timestamp, p.latitude, p.longitude, p.altitude, std::ignore) = ubuntu_geoip_obj->invoke_method_synchronously< core::Geoclue::Position::GetPosition, std::tuple>> >().value(); std::cout << p.fields << ", " << p.timestamp << ", " << p.latitude << ", " << p.longitude << ", " << p.altitude << std::endl; // Illustrates std::get-based access to. auto address = ubuntu_geoip_obj->invoke_method_synchronously< core::Geoclue::Address::GetAddress, std::tuple, dbus::types::Struct>> >().value(); std::cout << std::get<0>(address) << std::endl; std::for_each(std::get<1>(address).begin(), std::get<1>(address).end(), [](const std::pair& p) { std::cout << p.first << " -> " << p.second << std::endl; }); auto geoclue = dbus::Service::use_service(bus, dbus::traits::Service::interface_name()); auto geoclue_obj = geoclue->object_for_path(dbus::types::ObjectPath("/core/Geoclue/Master")); auto session_path = geoclue_obj->invoke_method_synchronously().value(); auto geoclue_client = geoclue->object_for_path(session_path); try { geoclue_client->invoke_method_synchronously< core::Geoclue::MasterClient::SetRequirements, void, int32_t, int32_t, bool, int32_t >(1, 100, false, (1 << 10)-1); } catch (const std::runtime_error& e) { std::cout << e.what() << std::endl; } sigset_t signal_set; sigemptyset(&signal_set); sigaddset(&signal_set, SIGINT); int signal; sigwait(&signal_set, &signal); if (t.joinable()) t.join(); return EXIT_SUCCESS; } dbus-cpp-5.0.3/examples/ofono/000077500000000000000000000000001407013304700161715ustar00rootroot00000000000000dbus-cpp-5.0.3/examples/ofono/CMakeLists.txt000066400000000000000000000021521407013304700207310ustar00rootroot00000000000000# Copyright © 2013 Canonical Ltd. # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License version 3 as # published by the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # # Authored by: Thomas Voss find_package(PkgConfig) find_package(Boost COMPONENTS system) find_package(Threads) pkg_check_modules(DBUS dbus-1) include_directories( ${CMAKE_SOURCE_DIR}/include ${DBUS_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS} ) add_executable( ofono main.cpp ) target_link_libraries( ofono dbus-cpp ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES} ${DBUS_LIBRARIES} ) install( TARGETS ofono DESTINATION ${CMAKE_INSTALL_LIBEXECDIR}/examples/ofono/ ) dbus-cpp-5.0.3/examples/ofono/main.cpp000066400000000000000000000071001407013304700176170ustar00rootroot00000000000000/* * Copyright © 2013 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Thomas Voß */ #include #include #include #include #include #include #include #include #include #include namespace dbus = core::dbus; namespace { dbus::Bus::Ptr the_session_bus() { static dbus::Bus::Ptr session_bus = std::make_shared(dbus::WellKnownBus::session); return session_bus; } } namespace org { namespace ofono { struct MessageManager { struct Signals { struct IncomingMessage { static std::string name() { return "IncomingMessage"; }; typedef MessageManager Interface; typedef std::tuple> ArgumentType; }; }; }; struct VoiceCallManager { struct Signals { struct CallAdded { static std::string name() { return "CallAdded"; }; typedef VoiceCallManager Interface; typedef std::tuple> ArgumentType; }; }; }; } } namespace core { namespace dbus { namespace traits { template<> struct Service { static std::string interface_name() { return "org.ofono.MessageManager"; } }; template<> struct Service { static std::string interface_name() { return "org.ofono.VoiceCallManager"; } }; }}} int main(int, char**) { auto bus = the_session_bus(); bus->install_executor(core::dbus::asio::make_executor(bus)); std::thread t {std::bind(&dbus::Bus::run, bus)}; auto ofono = dbus::Service::use_service(bus, "org.ofono"); auto obj = ofono->object_for_path(dbus::types::ObjectPath("/org/ofono")); /*auto incoming_message_signal = obj->get_signal(); incoming_message_signal->connect([](const std::tuple>>& arg) { std::cout << "Incoming message: " << std::get<0>(arg) << std::endl; }); auto call_added_signal = obj->get_signal(); call_added_signal->connect([](const std::tuple>>& arg) { std::cout << "Call added: " << std::get<0>(arg) << std::endl; });*/ sigset_t signal_set; sigemptyset(&signal_set); sigaddset(&signal_set, SIGINT); int signal; sigwait(&signal_set, &signal); if (t.joinable()) t.join(); return EXIT_SUCCESS; } dbus-cpp-5.0.3/examples/upower/000077500000000000000000000000001407013304700163725ustar00rootroot00000000000000dbus-cpp-5.0.3/examples/upower/CMakeLists.txt000066400000000000000000000022401407013304700211300ustar00rootroot00000000000000# Copyright © 2013 Canonical Ltd. # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License version 3 as # published by the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # # Authored by: Thomas Voss find_package(PkgConfig) find_package(Boost COMPONENTS system) find_package(Threads) pkg_check_modules(DBUS dbus-1) include_directories( ${CMAKE_SOURCE_DIR}/include ${DBUS_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS} ${GTEST_INCLUDE_DIRS} ) add_executable( upower main.cpp ) target_link_libraries( upower dbus-cpp ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES} ${DBUS_LIBRARIES} ${GTEST_BOTH_LIBRARIES} ) install( TARGETS upower DESTINATION ${CMAKE_INSTALL_LIBEXECDIR}/examples/upower/ ) dbus-cpp-5.0.3/examples/upower/main.cpp000066400000000000000000000250541407013304700200300ustar00rootroot00000000000000/* * Copyright © 2013 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Thomas Voß */ #include "upower.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace acc = boost::accumulators; namespace dbus = core::dbus; namespace { dbus::Bus::Ptr the_system_bus() { static dbus::Bus::Ptr system_bus = std::make_shared(dbus::WellKnownBus::system); return system_bus; } } int main(int, char**) { auto bus = the_system_bus(); bus->install_executor(core::dbus::asio::make_executor(bus)); std::thread t {std::bind(&dbus::Bus::run, bus)}; auto upower = dbus::Service::use_service(bus, dbus::traits::Service::interface_name()); auto upower_object = upower->object_for_path(dbus::types::ObjectPath("/core/UPower")); auto all_properties = upower_object->get_all_properties(); std::for_each(all_properties.begin(), all_properties.end(), [](const std::pair& pair) { std::cout << pair.first << std::endl; }); std::cout << upower_object->get_property()->get() << std::endl; std::cout << upower_object->get_property()->get() << std::endl; std::cout << upower_object->get_property()->get() << std::endl; std::cout << upower_object->get_property()->get() << std::endl; std::cout << upower_object->get_property()->get() << std::endl; std::cout << upower_object->get_property()->get() << std::endl; auto device_added_signal = upower_object->get_signal(); device_added_signal->connect([](const core::UPower::Signals::DeviceAdded::ArgumentType&) { std::cout << "core::UPower::Signals::DeviceAdded" << std::endl; }); auto device_removed_signal = upower_object->get_signal(); device_removed_signal->connect([](const core::UPower::Signals::DeviceRemoved::ArgumentType&) { std::cout << "core::UPower::Signals::DeviceRemoved" << std::endl; }); auto device_changed_signal = upower_object->get_signal(); device_changed_signal->connect([](const core::UPower::Signals::DeviceChanged::ArgumentType&) { std::cout << "core::UPower::Signals::DeviceChanged" << std::endl; }); auto changed_signal = upower_object->get_signal(); changed_signal->connect([]() { std::cout << "core::UPower::Signals::Changed" << std::endl; }); auto sleeping_signal = upower_object->get_signal(); sleeping_signal->connect([]() { std::cout << "core::UPower::Signals::Sleeping" << std::endl; }); auto resuming_signal = upower_object->get_signal(); resuming_signal->connect([]() { std::cout << "core::UPower::Signals::Resuming" << std::endl; }); auto devices = upower_object->invoke_method_synchronously>(); std::cout << "Devices count: " << devices.value().size() << std::endl; std::for_each(devices.value().begin(), devices.value().end(), [upower_object](const dbus::types::ObjectPath& path) { std::cout << "===================================================================================" << std::endl; auto device = upower_object->add_object_for_path(path); auto device_changed_signal = device->get_signal(); device_changed_signal->connect([]() { std::cout << "core::UPower::Device::Signals::Changed" << std::endl; }); try { auto stats = device->invoke_method_synchronously< core::UPower::Device::GetStatistics, std::vector>>, std::string>("charging"); std::for_each(stats.value().begin(), stats.value().end(), [](const dbus::types::Struct>& t) { std::cout << std::get<0>(t.value) << ", " << std::get<1>(t.value) << std::endl; }); } catch (const std::runtime_error& e) { std::cout << e.what() << std::endl; } try { acc::accumulator_set > > as; auto history = device->invoke_method_synchronously< core::UPower::Device::GetHistory, std::vector>>, std::string, uint32_t, uint32_t >("charge", 0, 50); std::for_each(history.value().begin(), history.value().end(), [&as](const dbus::types::Struct>& t) { as(std::get<1>(t.value)); }); std::cout << "Load statistics(Mean: " << acc::mean(as) << ", 2nd Moment: " << std::sqrt(acc::moment<2>(as)) << ")" << std::endl; } catch (const std::runtime_error& e) { std::cout << e.what() << std::endl; } std::cout << "Manual: " << path << std::endl; std::cout << "\tVendor: " << device->get_property()->get() << std::endl; std::cout << "\tModel: " << device->get_property()->get() << std::endl; std::cout << "\tSerial: " << device->get_property()->get() << std::endl; std::cout << "\tUpdateTime: " << device->get_property()->get() << std::endl; std::cout << "\tType: " << device->get_property()->get() << std::endl; std::cout << "\tPowerSupply: " << device->get_property()->get() << std::endl; std::cout << "\tHasHistory: " << device->get_property()->get() << std::endl; std::cout << "\tHasStatistics: " << device->get_property()->get() << std::endl; std::cout << "\tOnline: " << device->get_property()->get() << std::endl; std::cout << "\tEnergy: " << device->get_property()->get() << std::endl; std::cout << "\tEnergyEmpty: " << device->get_property()->get() << std::endl; std::cout << "\tEnergyFull: " << device->get_property()->get() << std::endl; std::cout << "\tEnergyFullDesign: " << device->get_property()->get() << std::endl; std::cout << "\tEnergyRate: " << device->get_property()->get() << std::endl; std::cout << "\tVoltage: " << device->get_property()->get() << std::endl; //std::cout << "\tTimeToEmpty: " << device->get_property()->get() << std::endl; //std::cout << "\tTimeToFull: " << device->get_property()->get() << std::endl; std::cout << "\tPercentage: " << device->get_property()->get() << std::endl; std::cout << "\tIsPresent: " << device->get_property()->get() << std::endl; std::cout << "\tState: " << device->get_property()->get() << std::endl; std::cout << "\tIsRechargeable: " << device->get_property()->get() << std::endl; std::cout << "\tCapacity: " << device->get_property()->get() << std::endl; std::cout << "\tTechnology: " << device->get_property()->get() << std::endl; std::cout << "\tRecallNotice: " << device->get_property()->get() << std::endl; std::cout << "\tRecallVendor: " << device->get_property()->get() << std::endl; std::cout << "\tRecallUrl: " << device->get_property()->get() << std::endl; std::cout << "-----------------------------------------------------------------------------------" << std::endl; auto properties = device->get_all_properties(); std::for_each(properties.begin(), properties.end(), [](const std::pair& pair) { std::cout << "\t" << pair.first << std::endl; }); std::cout << "===================================================================================" << std::endl; }); sigset_t signal_set; sigemptyset(&signal_set); sigaddset(&signal_set, SIGINT); int signal; sigwait(&signal_set, &signal); bus->stop(); if (t.joinable()) t.join(); } dbus-cpp-5.0.3/examples/upower/upower.h000066400000000000000000000405541407013304700200740ustar00rootroot00000000000000/* * Copyright © 2013 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Thomas Voß */ #ifndef ORG_FREEDESKTOP_UPOWER_H_ #define ORG_FREEDESKTOP_UPOWER_H_ #include #include #include #include namespace core { struct UPower { struct Properties { struct DaemonVersion { inline static std::string name() { return "DaemonVersion"; }; typedef UPower Interface; typedef std::string ValueType; static const bool readable = true; static const bool writable = false; }; struct CanSuspend { inline static std::string name() { return "CanSuspend"; }; typedef UPower Interface; typedef bool ValueType; static const bool readable = true; static const bool writable = false; }; struct CanHibernate { inline static std::string name() { return "CanHibernate"; }; typedef UPower Interface; typedef bool ValueType; static const bool readable = true; static const bool writable = false; }; struct OnBattery { inline static std::string name() { return "OnBattery"; }; typedef UPower Interface; typedef bool ValueType; static const bool readable = true; static const bool writable = false; }; struct OnLowBattery { inline static std::string name() { return "OnLowBattery"; }; typedef UPower Interface; typedef bool ValueType; static const bool readable = true; static const bool writable = false; }; struct LidIsClosed { inline static std::string name() { return "LidIsClosed"; }; typedef UPower Interface; typedef bool ValueType; static const bool readable = true; static const bool writable = false; }; struct LidIsPresent { inline static std::string name() { return "LidIsPresent"; }; typedef UPower Interface; typedef bool ValueType; static const bool readable = true; static const bool writable = false; }; }; struct Signals { struct DeviceAdded { inline static std::string name() { return "DeviceAdded"; }; typedef UPower Interface; typedef core::dbus::types::ObjectPath ArgumentType; }; struct DeviceRemoved { inline static std::string name() { return "DeviceRemoved"; }; typedef UPower Interface; typedef core::dbus::types::ObjectPath ArgumentType; }; struct DeviceChanged { inline static std::string name() { return "DeviceChanged"; }; typedef UPower Interface; typedef std::string ArgumentType; }; struct Changed { inline static std::string name() { return "Changed"; }; typedef UPower Interface; typedef void ArgumentType; }; struct Sleeping { inline static std::string name() { return "Sleeping"; }; typedef UPower Interface; typedef void ArgumentType; }; struct Resuming { inline static std::string name() { return "Resuming"; }; typedef UPower Interface; typedef void ArgumentType; }; }; struct EnumerateDevices { typedef UPower Interface; static const std::string& name() { static const std::string s { "EnumerateDevices" }; return s; } inline static const std::chrono::milliseconds default_timeout() { return std::chrono::seconds{1}; } }; struct Device { struct GetHistory { inline static std::string name() { return "GetHistory"; } typedef Device Interface; inline static const std::chrono::milliseconds default_timeout() { return std::chrono::seconds{1}; } }; struct GetStatistics { inline static std::string name() { return "GetStatistics"; } typedef Device Interface; inline static const std::chrono::milliseconds default_timeout() { return std::chrono::seconds{1}; } }; struct Properties { struct NativePath { inline static std::string name() { return "NativePath"; }; typedef Device Interface; typedef std::string ValueType; static const bool readable = true; static const bool writable = false; }; struct Vendor { inline static std::string name() { return "Vendor"; }; typedef Device Interface; typedef std::string ValueType; static const bool readable = true; static const bool writable = false; }; struct Model { inline static std::string name() { return "Model"; }; typedef Device Interface; typedef std::string ValueType; static const bool readable = true; static const bool writable = false; }; struct Serial { inline static std::string name() { return "Serial"; }; typedef Device Interface; typedef std::string ValueType; static const bool readable = true; static const bool writable = false; }; struct UpdateTime { inline static std::string name() { return "UpdateTime"; }; typedef Device Interface; typedef uint64_t ValueType; static const bool readable = true; static const bool writable = false; }; struct Type { inline static std::string name() { return "Type"; }; typedef Device Interface; typedef uint32_t ValueType; static const bool readable = true; static const bool writable = false; }; struct PowerSupply { inline static std::string name() { return "PowerSupply"; }; typedef Device Interface; typedef bool ValueType; static const bool readable = true; static const bool writable = false; }; struct HasHistory { inline static std::string name() { return "HasHistory"; }; typedef Device Interface; typedef bool ValueType; static const bool readable = true; static const bool writable = false; }; struct HasStatistics { inline static std::string name() { return "HasStatistics"; }; typedef Device Interface; typedef bool ValueType; static const bool readable = true; static const bool writable = false; }; struct Online { inline static std::string name() { return "Online"; }; typedef Device Interface; typedef bool ValueType; static const bool readable = true; static const bool writable = false; }; struct Energy { inline static std::string name() { return "Energy"; }; typedef Device Interface; typedef double ValueType; static const bool readable = true; static const bool writable = false; }; struct EnergyEmpty { inline static std::string name() { return "EnergyEmpty"; }; typedef Device Interface; typedef double ValueType; static const bool readable = true; static const bool writable = false; }; struct EnergyFull { inline static std::string name() { return "EnergyFull"; }; typedef Device Interface; typedef double ValueType; static const bool readable = true; static const bool writable = false; }; struct EnergyFullDesign { inline static std::string name() { return "EnergyFullDesign"; }; typedef Device Interface; typedef double ValueType; static const bool readable = true; static const bool writable = false; }; struct EnergyRate { inline static std::string name() { return "EnergyRate"; }; typedef Device Interface; typedef double ValueType; static const bool readable = true; static const bool writable = false; }; struct Voltage { inline static std::string name() { return "Voltage"; }; typedef Device Interface; typedef double ValueType; static const bool readable = true; static const bool writable = false; }; struct TimeToEmpty { inline static std::string name() { return "TimeToEmpty"; }; typedef Device Interface; typedef int64_t ValueType; static const bool readable = true; static const bool writable = false; }; struct TimeToFull { inline static std::string name() { return "TimeToFull"; }; typedef Device Interface; typedef int64_t ValueType; static const bool readable = true; static const bool writable = false; }; struct Percentage { inline static std::string name() { return "Percentage"; }; typedef Device Interface; typedef double ValueType; static const bool readable = true; static const bool writable = false; }; struct IsPresent { inline static std::string name() { return "IsPresent"; }; typedef Device Interface; typedef bool ValueType; static const bool readable = true; static const bool writable = false; }; struct State { inline static std::string name() { return "State"; }; typedef Device Interface; typedef uint32_t ValueType; static const bool readable = true; static const bool writable = false; }; struct IsRechargeable { inline static std::string name() { return "IsRechargeable"; }; typedef Device Interface; typedef bool ValueType; static const bool readable = true; static const bool writable = false; }; struct Capacity { inline static std::string name() { return "Capacity"; }; typedef Device Interface; typedef double ValueType; static const bool readable = true; static const bool writable = false; }; struct Technology { inline static std::string name() { return "Technology"; }; typedef Device Interface; typedef uint32_t ValueType; static const bool readable = true; static const bool writable = false; }; struct RecallNotice { inline static std::string name() { return "RecallNotice"; }; typedef Device Interface; typedef bool ValueType; static const bool readable = true; static const bool writable = false; }; struct RecallVendor { inline static std::string name() { return "RecallVendor"; }; typedef Device Interface; typedef std::string ValueType; static const bool readable = true; static const bool writable = false; }; struct RecallUrl { inline static std::string name() { return "RecallUrl"; }; typedef Device Interface; typedef std::string ValueType; static const bool readable = true; static const bool writable = false; }; }; struct Signals { struct Changed { inline static std::string name() { return "Changed"; }; typedef Device Interface; typedef void ArgumentType; }; }; }; }; } namespace core { namespace dbus { namespace traits { template<> struct Service { inline static const std::string& interface_name() { static const std::string s { "org.freedesktop.UPower" }; return s; } }; template<> struct Service { inline static const std::string& interface_name() { static const std::string s { "org.freedesktop.UPower.Device" }; return s; } }; } } } #endif // ORG_FREEDESKTOP_UPOWER_H_ dbus-cpp-5.0.3/include/000077500000000000000000000000001407013304700146565ustar00rootroot00000000000000dbus-cpp-5.0.3/include/CMakeLists.txt000066400000000000000000000013441407013304700174200ustar00rootroot00000000000000# Copyright © 2013 Canonical Ltd. # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License version 3 as # published by the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # # Authored by: Thomas Voss install( DIRECTORY core DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/ ) dbus-cpp-5.0.3/include/core/000077500000000000000000000000001407013304700156065ustar00rootroot00000000000000dbus-cpp-5.0.3/include/core/dbus/000077500000000000000000000000001407013304700165435ustar00rootroot00000000000000dbus-cpp-5.0.3/include/core/dbus/announcer.h000066400000000000000000000037241407013304700207120ustar00rootroot00000000000000/* * Copyright © 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Thomas Voß */ #ifndef CORE_DBUS_ANNOUNCER_H_ #define CORE_DBUS_ANNOUNCER_H_ #include #include namespace core { namespace dbus { /** * @brief Announces a service implementing the specified interface, dispatching requests to the specified implementation. * @tparam Interface The interface that we want to expose a service for. * @tparam Implementation The actual backend that calls are dispatched to. * @tparam ConstructArgs Parameter bundle passed on to the implementation c'tor. * @param [in] connection The DBus connection to announce the service upon. * @param [in] args Parameter pack to be passed on the implementation's c'tor. */ template inline static typename Implementation::Ptr announce_service_on_bus( const Bus::Ptr& connection, const ConstructArgs&... args) { static_assert(std::is_base_of, Implementation>::value, "Implementation is not a Skeleton"); static_assert(std::is_base_of::value, "Implementation type does not inherit from Interface type."); return typename Implementation::Ptr(new Implementation(connection, args...)); } } } #endif // CORE_DBUS_ANNOUNCER_H_ dbus-cpp-5.0.3/include/core/dbus/argument_type.h000066400000000000000000000056171407013304700216100ustar00rootroot00000000000000/* * Copyright © 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Thomas Voß */ #ifndef CORE_DBUS_ARGUMENT_TYPE_H_ #define CORE_DBUS_ARGUMENT_TYPE_H_ #include #include #include #include namespace core { namespace dbus { /** * @brief Wraps the underlying DBus types and exposes them as a strongly typed enum. */ enum class ArgumentType : int { byte = DBUS_TYPE_BYTE, boolean = DBUS_TYPE_BOOLEAN, int16 = DBUS_TYPE_INT16, uint16 = DBUS_TYPE_UINT16, int32 = DBUS_TYPE_INT32, uint32 = DBUS_TYPE_UINT32, int64 = DBUS_TYPE_INT64, uint64 = DBUS_TYPE_UINT64, floating_point = DBUS_TYPE_DOUBLE, string = DBUS_TYPE_STRING, object_path = DBUS_TYPE_OBJECT_PATH, signature = DBUS_TYPE_SIGNATURE, unix_fd = DBUS_TYPE_UNIX_FD, array = DBUS_TYPE_ARRAY, variant = DBUS_TYPE_VARIANT, structure = DBUS_TYPE_STRUCT, dictionary_entry = DBUS_TYPE_DICT_ENTRY, invalid = DBUS_TYPE_INVALID }; /** * @brief Pretty prints ArgumentType to an output stream. * @param out The stream to write to. * @param type The type to be printed. * @return The stream that has been written to. */ inline std::ostream& operator<<(std::ostream& out, const ArgumentType& type) noexcept(true) { static const std::map lut = { {ArgumentType::byte, "byte"}, {ArgumentType::boolean, "boolean"}, {ArgumentType::int16, "int16"}, {ArgumentType::uint16, "uint16"}, {ArgumentType::int32, "int32"}, {ArgumentType::uint32, "uint32"}, {ArgumentType::int64, "int64"}, {ArgumentType::uint64, "uint64"}, {ArgumentType::floating_point, "floating_point"}, {ArgumentType::string, "string"}, {ArgumentType::object_path, "object_path"}, {ArgumentType::signature, "signature"}, {ArgumentType::unix_fd, "unix_fd"}, {ArgumentType::array, "array"}, {ArgumentType::variant, "variant"}, {ArgumentType::structure, "structure"}, {ArgumentType::dictionary_entry, "dictionary_entry"}, {ArgumentType::invalid, "invalid"} }; try { out << lut.at(type); } catch(...) { out << lut.at(ArgumentType::invalid); } return out; } } } #endif // CORE_DBUS_ARGUMENT_TYPE_H_ dbus-cpp-5.0.3/include/core/dbus/asio/000077500000000000000000000000001407013304700174765ustar00rootroot00000000000000dbus-cpp-5.0.3/include/core/dbus/asio/executor.h000066400000000000000000000022571407013304700215130ustar00rootroot00000000000000/* * Copyright © 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Thomas Voß */ #ifndef CORE_DBUS_ASIO_EXECUTOR_H_ #define CORE_DBUS_ASIO_EXECUTOR_H_ #include #include #include #include namespace core { namespace dbus { namespace asio { ORG_FREEDESKTOP_DBUS_DLL_PUBLIC Executor::Ptr make_executor(const Bus::Ptr& bus); ORG_FREEDESKTOP_DBUS_DLL_PUBLIC Executor::Ptr make_executor(const Bus::Ptr& bus, boost::asio::io_service& io); } } } #endif // CORE_DBUS_ASIO_EXECUTOR_H_ dbus-cpp-5.0.3/include/core/dbus/bus.h000066400000000000000000000246351407013304700175170ustar00rootroot00000000000000/* * Copyright © 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Thomas Voß */ #ifndef CORE_DBUS_BUS_H_ #define CORE_DBUS_BUS_H_ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace core { namespace dbus { class MatchRule; class Object; /** * @brief The Bus class constitutes a very thin wrapper and the starting * point to expose low-level DBus functionality for internal purposes. */ class ORG_FREEDESKTOP_DBUS_DLL_PUBLIC Bus { public: typedef std::shared_ptr Ptr; /** * @brief The RequestNameFlag enum lists possible behavior when trying to acquire name on the bus. */ enum class RequestNameFlag { not_set = 0, allow_replacement = 1 << 0, ///< Allow for later replacement by another service implementation. replace_existing = 1 << 1, ///< Replace any existing instance on the bus. do_not_queue = 1 << 2 ///< Blocking wait for service name to be acquired. }; /** @brief Describes a name on the bus. */ class Name { public: Name(const Name&) = delete; Name(Name&& rhs); Name& operator=(Name&& rhs); /** * @brief as_string returns a string presentation of the name. */ const std::string& as_string() const; private: friend class Bus; Name(const std::string& name); std::string name; }; /** * @brief default_request_name_flags returns defaults flags when acquiring a name on the bus. */ static RequestNameFlag default_request_name_flags(); /** * @brief The Errors struct summarizes exceptions that are thrown by Bus functions. */ struct Errors { Errors() = delete; /** * @brief The AlreadyOwner exception if this process already owns the name on the bus. */ struct AlreadyOwner : public std::runtime_error { inline AlreadyOwner() : std::runtime_error( "This process already owns the name on the bus.") { } }; /** * @brief The AlreadyOwned exception is thrown if this process already owns the name on the bus. */ struct AlreadyOwned : public std::runtime_error { inline AlreadyOwned() : std::runtime_error( "The name is already owned on the bus.") { } }; /** * @brief The NoMemory exception is thrown if an operation failed due to a lack of memory. */ struct NoMemory : public std::runtime_error { inline NoMemory() : std::runtime_error( "Not enough memory to complete operation.") { } }; /** * @brief The ObjectPathInUse exception is thrown if a path is already owned. */ struct ObjectPathInUse : public std::runtime_error { inline ObjectPathInUse() : std::runtime_error( "Object path is already in use.") { } }; }; /** @brief Routing of messages based on their type. */ typedef MessageRouter MessageTypeRouter; /** @brief Routing of signals based on a tuple of interface and member name. */ typedef MessageRouter SignalRouter; /** * @brief The MessageHandlerResult enum summarizes possible replies of a MessageHandler. */ enum class MessageHandlerResult { handled = DBUS_HANDLER_RESULT_HANDLED, ///< Message has had its effect - no need to run more handlers. not_yet_handled = DBUS_HANDLER_RESULT_NOT_YET_HANDLED, ///< Message has not had any effect - see if other handlers want it. need_memory = DBUS_HANDLER_RESULT_NEED_MEMORY ///< Need more memory, please try again later with more memory. }; /** @brief Function signature for handling a message. */ typedef std::function MessageHandler; /** * @brief Constructs an instance of Bus and connected to the bus specified by address. * @param address The address of the bus to connect to. */ explicit Bus(const std::string& address); /** * @brief Creates a connection to a well-known bus. The implementation takes care of setting up thread-safety flags for DBus. * @param bus The well-known bus the instance should connect to. */ explicit Bus(WellKnownBus bus); // A Bus instance is not copy-able. Bus(const Bus&) = delete; /** * @brief Disconnects from the bus and releases the connection corresponding to this instance. */ ~Bus() noexcept; Bus& operator=(const Bus&) = delete; bool operator==(const Bus&) const = delete; /** * @brief Provides access to a bus-specific message factory. */ const std::shared_ptr message_factory(); /** * @brief Attempts to own the given name on the bus. * @throw Bus::Errors::AlreadyOwner if this process already owns the name. * @throw Bus::Errors::AlreadyOwned if the name is already owned on the bus. * @return A unique instance if the ownership request completed successfully. */ Name request_name_on_bus( const std::string& name, RequestNameFlag flags); /** * @brief Releases the previously owned name. * @param name The name to release. */ void release_name_on_bus(Name&& name); /** * @brief Sends a raw DBus message over this DBus connection. * @param msg The message to send, must not be null. * @return A reply serial. * @throw std::runtime_error in case of errors. */ uint32_t send(const std::shared_ptr& msg); /** * @brief Invokes a function and blocks for a specified amount of time waiting for a result. * @param msg The method call. * @param milliseconds The timeout. * @return The reply message or null in case of errors. * @throw std::runtime_error if a timeout occurs. */ std::shared_ptr send_with_reply_and_block_for_at_most( const std::shared_ptr& msg, const std::chrono::milliseconds& milliseconds); /** * @brief Invokes a function, returning a waitable pending call that times out after the specified time period. * @param msg The method call. * @param timeout The timeout. * @return The waitable, pending call for this method invocation. */ PendingCall::Ptr send_with_reply_and_timeout( const std::shared_ptr& msg, const std::chrono::milliseconds& timeout); /** * @brief Installs a match rule to the underlying DBus connection. * @param rule The match rule to be installed, has to be a valid match rule. */ void add_match(const MatchRule& rule); /** * @brief Uninstalls a match rule to the underlying DBus connection. * @param rule The match rule to be uninstalled. */ void remove_match(const MatchRule& rule); /** * @brief Checks if the given name is owned on this bus connection. * @param name The name to check ownership for. * @return true if the name is already owned, false otherwise. */ bool has_owner_for_name(const std::string& name); /** * @brief Installs an executor for this bus connection, enabling signal and method call delivery. * @param e The executor instance, must not be null. */ void install_executor(const Executor::Ptr& e); /** * @brief Stops signal and method call delivery, i.e., stops the underlying executor if any. */ void stop(); /** * @brief Starts signal and method call delivery, i.e., starts the underlying executor if any. */ void run(); /** * @brief Provides mutable access to the contained signal router. */ SignalRouter& access_signal_router(); /** * @brief Provides raw, unmanaged access to the underlying DBus connection. */ DBusConnection* raw() const; /** * @brief register_object_for_path makes the given object known for the path on the bus. * @throw Bus::Errors::NoMemory if not enough memory. * @throw Bus::Errors::ObjectPathInUse if path is already used. * @param path The path to make the object known for on the bus. * @param object The object to make known */ void register_object_for_path( const types::ObjectPath& path, const std::shared_ptr& object); /** * @brief unregister_object_path removes the object known under the given name from the bus. * @throw Bus::Errors::NoMemory if not enough memory. * @param path The path to remove from the bus. */ void unregister_object_path( const types::ObjectPath& path); /** * @brief Hands over a message to the internal message and signal routers. */ MessageHandlerResult handle_message(const Message::Ptr& msg); private: struct Private; std::unique_ptr d; }; /** @brief Enables usage of RequestNameFlag as a bitfield. */ inline Bus::RequestNameFlag operator|(Bus::RequestNameFlag lhs, Bus::RequestNameFlag rhs) { return static_cast( static_cast(lhs) | static_cast(rhs)); } } } #endif // CORE_DBUS_BUS_H_ dbus-cpp-5.0.3/include/core/dbus/codec.h000066400000000000000000000231321407013304700177720ustar00rootroot00000000000000/* * Copyright © 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Thomas Voß */ #ifndef CORE_DBUS_CODEC_H_ #define CORE_DBUS_CODEC_H_ #include #include namespace core { namespace dbus { /** * @brief A templated class that allows for defining encoding/decoding of arbitrary types to the DBus type system. * @tparam T The type for which encoding and decoding should be specified. */ template struct Codec { /** * @brief Encodes an argument to a DBus message * @param out Output writer into the outgoing message. * @param arg The argument to encode. * @throw std::runtime_error in case of errors. */ static void encode_argument(Message::Writer& out, const T& arg); /** * @brief Decodes an argument from a DBus message. * @param in Input iterator into the incoming message. * @param arg The argument to decode to. * @throw std::runtime_error in case of errors. */ static void decode_argument(Message::Reader& in, T& arg); }; /** * @brief Template specialization for void argument types. */ template<> struct Codec { /** * @brief Does nothing */ inline static void encode_argument(Message::Writer&) { } /** * @brief Does nothing */ inline static void decode_argument(Message::Reader&) { } }; /** * @brief Template specialization for byte argument types. */ template<> struct Codec { inline static void encode_argument(Message::Writer& out, const std::int8_t& value) { out.push_byte(value); } inline static void decode_argument(Message::Reader& in, std::int8_t& value) { value = in.pop_byte(); } }; /** * @brief Template specialization for boolean argument types. */ template<> struct Codec { inline static void encode_argument(Message::Writer& out, bool value) { out.push_boolean(value); } inline static void decode_argument(Message::Reader& in, bool& value) { value = in.pop_boolean(); } }; /** * @brief Template specialization for int16 argument types. */ template<> struct Codec { inline static void encode_argument(Message::Writer& out, std::int16_t value) { out.push_int16(value); } inline static void decode_argument(Message::Reader& in, std::int16_t& value) { value = in.pop_int16(); } }; /** * @brief Template specialization for uint16 argument types. */ template<> struct Codec { inline static void encode_argument(Message::Writer& out, std::uint16_t value) { out.push_uint16(value); } inline static void decode_argument(Message::Reader& in, std::uint16_t& value) { value = in.pop_uint16(); } }; /** * @brief Template specialization for int32 argument types. */ template<> struct Codec { inline static void encode_argument(Message::Writer& out, std::int32_t value) { out.push_int32(value); } inline static void decode_argument(Message::Reader& in, std::int32_t& value) { value = in.pop_int32(); } }; /** * @brief Template specialization for uint32 argument types. */ template<> struct Codec { inline static void encode_argument(Message::Writer& out, std::uint32_t value) { out.push_uint32(value); } inline static void decode_argument(Message::Reader& in, std::uint32_t& value) { value = in.pop_uint32(); } }; /** * @brief Template specialization for int64 argument types. */ template<> struct Codec { inline static void encode_argument(Message::Writer& out, std::int64_t value) { out.push_int64(value); } inline static void decode_argument(Message::Reader& in, std::int64_t& value) { value = in.pop_int64(); } }; /** * @brief Template specialization for uint64 argument types. */ template<> struct Codec { inline static void encode_argument(Message::Writer& out, std::uint64_t value) { out.push_uint64(value); } inline static void decode_argument(Message::Reader& in, std::uint64_t& value) { value = in.pop_uint64(); } }; /** * @brief Template specialization for floating point argument types. */ template<> struct Codec { inline static void encode_argument(Message::Writer& out, double value) { out.push_floating_point(value); } inline static void decode_argument(Message::Reader& in, double& value) { value = in.pop_floating_point(); } }; /** * @brief Template specialization for floating point argument types. */ template<> struct Codec { inline static void encode_argument(Message::Writer& out, float value) { out.push_floating_point(value); } inline static void decode_argument(Message::Reader& in, float& value) { value = in.pop_floating_point(); } }; /** * @brief Template specialization for object path argument types. */ template<> struct Codec { inline static void encode_argument(Message::Writer& out, const types::ObjectPath& value) { out.push_object_path(value); } inline static void decode_argument(Message::Reader& in, types::ObjectPath& value) { value = in.pop_object_path(); } }; /** * @brief Template specialization for object path argument types. */ template<> struct Codec { inline static void encode_argument(Message::Writer& out, const types::Signature& value) { out.push_signature(value); } inline static void decode_argument(Message::Reader& in, types::Signature& value) { value = in.pop_signature(); } }; /** * @brief Template specialization for object path argument types. */ template<> struct Codec { inline static void encode_argument(Message::Writer& out, const types::UnixFd& value) { out.push_unix_fd(value); } inline static void decode_argument(Message::Reader& in, types::UnixFd& value) { value = in.pop_unix_fd(); } }; /** * @brief Template specialization for any argument types. */ template<> struct Codec { inline static void encode_argument(Message::Writer& out, const types::Any& value) { (void) out; (void) value; } inline static void decode_argument(Message::Reader& in, types::Any& value) { value = types::Any{in}; } }; /** * @brief Helper function that encodes the supplied argument relying on a Codec template specialization. * @tparam T Type of the argument that should be encoded. * @param out Output iterator to write to. * @param arg Argument to encode. * @throw std::runtime_error as thrown by Codec::encode_argument. */ template inline void encode_argument(Message::Writer& out, const T& arg) { Codec::type>::encode_argument(out, arg); } /** * @brief Special overload to end compile-time recursion. */ inline void encode_message(Message::Writer&) {} /** * @brief Compile-time recursion to encode a parameter pack into a DBus message. * @tparam Arg The first argument to encode. * @tparam Args The remaining arguments to encode. * @throw std::runtime_error as propagated by Codec::encode_argument. */ template inline void encode_message(Message::Writer& out, const Arg& arg, Args... params) { encode_argument(out, arg); encode_message(out, params...); } /** * @brief Helper function that decodes the supplied argument relying on a Codec template specialization. * @tparam T Type of the argument that should be decoded. * @param out Input iterator to read from. * @param arg Argument to decode. * @throw std::runtime_error as thrown by Codec::decode_argument. */ template inline void decode_argument(Message::Reader& out, T& arg) { Codec::decode_argument(out, arg); } /** * @brief Helper function that decodes an argument relying on a Codec template specialization, returning a copy of the argument. * @tparam T Type of the argument that should be decoded. * @param out Input iterator to read from. * @return An instance of T, filled with values decoded from the underlying message. * @throw std::runtime_error as thrown by Codec::decode_argument. */ template inline T decode_argument(Message::Reader& out) { T arg; Codec::decode_argument(out, arg); return arg; } /** * @brief Special overload to end compile-time recursion. */ inline void decode_message(Message::Reader&) {} /** * @brief Compile-time recursion to decode a parameter pack from a DBus message. * @tparam Arg The first argument to decode. * @tparam Args The remaining arguments to decode. * @throw std::runtime_error as propagated by Codec::decode_argument. */ template inline void decode_message(Message::Reader& out, Arg& arg, Args& ... params) { decode_argument(out, arg); decode_message(out, params...); } } } #endif // CORE_DBUS_CODEC_H_ dbus-cpp-5.0.3/include/core/dbus/compiler.h000066400000000000000000000202431407013304700205270ustar00rootroot00000000000000/* * Copyright © 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Thomas Voß */ #ifndef CORE_DBUS_COMPILER_H_ #define CORE_DBUS_COMPILER_H_ #include #include #include #include #include #include namespace core { namespace dbus { class Generator; struct GeneratorConfiguration; /** * \brief Parses and processes a DBus introspection XML. */ class Compiler { public: static int main(int argc, const char** argv); class Element { public: enum class Type { node, interface, method, signal, property, argument, annotation }; inline Element(const std::shared_ptr& parent, const IntrospectionParser::Node& node) : d{parent, Type::node, node} { } inline Element(const std::shared_ptr& parent, const IntrospectionParser::Interface& interface) : d{parent, Type::interface, interface} { } inline Element(const std::shared_ptr& parent, const IntrospectionParser::Method& method) : d{parent, Type::method, method} { } inline Element(const std::shared_ptr& parent, const IntrospectionParser::Signal& signal) : d{parent, Type::signal, signal} { } inline Element(const std::shared_ptr& parent, const IntrospectionParser::Property& property) : d{parent, Type::property, property} { } inline Element(const std::shared_ptr& parent, const IntrospectionParser::Argument& argument) : d{parent, Type::argument, argument} { } inline Element(const std::shared_ptr& parent, const IntrospectionParser::Annotation& annotation) : d{parent, Type::annotation, annotation} { } Element(const Element&) = delete; Element& operator=(const Element&) = delete; bool operator<(const Element& rhs) const { return static_cast(d.type) < static_cast(rhs.d.type); } inline void apply(std::function before, std::function visitor, std::function after) { visitor(*this); for(auto child : d.children) { if (before) before(*child); child->apply(before, visitor, after); if (after) after(*child); } } inline const std::shared_ptr& parent() const { return d.parent; } inline Type type() const { return d.type; } inline void add_child(const std::shared_ptr& child) { d.children.insert(child); } inline const IntrospectionParser::Node& node() const { if (d.type != Type::node) throw std::runtime_error("Type mismatch"); return d.payload.node; } inline const IntrospectionParser::Interface& interface() const { if (d.type != Type::interface) throw std::runtime_error("Type mismatch"); return d.payload.interface; } inline const IntrospectionParser::Method& method() const { if (d.type != Type::method) throw std::runtime_error("Type mismatch"); return d.payload.method; } inline const IntrospectionParser::Signal& signal() const { if (d.type != Type::signal) throw std::runtime_error("Type mismatch"); return d.payload.signal; } inline const IntrospectionParser::Property& property() const { if (d.type != Type::property) throw std::runtime_error("Type mismatch"); return d.payload.property; } inline const IntrospectionParser::Argument& argument() const { if (d.type != Type::argument) throw std::runtime_error("Type mismatch"); return d.payload.argument; } inline const IntrospectionParser::Annotation& annotation() const { if (d.type != Type::annotation) throw std::runtime_error("Type mismatch"); return d.payload.annotation; } private: struct Private { struct KeyCompare { bool operator()(const std::shared_ptr& lhs, const std::shared_ptr& rhs) const { return *lhs < *rhs; } }; template Private(const std::shared_ptr& parent, Type type, const T& t) : parent(parent), children(KeyCompare()), type(type), payload(t) { } std::shared_ptr parent; std::multiset, KeyCompare> children; Type type; union Payload { Payload(const IntrospectionParser::Node& node) : node(node) {} Payload(const IntrospectionParser::Interface& interface) : interface(interface) {} Payload(const IntrospectionParser::Method& method) : method(method) {} Payload(const IntrospectionParser::Signal& signal) : signal(signal) {} Payload(const IntrospectionParser::Property& property) : property(property) {} Payload(const IntrospectionParser::Argument& argument) : argument(argument) {} Payload(const IntrospectionParser::Annotation& annotation) : annotation(annotation) {} ~Payload() {} IntrospectionParser::Node node; IntrospectionParser::Interface interface; IntrospectionParser::Method method; IntrospectionParser::Signal signal; IntrospectionParser::Property property; IntrospectionParser::Argument argument; IntrospectionParser::Annotation annotation; } payload; } d; }; /** * \brief Result of processing a DBus introspection XML. */ struct Result { /** * \brief Stub elements for usage on clients go here. */ struct { std::string header_file_path; std::string impl_file_path; } stub; /** * \brief Skeleton elements for usage/implementation by services go here. */ struct { std::string header_file_path; std::string impl_file_path; } skeleton; }; /** * \brief Creates a compiler instance with the given parser and generator. * \param[in] parser The parser implementation. * \param[in] generator The generator implementation. */ Compiler(const std::shared_ptr& parser, const std::shared_ptr& generator); Compiler(const Compiler&) = delete; ~Compiler(); bool operator==(const Compiler&) const = delete; Compiler& operator=(const Compiler&) = delete; /** * \brief Parses and processes the DBus introspection XML in the file pointed to by fn. * \brief[in] fn Name of the file containing the DBus introspection XML. * \returns An instance of result on success. * \throws std::runtime_error in case of errors. */ bool process_introspection_file_with_generator_config( const std::string& fn, const GeneratorConfiguration& config); private: struct Private; std::unique_ptr d; }; } } #endif // CORE_DBUS_COMPILER_H_ dbus-cpp-5.0.3/include/core/dbus/dbus.h000066400000000000000000000065761407013304700176670ustar00rootroot00000000000000/* * Copyright © 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Thomas Voß */ #ifndef CORE_DBUS_DBUS_H_ #define CORE_DBUS_DBUS_H_ #include #include #include #include #include namespace core { namespace dbus { class Bus; class Object; class Service; class ServiceWatcher; namespace types { class ObjectPath; } /** * @brief The DBus class provides access to dbus daemon on the bus. */ class ORG_FREEDESKTOP_DBUS_DLL_PUBLIC DBus { public: /** * @brief The WatchMode enum lists the different watch modes for service registration. */ enum class WatchMode { registration = 0x01, ///< Notify when a name is newly registered. unregistration = 0x02, ///< Notify when a name is newly unregistered. owner_change = 0x03, ///< Notify if the owner name changes at all. }; /** @brief Query the well-known name of the DBus daemon. */ static const std::string& name(); /** @brief Query the object path of the DBus daemon. */ static const types::ObjectPath& path(); /** @brief Query the interface name of the DBus daemon. */ static const std::string& interface(); DBus(const std::shared_ptr& bus); DBus(const DBus&) = delete; DBus& operator=(const DBus&) = delete; bool operator==(const DBus&) const = delete; /** * @brief Queries the process ID given a name on the bus. * @param [in] name Name of the remote peer. * @return The process id of the remote peer. */ uint32_t get_connection_unix_process_id(const std::string& name) const; /** * @brief Queries the user ID given a name on the bus. * @param [in] name Name of the remote peer. * @return The user id that the remote peer runs under. */ uint32_t get_connection_unix_user(const std::string& name) const; /** * @brief Say hello to the message bus daemon. * @return The unique name assigned to this connection. */ std::string hello() const; /** * @brief List all known names on the bus. * @return A vector of all known participants on the bus. */ std::vector list_names() const; /** * @brief Create a new service watcher for the specified name and watch mode * @return Unique instance of ServiceWatcher with the specified parameters */ std::unique_ptr make_service_watcher( const std::string& name, WatchMode watch_mode = WatchMode::owner_change); private: struct ListNames; struct Hello; struct GetConnectionUnixProcessID; struct GetConnectionUnixUser; std::shared_ptr bus; std::shared_ptr service; std::shared_ptr object; }; } } #endif // CORE_DBUS_DBUS_H_ dbus-cpp-5.0.3/include/core/dbus/error.h000066400000000000000000000040711407013304700200470ustar00rootroot00000000000000/* * Copyright © 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Thomas Voß */ #ifndef CORE_DBUS_ERROR_H_ #define CORE_DBUS_ERROR_H_ #include #include #include struct DBusError; namespace core { namespace dbus { /** * @brief Wraps a raw error instance as reported by the underlying DBus implementation. */ class ORG_FREEDESKTOP_DBUS_DLL_PUBLIC Error { public: /** * @brief Constructs a valid but empty Error instance. * @post operator bool() returns false. */ Error(); Error(const Error&) = delete; Error(Error&&); ~Error(); Error& operator=(const Error&) = delete; Error& operator=(Error&&); /** * @brief Queries the name of the error. Non-empty if operator bool() returns true. */ std::string name() const; /** * @brief Queries the human readable description of the error. Non-empty if operator bool() returns true. */ std::string message() const; /** * @brief Pretty prints name and message for consumption by humans. */ std::string print() const; /** * @brief Checks if the error bit is set. */ operator bool() const; /** * @brief Provides mutable access to the underlying error as defined by the underlying DBus implementation. */ DBusError& raw(); private: struct ORG_FREEDESKTOP_DBUS_DLL_LOCAL Private; std::unique_ptr d; }; } } #endif // CORE_DBUS_ERROR_H_ dbus-cpp-5.0.3/include/core/dbus/executor.h000066400000000000000000000026741407013304700205630ustar00rootroot00000000000000/* * Copyright © 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Thomas Voß */ #ifndef CORE_DBUS_EXECUTOR_H_ #define CORE_DBUS_EXECUTOR_H_ #include #include namespace core { namespace dbus { /** * @brief Abstracts an event loop that a bus instance should be running upon. */ class ORG_FREEDESKTOP_DBUS_DLL_PUBLIC Executor { public: typedef std::shared_ptr Ptr; virtual ~Executor() = default; protected: friend class Bus; Executor() = default; Executor(const Executor&) = delete; Executor& operator=(const Executor&) = delete; /** * @brief Start the event loop and block until stop is called. */ virtual void run() = 0; /** * @brief Stop the event loop. */ virtual void stop() = 0; }; } } #endif // CORE_DBUS_EXECUTOR_H_ dbus-cpp-5.0.3/include/core/dbus/fixture.h000066400000000000000000000121341407013304700204030ustar00rootroot00000000000000/* * Copyright © 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Thomas Voß */ #ifndef CORE_DBUS_FIXTURE_H_ #define CORE_DBUS_FIXTURE_H_ #include #include #include #include namespace core { namespace dbus { class Bus; /** * @brief The Fixture class provides private session and system bus instances for testing purposes. */ class ORG_FREEDESKTOP_DBUS_DLL_PUBLIC Fixture { public: /** @brief Fractional seconds. */ typedef std::chrono::duration Seconds; /** * @brief default_daemon_timeout after which the dbus daemons will be killed. */ static Seconds& default_daemon_timeout(); /** * @brief default_session_bus_config_file provides the filename of the default session * bus configuration file. */ static const std::string& default_session_bus_config_file(); /** * @brief default_system_bus_config_file provides the filename of the default system * bus configuration file. */ static const std::string& default_system_bus_config_file(); /** * @brief Constructs a fixture instance with the two given configuration files. * * Any test running within the scope of this fixture will access the private * session- and system-bus instances setup by this class. * * @param session_bus_config_file Path to the session-bus configuration file. * @param system_bus_config_file Path to the system-bus configuration file. */ Fixture(const std::string& session_bus_config_file, const std::string& system_bus_config_file); virtual ~Fixture(); /** * @brief session_bus_address returns the address of the private session bus instance. */ std::string session_bus_address(); /** * @brief create_connection_to_session_bus creates a new connection to the testing session bus instance. */ std::shared_ptr create_connection_to_session_bus(); /** * @brief session_bus_address returns the address of the private session bus instance. */ std::string system_bus_address(); /** * @brief create_connection_to_system_bus creates a new connection to the testing system bus instance. */ std::shared_ptr create_connection_to_system_bus(); private: struct Private; std::unique_ptr d; }; } } #if defined(CORE_DBUS_ENABLE_GOOGLE_TEST_FIXTURE) #include namespace core { namespace dbus { namespace testing { /** * @brief The Fixture class provides a Google Test fixture for running * tests in a private dbus environment. */ class Fixture : public ::testing::Test { public: /** * @brief default_session_bus_config_file provides the filename of the default session * bus configuration file. */ inline static std::string& default_session_bus_config_file() { static std::string s{core::dbus::Fixture::default_session_bus_config_file()}; return s; } /** * @brief default_system_bus_config_file provides the filename of the default system * bus configuration file. */ inline static std::string& default_system_bus_config_file() { static std::string s{core::dbus::Fixture::default_system_bus_config_file()}; return s; } /** * @brief Constructs an instance and sets up connections to the private * session and system bus. * * @throw std::runtime_error in case of issues. */ inline Fixture() : fixture(default_session_bus_config_file(), default_system_bus_config_file()) { } /** * @brief session_bus_address returns the address of the private session bus instance. */ inline std::string session_bus_address() { return fixture.session_bus_address(); } /** * @brief session_bus provides access to the private session bus. */ inline std::shared_ptr session_bus() { return fixture.create_connection_to_session_bus(); } /** * @brief system_bus_address returns the address of the private session bus instance. */ inline std::string system_bus_address() { return fixture.system_bus_address(); } /** * @brief system_bus provides access to the private system bus. */ inline std::shared_ptr system_bus() { return fixture.create_connection_to_system_bus(); } private: core::dbus::Fixture fixture; }; } } } #endif // CORE_DBUS_ENABLE_GOOGLE_TEST_FIXTURE #endif // CORE_DBUS_FIXTURE_H_ dbus-cpp-5.0.3/include/core/dbus/generator.h000066400000000000000000000044411407013304700207050ustar00rootroot00000000000000/* * Copyright © 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Thomas Voß */ #ifndef CORE_DBUS_GENERATOR_H_ #define CORE_DBUS_GENERATOR_H_ #include #include #include #include namespace core { namespace dbus { struct GeneratorConfiguration; /** * @brief Interface and implementation to generate boilerplate bindings code for interfacing with DBus services. */ class Generator { public: /** * @brief Specifies the default generator configuration. * @return An instance of the default generator configuration. */ static const GeneratorConfiguration& default_configuration(); /** * @brief Constructs a default generator. */ Generator(); Generator(const Generator&) = delete; virtual ~Generator(); bool operator==(const Generator&) const = delete; Generator& operator=(const Generator&) = delete; /** * @brief Invokes the generator for the supplied root element and configuration. * @param element The root element that the generator should start with. * @param raw_file_contents The raw file contents that the intermediate model has been parsed from. * @param config The configuration of the generator. * @return true if the final binding boilerplate code has been generated successfully, false otherwise. */ virtual bool invoke_for_model_with_configuration( const std::shared_ptr& element, std::istream& raw_file_contents, const GeneratorConfiguration& config = default_configuration()); private: struct Private; std::unique_ptr d; }; } } #endif // CORE_DBUS_GENERATOR_H_ dbus-cpp-5.0.3/include/core/dbus/generator_configuration.h000066400000000000000000000022011407013304700236240ustar00rootroot00000000000000/* * Copyright © 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Thomas Voß */ #ifndef CORE_DBUS_GENERATOR_CONFIGURATION_H_ #define CORE_DBUS_GENERATOR_CONFIGURATION_H_ #include namespace core { namespace dbus { /** * \brief Configuration options and customization points for the code generator. */ struct GeneratorConfiguration { std::function include_guard_generator; std::function build_time_stamp_generator; }; } } #endif // CORE_DBUS_GENERATOR_CONFIGURATION_H_ dbus-cpp-5.0.3/include/core/dbus/helper/000077500000000000000000000000001407013304700200225ustar00rootroot00000000000000dbus-cpp-5.0.3/include/core/dbus/helper/apply_visitor.h000066400000000000000000000032531407013304700231020ustar00rootroot00000000000000/* * Copyright © 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Thomas Voß */ #ifndef CORE_DBUS_HELPER_APPLY_VISITOR_H_ #define CORE_DBUS_HELPER_APPLY_VISITOR_H_ #include #include namespace core { namespace dbus { namespace helper { template inline void apply_visitor(DBusMessageIter* it, Visitor visitor) { ArgumentType type {ArgumentType::invalid}; while ((type = static_cast(dbus_message_iter_get_arg_type(it))) != ArgumentType::invalid) { if (is_compound_type(type)) { visitor(type); DBusMessageIter itt; dbus_message_iter_recurse(it, std::addressof(itt)); apply_visitor(std::addressof(itt), visitor); } else { DBusBasicValue value; dbus_message_iter_get_basic(it, std::addressof(value)); visitor(type, std::addressof(value)); } dbus_message_iter_next(it); } } } } } } #endif // CORE_DBUS_HELPER_APPLY_VISITOR_H_ dbus-cpp-5.0.3/include/core/dbus/helper/is_compound_type.h000066400000000000000000000023001407013304700235460ustar00rootroot00000000000000/* * Copyright © 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Thomas Voß */ #ifndef CORE_DBUS_HELPER_IS_COMPOUND_TYPE_H_ #define CORE_DBUS_HELPER_IS_COMPOUND_TYPE_H_ #include namespace core { namespace dbus { namespace helper { inline bool is_compound_type(ArgumentType type) { switch (type) { case ArgumentType::array: case ArgumentType::structure: case ArgumentType::dictionary_entry: return true; break; default: break; } return false; } } } } } #endif // CORE_DBUS_HELPER_IS_COMPOUND_TYPE_H_ dbus-cpp-5.0.3/include/core/dbus/helper/signature.h000066400000000000000000000024771407013304700222060ustar00rootroot00000000000000/* * Copyright © 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Thomas Voß */ #ifndef CORE_DBUS_HELPER_SIGNATURE_H_ #define CORE_DBUS_HELPER_SIGNATURE_H_ #include #include namespace core { namespace dbus { namespace helper { template inline std::string atomic_signature() { return TypeMapper::signature(); } inline std::string signature() { static const std::string s; return s; } template inline std::string signature(const Arg&, const Args& ... remainder) { static const std::string s = atomic_signature() + signature(remainder...); return s; } } } } #endif // CORE_DBUS_HELPER_SIGNATURE_H_ dbus-cpp-5.0.3/include/core/dbus/helper/type_mapper.h000066400000000000000000000200151407013304700225160ustar00rootroot00000000000000/* * Copyright © 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Thomas Voß */ #ifndef CORE_DBUS_HELPER_TYPE_MAPPER_H_ #define CORE_DBUS_HELPER_TYPE_MAPPER_H_ #include #include #include #include #include #include #include #include #include #include #include namespace core { namespace dbus { namespace types { class Variant; } namespace helper { template struct DBusTypeMapper { }; template<> struct DBusTypeMapper { typedef dbus_bool_t Type; }; template<> struct DBusTypeMapper { typedef uint8_t Type; }; template<> struct DBusTypeMapper { typedef int16_t Type; }; template<> struct DBusTypeMapper { typedef uint16_t Type; }; template<> struct DBusTypeMapper { typedef int32_t Type; }; template<> struct DBusTypeMapper { typedef uint32_t Type; }; template<> struct DBusTypeMapper { typedef int64_t Type; }; template<> struct DBusTypeMapper { typedef uint64_t Type; }; template<> struct DBusTypeMapper { typedef double Type; }; template struct TypeMapper { constexpr inline static ArgumentType type_value(); constexpr inline static bool is_basic_type(); constexpr inline static bool requires_signature(); static inline std::string signature(); }; template<> struct TypeMapper { constexpr inline static ArgumentType type_value() { return ArgumentType::boolean; } constexpr inline static bool is_basic_type() { return true; } constexpr inline static bool requires_signature() { return true; } inline static std::string signature() { return DBUS_TYPE_BOOLEAN_AS_STRING; } }; template<> struct TypeMapper { constexpr inline static ArgumentType type_value() { return ArgumentType::byte; } constexpr inline static bool is_basic_type() { return true; } constexpr inline static bool requires_signature() { return true; } inline static std::string signature() { return DBUS_TYPE_BYTE_AS_STRING; } }; template<> struct TypeMapper { constexpr inline static ArgumentType type_value() { return ArgumentType::int16; } constexpr inline static bool is_basic_type() { return true; } constexpr inline static bool requires_signature() { return true; } inline static std::string signature() { return DBUS_TYPE_INT16_AS_STRING; } }; template<> struct TypeMapper { constexpr inline static ArgumentType type_value() { return ArgumentType::uint16; } constexpr inline static bool is_basic_type() { return true; } constexpr inline static bool requires_signature() { return true; } inline static std::string signature() { return DBUS_TYPE_UINT16_AS_STRING; } }; template<> struct TypeMapper { constexpr inline static ArgumentType type_value() { return ArgumentType::int32; } constexpr inline static bool is_basic_type() { return true; } constexpr inline static bool requires_signature() { return true; } inline static std::string signature() { return DBUS_TYPE_INT32_AS_STRING; } }; template<> struct TypeMapper { constexpr inline static ArgumentType type_value() { return ArgumentType::uint32; } constexpr inline static bool is_basic_type() { return true; } constexpr inline static bool requires_signature() { return true; } inline static std::string signature() { return DBUS_TYPE_UINT32_AS_STRING; } }; template<> struct TypeMapper { constexpr inline static ArgumentType type_value() { return ArgumentType::int64; } constexpr inline static bool is_basic_type() { return true; } constexpr inline static bool requires_signature() { return true; } inline static std::string signature() { return DBUS_TYPE_INT64_AS_STRING; } }; template<> struct TypeMapper { constexpr inline static ArgumentType type_value() { return ArgumentType::uint64; } constexpr inline static bool is_basic_type() { return true; } constexpr inline static bool requires_signature() { return true; } inline static std::string signature() { return DBUS_TYPE_UINT64_AS_STRING; } }; template<> struct TypeMapper { constexpr inline static ArgumentType type_value() { return ArgumentType::floating_point; } constexpr inline static bool is_basic_type() { return true; } constexpr inline static bool requires_signature() { return true; } inline static std::string signature() { return DBUS_TYPE_DOUBLE_AS_STRING; } }; template<> struct TypeMapper { constexpr inline static ArgumentType type_value() { return ArgumentType::floating_point; } constexpr inline static bool is_basic_type() { return true; } constexpr inline static bool requires_signature() { return true; } inline static std::string signature() { return DBUS_TYPE_DOUBLE_AS_STRING; } }; template<> struct TypeMapper { constexpr inline static ArgumentType type_value() { return ArgumentType::object_path; } constexpr inline static bool is_basic_type() { return true; } constexpr inline static bool requires_signature() { return true; } inline static std::string signature() { return DBUS_TYPE_OBJECT_PATH_AS_STRING; } }; template<> struct TypeMapper { constexpr inline static ArgumentType type_value() { return ArgumentType::signature; } constexpr inline static bool is_basic_type() { return true; } constexpr inline static bool requires_signature() { return true; } inline static std::string signature() { return DBUS_TYPE_SIGNATURE_AS_STRING; } }; template<> struct TypeMapper { constexpr inline static ArgumentType type_value() { return ArgumentType::unix_fd; } constexpr inline static bool is_basic_type() { return true; } constexpr inline static bool requires_signature() { return true; } inline static std::string signature() { return DBUS_TYPE_UNIX_FD_AS_STRING; } }; template<> struct TypeMapper { constexpr inline static ArgumentType type_value() { return ArgumentType::variant; } constexpr inline static bool is_basic_type() { return true; } constexpr inline static bool requires_signature() { return true; } inline static std::string signature() { return DBUS_TYPE_VARIANT_AS_STRING; } }; } } } #endif // CORE_DBUS_HELPER_TYPE_MAPPER_H_ dbus-cpp-5.0.3/include/core/dbus/impl/000077500000000000000000000000001407013304700175045ustar00rootroot00000000000000dbus-cpp-5.0.3/include/core/dbus/impl/message.h000066400000000000000000000020261407013304700213010ustar00rootroot00000000000000/* * Copyright © 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Thomas Voß */ #ifndef CORE_DBUS_IMPL_MESSAGE_H_ #define CORE_DBUS_IMPL_MESSAGE_H_ namespace std { template<> struct hash { size_t operator()(const core::dbus::Message::Type& type) const { static const hash h {}; return h(static_cast(type)); } }; } #endif // CORE_DBUS_IMPL_MESSAGE_H_ dbus-cpp-5.0.3/include/core/dbus/impl/object.h000066400000000000000000000322601407013304700211260ustar00rootroot00000000000000/* * Copyright © 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Thomas Voß */ #ifndef CORE_DBUS_IMPL_OBJECT_H_ #define CORE_DBUS_IMPL_OBJECT_H_ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace core { namespace dbus { template inline void Object::emit_signal(const Args& ... args) { auto msg_factory = parent->get_connection()->message_factory(); auto msg = msg_factory->make_signal( object_path.as_string(), traits::Service::interface_name(), Signal::name()); if (!msg) throw std::runtime_error("No memory available to allocate DBus message"); auto writer = msg->writer(); encode_message(writer, args...); parent->get_connection()->send(msg); } template inline Result Object::invoke_method_synchronously(const Args& ... args) { auto msg_factory = parent->get_connection()->message_factory(); auto msg = msg_factory->make_method_call( parent->get_name(), object_path.as_string(), traits::Service::interface_name().c_str(), Method::name()); if (!msg) throw std::runtime_error("No memory available to allocate DBus message"); auto writer = msg->writer(); encode_message(writer, args...); auto reply = parent->get_connection()->send_with_reply_and_block_for_at_most( msg, Method::default_timeout()); return Result::from_message(reply); } template inline Result Object::transact_method(const Args& ... args) { return invoke_method_asynchronously(args...).get(); } template inline std::future> Object::invoke_method_asynchronously(const Args& ... args) { auto msg_factory = parent->get_connection()->message_factory(); auto msg = msg_factory->make_method_call( parent->get_name(), object_path.as_string(), traits::Service::interface_name().c_str(), Method::name()); if (!msg) throw std::runtime_error("No memory available to allocate DBus message"); auto writer = msg->writer(); encode_message(writer, args...); auto pending_call = parent->get_connection()->send_with_reply_and_timeout( msg, Method::default_timeout()); auto promise = std::make_shared>>(); auto future = promise->get_future(); pending_call->then([promise](const Message::Ptr& reply) { promise->set_value(Result::from_message(reply)); }); return future; } template inline void Object::invoke_method_asynchronously_with_callback( std::function&)> cb, const Args& ... args) { auto msg_factory = parent->get_connection()->message_factory(); auto msg = msg_factory->make_method_call( parent->get_name(), object_path.as_string(), traits::Service::interface_name().c_str(), Method::name()); if (!msg) throw std::runtime_error("No memory available to allocate DBus message"); auto writer = msg->writer(); encode_message(writer, args...); auto pending_call = parent->get_connection()->send_with_reply_and_timeout( msg, Method::default_timeout()); pending_call->then([cb](const Message::Ptr& reply) { cb(Result::from_message(reply)); }); } template inline std::shared_ptr> Object::get_property() { typedef Property PropertyType; // Creating a stub property for a remote object/property instance // requires the following steps: // [1.] Look up if we already have a property instance available in the cache, // leveraging the tuple (path, interface, name) as key. // [1.1] If yes: return the property. // [1.2] If no: Create a new proeprty instance and: // [1.2.1] Make it known to the cache. // [1.2.2] Wire it up for property_changed signal receiving. // [1.2.3] Communicate a new match rule to the dbus daemon to enable reception. if (parent->is_stub()) { auto itf = traits::Service::interface_name(); auto name = PropertyDescription::name(); auto ekey = std::make_tuple(path(), itf, name); auto property = Object::property_cache().retrieve_value_for_key(ekey); if (property) { return property; } auto mr = MatchRule() .type(Message::Type::signal) .interface(traits::Service::interface_name()) .member(interfaces::Properties::Signals::PropertiesChanged::name()); property = PropertyType::make_property(shared_from_this()); Object::property_cache().insert_value_for_key(ekey, property); // We only ever do this once per object. std::call_once(add_match_once, [&]() { // [1.2.4] Inform the dbus daemon that we would like to receive the respective signals. add_match(mr); }); // [1.2.2] Enable dispatching of changes. std::weak_ptr wp{property}; property_changed_vtable[std::make_tuple(itf, name)] = [wp](const types::Variant& arg) { if (auto sp = wp.lock()) sp->handle_changed(arg); }; return property; } return PropertyType::make_property(shared_from_this()); } template inline std::map Object::get_all_properties() { return std::move( invoke_method_synchronously< interfaces::Properties::GetAll, std::map >(traits::Service::interface_name()).value()); } template inline const std::shared_ptr> Object::get_signal() { typedef Signal SignalType; auto signal = SignalType::make_signal(shared_from_this(), traits::Service::interface_name(), SignalDescription::name()); return signal; } inline std::shared_ptr Object::add_object_for_path(const types::ObjectPath& path) { return std::shared_ptr(new Object(parent, path)); } template inline void Object::install_method_handler(const MethodHandler& handler) { static const dbus::Object::MethodKey key { dbus::traits::Service::interface_name(), Method::name() }; method_router.install_route(key, handler); } template inline void Object::uninstall_method_handler() { static const dbus::Object::MethodKey key { dbus::traits::Service::interface_name(), Method::name() }; method_router.uninstall_route(key); } inline bool Object::is_stub() const { return parent->is_stub(); } inline bool Object::on_new_message(const Message::Ptr& msg) { return method_router(msg); } inline const types::ObjectPath& Object::path() const { return object_path; } inline Object::Object( const std::shared_ptr parent, const types::ObjectPath& path) : parent(parent), object_path(path), signal_router { [](const Message::Ptr& msg) { return SignalKey {msg->interface(), msg->member()}; } }, method_router { [](const Message::Ptr& msg) { return MethodKey {msg->interface(), msg->member()}; } }, get_property_router { [](const Message::Ptr& msg) { std::string interface, member; msg->reader() >> interface >> member; return PropertyKey{interface, member}; } }, set_property_router { [](const Message::Ptr& msg) { std::string interface, member; msg->reader() >> interface >> member; return PropertyKey {interface, member}; } } { parent->get_connection()->access_signal_router().install_route( object_path, std::bind(&MessageRouter::operator(), std::ref(signal_router), std::placeholders::_1)); if (!parent->is_stub()) { install_method_handler( std::bind( &MessageRouter::operator(), std::ref(get_property_router), std::placeholders::_1)); install_method_handler( std::bind( &MessageRouter::operator(), std::ref(set_property_router), std::placeholders::_1)); } else { // We centrally route org.freedesktop.DBus.Properties.PropertiesChanged // through the object, which in turn routes via a custom Property cache. signal_router.install_route( SignalKey{ traits::Service::interface_name(), interfaces::Properties::Signals::PropertiesChanged::name() }, // Passing 'this' is fine as the lifetime of the signal_router is upper limited // by the lifetime of 'this'. [this](const Message::Ptr& msg) { interfaces::Properties::Signals::PropertiesChanged::ArgumentType arg; msg->reader() >> arg; on_properties_changed(arg); }); } } inline Object::~Object() { parent->get_connection()->access_signal_router().uninstall_route(object_path); parent->get_connection()->unregister_object_path(object_path); auto mr = MatchRule() .type(Message::Type::signal) .interface(traits::Service::interface_name()) .member(interfaces::Properties::Signals::PropertiesChanged::name()); try { remove_match(mr); } catch(...) { // We consciously drop all possible exceptions here. There is hardly // anything we can do about the error anyway. } } inline void Object::add_match(const MatchRule& rule) { parent->add_match(rule.path(object_path)); } inline void Object::remove_match(const MatchRule& rule) { parent->remove_match(rule.path(object_path)); } inline void Object::on_properties_changed( const interfaces::Properties::Signals::PropertiesChanged::ArgumentType& arg) { const auto& interface = std::get<0>(arg); const auto& changed_values = std::get<1>(arg); for (const auto& value : changed_values) { auto it = property_changed_vtable.find(std::make_tuple(interface, value.first)); if (it != property_changed_vtable.end()) { it->second(value.second); } } } template inline core::dbus::ThreadSafeLifetimeConstrainedCache< core::dbus::Object::CacheKey, core::dbus::Property>& core::dbus::Object::property_cache() { static core::dbus::ThreadSafeLifetimeConstrainedCache< core::dbus::Object::CacheKey, core::dbus::Property > cache; return cache; } } } #endif // CORE_DBUS_IMPL_OBJECT_H_ dbus-cpp-5.0.3/include/core/dbus/impl/property.h000066400000000000000000000131131407013304700215400ustar00rootroot00000000000000/* * Copyright © 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Thomas Voß */ #ifndef CORE_DBUS_IMPL_PROPERTY_H_ #define CORE_DBUS_IMPL_PROPERTY_H_ namespace core { namespace dbus { template const typename Property::ValueType& Property::get() const { if (parent->is_stub()) { Super::mutable_get() = parent->invoke_method_synchronously< interfaces::Properties::Get, types::TypedVariant::ValueType> >(interface, name).value().get(); } return Super::get(); } template void Property::set(const typename Property::ValueType& new_value) { if (parent->is_stub()) { if (!writable) { throw std::runtime_error("Property is not writable"); } parent->invoke_method_synchronously< interfaces::Properties::Set, void >(interface, name, types::TypedVariant(new_value)); } Super::set(new_value); } template bool Property::is_writable() const { return writable; } template const core::Signal& Property::about_to_be_destroyed() const { return signal_about_to_be_destroyed; } template std::shared_ptr> Property::make_property(const std::shared_ptr& parent) { return std::shared_ptr>( new Property( parent, traits::Service::interface_name(), PropertyType::name(), PropertyType::writable)); } template Property::Property( const std::shared_ptr& parent, const std::string& interface, const std::string& name, bool writable) : parent(parent), interface(interface), name(name), writable(writable) { if (!parent->is_stub()) { parent->get_property_router.install_route( Object::PropertyKey { traits::Service::interface_name(), PropertyType::name() }, std::bind(&Property::handle_get, this, std::placeholders::_1)); parent->set_property_router.install_route( Object::PropertyKey { traits::Service::interface_name(), PropertyType::name() }, std::bind( &Property::handle_set, this, std::placeholders::_1)); } } template Property::~Property() { try { signal_about_to_be_destroyed(); } catch(...) { // Consciously dropping all exceptions here. // There is hardly anything we can do about it while // tearing down the object anyway. } } template void Property::handle_get(const Message::Ptr& msg) { auto reply = Message::make_method_return(msg); reply->writer() << types::TypedVariant(Super::get()); parent->parent->get_connection()->send(reply); } template void Property::handle_set(const Message::Ptr& msg) { if (!writable) { auto error = Message::make_error( msg, traits::Service::interface_name() + ".NotWritableError", name + "is not writable"); parent->parent->get_connection()->send(error); return; } std::string s; types::TypedVariant value; try { msg->reader() >> s >> s >> value; Super::set(value.get()); } catch (...) { auto error = Message::make_error( msg, traits::Service::interface_name() + ".NotWritableError", name + "is not writable"); parent->parent->get_connection()->send(error); return; } auto reply = Message::make_method_return(msg); parent->parent->get_connection()->send(reply); } template void Property::handle_changed(const types::Variant& arg) { try { auto value = arg.as(); Super::set(value); } catch (const std::exception &e){ std::cout << __PRETTY_FUNCTION__ << ": " << e.what() << std::endl; } catch (...) { std::cout << __PRETTY_FUNCTION__ << ": " << "Unknown exception." << std::endl; } } } } #endif // CORE_DBUS_IMPL_PROPERTY_H_ dbus-cpp-5.0.3/include/core/dbus/impl/signal.h000066400000000000000000000274431407013304700211440ustar00rootroot00000000000000/* * Copyright © 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Thomas Voß */ #ifndef CORE_DBUS_IMPL_SIGNAL_H_ #define CORE_DBUS_IMPL_SIGNAL_H_ #include #include #include namespace core { namespace dbus { template inline Signal::~Signal() noexcept { signal_about_to_be_destroyed(); parent->signal_router.uninstall_route(Object::SignalKey{interface, name}); try { parent->remove_match(rule); } catch (...) { // Intentionally left empty as we do not care about the match rule // not being removed at this point. There is hardly anything we can // do and just assume correct state. } } template inline void Signal::emit(void) { parent->emit_signal(); } template inline typename Signal::SubscriptionToken Signal::connect(const Handler& h) { std::lock_guard lg(handlers_guard); return handlers.insert(handlers.end(), h); } template inline void Signal::disconnect( const typename Signal::SubscriptionToken& token) { std::lock_guard lg(handlers_guard); handlers.erase(token); } template inline const core::Signal& Signal::about_to_be_destroyed() const { return signal_about_to_be_destroyed; } template inline std::shared_ptr> Signal::make_signal( const std::shared_ptr& parent, const std::string& interface, const std::string& name) { typedef std::shared_ptr> SharedSignalPtr; typedef std::tuple SignalCacheKey; typedef Signal SignalCacheValue; typedef ThreadSafeLifetimeConstrainedCache SignalCache; static SignalCache signal_cache; auto key = std::make_tuple(parent->path(), interface, name); auto signal = signal_cache.retrieve_value_for_key(key); if (signal) return signal; signal = SharedSignalPtr( new Signal( parent, interface, name)); signal_cache.insert_value_for_key(key, signal); return signal; } template inline Signal::Signal( const std::shared_ptr& parent, const std::string& interface, const std::string& name) : parent(parent), interface(interface), name(name) { parent->signal_router.install_route( Object::SignalKey {interface, name}, std::bind( &Signal::operator(), this, std::placeholders::_1)); rule = rule.type(Message::Type::signal).interface(interface).member(name); parent->add_match(rule); } template inline void Signal::operator()(const Message::Ptr&) { std::lock_guard lg(handlers_guard); for (auto handler : handlers) handler(); } template inline Signal< SignalDescription, typename std::enable_if< is_not_void::value, typename SignalDescription::ArgumentType>::type >::~Signal() noexcept { d->signal_about_to_be_destroyed(); d->parent->signal_router.uninstall_route( Object::SignalKey{d->interface, d->name}); // Iterate through the unique keys in the map for (auto it = d->handlers.begin(); it != d->handlers.end(); it = d->handlers.upper_bound(it->first)) { const MatchRule::MatchArgs& match_args(it->first); try { d->parent->remove_match(d->rule.args(match_args)); } catch (...) { } } } template inline void Signal< SignalDescription, typename std::enable_if< is_not_void::value, typename SignalDescription::ArgumentType>::type >::emit(const typename SignalDescription::ArgumentType& args) { d->parent->template emit_signal(args); } template inline typename Signal< SignalDescription, typename std::enable_if< is_not_void::value, typename SignalDescription::ArgumentType >::type >::SubscriptionToken Signal< SignalDescription, typename std::enable_if< is_not_void::value, typename SignalDescription::ArgumentType >::type >::connect(const Handler& h) { return connect_with_match_args(h, MatchRule::MatchArgs()); } template inline typename Signal< SignalDescription, typename std::enable_if< is_not_void::value, typename SignalDescription::ArgumentType >::type >::SubscriptionToken Signal< SignalDescription, typename std::enable_if< is_not_void::value, typename SignalDescription::ArgumentType >::type >::connect_with_match_args(const Handler& h, const MatchRule::MatchArgs& match_args) { std::lock_guard lg(d->handlers_guard); bool new_entry = (d->handlers.find(match_args) == d->handlers.cend()); SubscriptionToken token = d->handlers.insert(std::make_pair(match_args, h)); if (new_entry) d->parent->add_match(d->rule.args(match_args)); return token; } template inline void Signal< SignalDescription, typename std::enable_if< is_not_void::value, typename SignalDescription::ArgumentType >::type >::disconnect(const SubscriptionToken& token) { std::lock_guard lg(d->handlers_guard); MatchRule::MatchArgs match_args(token->first); d->handlers.erase(token); if (d->handlers.count(match_args) == 0) { d->parent->remove_match(d->rule.args(match_args)); } } template inline const core::Signal& Signal< SignalDescription, typename std::enable_if< is_not_void::value, typename SignalDescription::ArgumentType >::type >::about_to_be_destroyed() const { return d->signal_about_to_be_destroyed; } template inline std::shared_ptr> Signal< SignalDescription, typename std::enable_if< is_not_void::value, typename SignalDescription::ArgumentType>::type >::make_signal( const std::shared_ptr& parent, const std::string& interface, const std::string& name) { typedef std::shared_ptr> SharedSignalPtr; typedef std::tuple SignalCacheKey; typedef Signal SignalCacheValue; typedef ThreadSafeLifetimeConstrainedCache SignalCache; static SignalCache signal_cache; auto key = std::make_tuple(parent->path(), interface, name); auto signal = signal_cache.retrieve_value_for_key(key); if (signal) return signal; signal = SharedSignalPtr( new Signal( parent, interface, name)); signal_cache.insert_value_for_key(key, signal); return signal; } template inline Signal< SignalDescription, typename std::enable_if< is_not_void::value, typename SignalDescription::ArgumentType>::type >::Signal(const std::shared_ptr& parent, const std::string& interface, const std::string& name) : d{new Shared{parent, interface, name}} { d->parent->signal_router.install_route( Object::SignalKey {interface, name}, std::bind( &Signal::operator(), this, std::placeholders::_1)); d->rule = d->rule.type(Message::Type::signal).interface(interface).member(name); } template inline void Signal< SignalDescription, typename std::enable_if< is_not_void::value, typename SignalDescription::ArgumentType>::type >::operator()(const Message::Ptr& msg) noexcept { try { typename SignalDescription::ArgumentType value; msg->reader() >> value; std::lock_guard lg(d->handlers_guard); for (auto it : d->handlers) { const MatchRule::MatchArgs& match_args(it.first); const Handler &handler(it.second); if (!match_args.empty()) { bool matched = true; for(const MatchRule::MatchArg& arg: match_args) { std::size_t index = arg.first; const std::string& value = arg.second; // FIXME This code is probably bad, it starts reading the arguments // from the beginning each time auto reader = msg->reader(); // Wind the reader forward until we get to the desired point for (std::size_t i(0); i < index && reader.type() != dbus::ArgumentType::invalid; ++i) reader.pop(); if (value != reader.pop_string()) { matched = false; continue; } } if (!matched) continue; } handler(value); } } catch (const std::runtime_error& e) { std::cout << e.what() << std::endl; } } template inline Signal< SignalDescription, typename std::enable_if< is_not_void::value, typename SignalDescription::ArgumentType>::type >::Shared::Shared(const std::shared_ptr& parent, const std::string& interface, const std::string& name) : parent(parent), interface(interface), name(name) { } } } #endif // CORE_DBUS_IMPL_SIGNAL_H_ dbus-cpp-5.0.3/include/core/dbus/interfaces/000077500000000000000000000000001407013304700206665ustar00rootroot00000000000000dbus-cpp-5.0.3/include/core/dbus/interfaces/introspectable.h000066400000000000000000000036031407013304700240570ustar00rootroot00000000000000/* * Copyright © 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Thomas Voß */ #ifndef CORE_DBUS_INTERFACES_INTROSPECTABLE_H_ #define CORE_DBUS_INTERFACES_INTROSPECTABLE_H_ #include #include #include namespace core { namespace dbus { namespace interfaces { class Introspectable { public: virtual ~Introspectable() = default; std::string introspect() { return service->root_object()->invoke_method_synchronously(); } protected: Introspectable(const Service::Ptr& service) : service(service) { } private: struct Introspect { typedef Introspectable Interface; inline static std::string name() { return "Introspect"; } static const bool call_synchronously = true; inline static const std::chrono::milliseconds default_timeout() { return std::chrono::seconds{1}; } }; Service::Ptr service; }; } namespace traits { template<> struct Service { inline static const std::string& interface_name() { static const std::string s{"org.freedesktop.DBus.Introspectable"}; return s; } }; } } } #endif // CORE_DBUS_INTERFACES_INTROSPECTABLE_H_ dbus-cpp-5.0.3/include/core/dbus/interfaces/object_manager.h000066400000000000000000000044271407013304700240060ustar00rootroot00000000000000/* * Copyright © 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Thomas Voß */ #ifndef CORE_DBUS_INTERFACES_OBJECT_MANAGER_H_ #define CORE_DBUS_INTERFACES_OBJECT_MANAGER_H_ #include #include #include #include #include #include #include namespace core { namespace dbus { namespace interfaces { class ObjectManager { public: virtual ~ObjectManager() = default; std::map>>> get_managed_objects() { return service->root_object()->invoke_method_synchronously< GetManagedObjects, std::map>>> >(); } protected: ObjectManager(const Service::Ptr& service) : service(service) { } private: struct GetManagedObjects { typedef ObjectManager Interface; inline static std::string name() { return "GetManagedObjects"; } static const bool call_synchronously = true; inline static const std::chrono::milliseconds default_timeout() { return std::chrono::seconds{1}; } }; Service::Ptr service; }; } namespace traits { template<> struct Service { inline static const std::string& interface_name() { static const std::string s { "org.freedesktop.DBus.ObjectManager" }; return s; } }; } } } #endif // CORE_DBUS_INTERFACES_INTROSPECTABLE_H_ dbus-cpp-5.0.3/include/core/dbus/interfaces/properties.h000066400000000000000000000053501407013304700232360ustar00rootroot00000000000000/* * Copyright © 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Thomas Voß */ #ifndef CORE_DBUS_INTERFACES_PROPERTIES_H_ #define CORE_DBUS_INTERFACES_PROPERTIES_H_ #include #include #include #include namespace core { namespace dbus { namespace interfaces { struct Properties { public: virtual ~Properties() = default; struct GetAll { typedef Properties Interface; inline static const std::string& name() { static const std::string s{"GetAll"}; return s; }; inline static const std::chrono::milliseconds default_timeout() { return std::chrono::seconds{30}; } }; struct Get { typedef Properties Interface; inline static const std::string& name() { static const std::string s{"Get"}; return s; }; inline static const std::chrono::milliseconds default_timeout() { return std::chrono::seconds{30}; } }; struct Set { typedef Properties Interface; inline static const std::string& name() { static const std::string s{"Set"}; return s; }; inline static const std::chrono::milliseconds default_timeout() { return std::chrono::seconds{30}; } }; struct Signals { struct PropertiesChanged { inline static std::string name() { return "PropertiesChanged"; }; typedef Properties Interface; typedef std::tuple< std::string, std::map, std::vector > ArgumentType; }; }; }; } namespace traits { template<> struct Service { inline static const std::string& interface_name() { static const std::string s{"org.freedesktop.DBus.Properties"}; return s; }; }; } } } #endif // CORE_DBUS_INTERFACES_INTROSPECTABLE_H_ dbus-cpp-5.0.3/include/core/dbus/introspection_parser.h000066400000000000000000000167211407013304700231770ustar00rootroot00000000000000/* * Copyright © 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Thomas Voß */ #ifndef CORE_DBUS_INTROSPECTION_PARSER_H_ #define CORE_DBUS_INTROSPECTION_PARSER_H_ #include #include #include namespace core { namespace dbus { /** * @brief Parses the DBus XML introspection file format and maps it to an intermediate code model. */ class IntrospectionParser { public: /** * \brief Models an annotation as parsed from the introspection XML. */ struct Annotation { inline static const char* element_name() { return "annotation"; } inline static const char* name_attribute_name() { return "name"; } inline static const char* value_attribute_name() { return "value"; } std::string name; ///< Name of the annotation, never empty. std::string value; ///< Value of the annotation, never empty. }; /** * \brief Models a node as parsed from the introspection XML. */ struct Node { inline static const char* element_name() { return "node"; } inline static const char* name_attribute_name() { return "name"; } std::string name; ///< Name of the node, never empty. }; /** * \brief Models an interface as parsed from the introspection XML. */ struct Interface { inline static const char* element_name() { return "interface"; } inline static const char* name_attribute_name() { return "name"; } std::string name; ///< Name of the interface, never empty. }; /** * \brief Models an argument as parsed from the introspection XML. */ struct Argument { inline static const char* element_name() { return "arg"; } inline static const char* name_attribute_name() { return "name"; } inline static const char* type_attribute_name() { return "type"; } inline static const char* direction_attribute_name() { return "direction"; } /** * \brief Direction of the argument. */ enum class Direction { context, ///< Direction depends on context, i.e., whether it's an arg to a method or a signal. in, ///< Argument is passed in. out ///< Argument is returned. }; std::string name; ///< Name of the argument, never empty. std::string type; ///< Type of the argument, never empty. Direction direction; ///< Direction of the argument. }; /** * \brief Models a method as parsed from the introspection XML. */ struct Method { inline static const char* element_name() { return "method"; } inline static const char* name_attribute_name() { return "name"; } std::string name; ///< Name of the method, never empty. }; /** * \brief Models a signal as parsed from the introspection XML. */ struct Signal { inline static const char* element_name() { return "signal"; } inline static const char* name_attribute_name() { return "name"; } std::string name; ///< Name of the signal, never empty. }; /** * \brief Models a property as parsed from the introspection XML. */ struct Property { inline static const char* element_name() { return "property"; } inline static const char* name_attribute_name() { return "name"; } inline static const char* type_attribute_name() { return "type"; } inline static const char* access_attribute_name() { return "access"; } /** * \brief Access qualifier. */ enum class Access { read, ///< Property is readable. write, ///< Property is writable. read_write ///< Property is both readable and writable. }; std::string name; ///< Name of the property, never empty. std::string type; ///< Type of the argument, never empty. Access access; ///< Access specification. }; IntrospectionParser(); IntrospectionParser(const IntrospectionParser&) = delete; virtual ~IntrospectionParser(); bool operator==(const IntrospectionParser&) const = delete; IntrospectionParser& operator=(const IntrospectionParser&) = delete; /** * \brief Invokes the parser for the file referred to by filename. * \returns True in case of success, false otherwise. */ virtual bool invoke_for(const std::string& filename); /** * \brief Registers the supplied lambda function which is then invoked for every node. */ virtual void on_node(const std::function& f); /** * \brief Registers the supplied lambda function which is then invoked for every node done. */ virtual void on_node_done(const std::function& f); /** * \brief Registers the supplied lambda function which is then invoked for every interface. */ virtual void on_interface(const std::function& f); /** * \brief Registers the supplied lambda function which is then invoked for every interface done. */ virtual void on_interface_done(const std::function& f); /** * \brief Registers the supplied lambda function which is then invoked for every method. */ virtual void on_method(const std::function& f); /** * \brief Registers the supplied lambda function which is then invoked for every method done. */ virtual void on_method_done(const std::function& f); /** * \brief Registers the supplied lambda function which is then invoked for every property. */ virtual void on_property(const std::function& f); /** * \brief Registers the supplied lambda function which is then invoked for every signal. */ virtual void on_signal(const std::function& f); /** * \brief Registers the supplied lambda function which is then invoked for every signal done. */ virtual void on_signal_done(const std::function& f); /** * \brief Registers the supplied lambda function which is then invoked for every argument. */ virtual void on_argument(const std::function& f); /** * \brief Registers the supplied lambda function which is then invoked for every argument done. */ virtual void on_argument_done(const std::function& f); /** * \brief Registers the supplied lambda function which is then invoked for every annotation. */ virtual void on_annotation(const std::function& f); /** * \brief Registers the supplied lambda function which is then invoked for every annotation done. */ virtual void on_annotation_done(const std::function& f); private: struct Private; std::unique_ptr d; }; } } #endif // CORE_DBUS_INTROSPECTION_PARSER_H_ dbus-cpp-5.0.3/include/core/dbus/lifetime_constrained_cache.h000066400000000000000000000062441407013304700242340ustar00rootroot00000000000000/* * Copyright © 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Thomas Voß */ #ifndef CORE_DBUS_LIFETIME_CONSTRAINED_CACHE_H_ #define CORE_DBUS_LIFETIME_CONSTRAINED_CACHE_H_ #include #include #include #include namespace core { namespace dbus { template struct LifetimeConstraintTraits { static inline const core::Signal& access_signal_object_about_to_be_destroyed(const T& t) { return t.about_to_be_destroyed(); } }; template class ThreadSafeLifetimeConstrainedCache { public: ThreadSafeLifetimeConstrainedCache() = default; ~ThreadSafeLifetimeConstrainedCache() { std::lock_guard lg(guard); for (auto& element : cache) { std::get<1>(element.second).disconnect(); } } ThreadSafeLifetimeConstrainedCache(const ThreadSafeLifetimeConstrainedCache&) = delete; ThreadSafeLifetimeConstrainedCache& operator=(const ThreadSafeLifetimeConstrainedCache&) = delete; inline std::shared_ptr retrieve_value_for_key(const Key& key) { std::lock_guard lg(guard); auto it = cache.find(key); if (it == cache.end()) return std::shared_ptr{}; return std::get<0>(it->second).lock(); } inline bool insert_value_for_key(const Key& key, const std::shared_ptr& value) { std::lock_guard lg(guard); auto it = cache.find(key); if (it != cache.end()) return false; auto connection = LifetimeConstraintTraits::access_signal_object_about_to_be_destroyed(*value).connect([this, key]() { remove_value_for_key(key); }); bool inserted{false}; std::tie(std::ignore, inserted) = cache.insert( std::make_pair( key, std::make_tuple(std::weak_ptr(value), connection))); return inserted; } inline void remove_value_for_key(const Key& key) { std::lock_guard lg(guard); auto it = cache.find(key); if (it == cache.end()) return; cache.erase(it); } inline bool has_value_for_key(const Key& key) const { std::lock_guard lg(guard); return cache.find(key) != cache.end(); } private: mutable std::mutex guard; std::map, core::Connection>> cache; }; } } #endif // CORE_DBUS_LIFETIME_CONSTRAINED_CACHE_H_ dbus-cpp-5.0.3/include/core/dbus/macros.h000066400000000000000000000044121407013304700202010ustar00rootroot00000000000000/* * Copyright © 2014 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Thomas Voß */ #ifndef CORE_DBUS_MACROS_H_ #define CORE_DBUS_MACROS_H_ #include #include #include #define DBUS_CPP_METHOD_WITH_TIMEOUT_DEF(Name, Itf, Timeout) \ struct Name \ { \ typedef Itf Interface; \ inline static const std::string& name() \ { \ static const std::string s{#Name}; \ return s; \ } \ inline static const std::chrono::milliseconds default_timeout() { return std::chrono::milliseconds{Timeout}; } \ };\ #define DBUS_CPP_METHOD_DEF(Name, Itf) DBUS_CPP_METHOD_WITH_TIMEOUT_DEF(Name, Itf, 2000) #define DBUS_CPP_SIGNAL_DEF(Name, Itf, ArgType) \ struct Name \ { \ inline static std::string name() \ { \ return #Name; \ }; \ typedef Itf Interface; \ typedef ArgType ArgumentType; \ };\ #define DBUS_CPP_READABLE_PROPERTY_DEF(Name, Itf, Type) \ struct Name \ { \ inline static std::string name() \ { \ return #Name; \ }; \ typedef Itf Interface; \ typedef Type ValueType; \ static const bool readable = true; \ static const bool writable = false; \ }; \ #define DBUS_CPP_WRITABLE_PROPERTY_DEF(Name, Itf, Type) \ struct Name \ { \ inline static std::string name() \ { \ return #Name; \ }; \ typedef Itf Interface; \ typedef Type ValueType; \ static const bool readable = true; \ static const bool writable = true; \ }; \ #endif // CORE_DBUS_MACROS_H_ dbus-cpp-5.0.3/include/core/dbus/match_rule.h000066400000000000000000000077201407013304700210450ustar00rootroot00000000000000/* * Copyright © 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Thomas Voß */ #ifndef CORE_DBUS_MATCH_RULE_H_ #define CORE_DBUS_MATCH_RULE_H_ #include #include #include #include #include #include namespace core { namespace dbus { /** * @brief Wraps a DBus match rule. */ class ORG_FREEDESKTOP_DBUS_DLL_PUBLIC MatchRule { public: typedef std::pair MatchArg; typedef std::vector MatchArgs; /** * @brief Constructs a valid match rule. */ MatchRule(); ~MatchRule(); MatchRule(const MatchRule& rhs); MatchRule& operator=(const MatchRule& rhs); /** * @brief Adjusts the message type that this rule applies to. * @param t The new type * @return The match rule instance. */ MatchRule& type(Message::Type t); /** * @brief Adjusts the message type that this rule applies to. * @param t The new type * @return A new match rule instance. */ MatchRule type(Message::Type t) const; /** * @brief Adjusts the sender that this rule applies to. * @param s The new sender * @return The match rule instance. */ MatchRule& sender(const std::string& s); /** * @brief Adjusts the sender that this rule applies to. * @param s The new sender * @return A new match rule instance. */ MatchRule sender(const std::string& s) const; /** * @brief Adjusts the interface that this rule applies to. * @param i The new interface. * @return The match rule instance. */ MatchRule& interface(const std::string& i); /** * @brief Adjusts the interface that this rule applies to. * @param i The new interface. * @return A new match rule instance. */ MatchRule interface(const std::string& i) const; /** * @brief Adjusts the member that this rule applies to. * @param m The new member. * @return The match rule instance. */ MatchRule& member(const std::string& m); /** * @brief Adjusts the member that this rule applies to. * @param m The new member. * @return A new match rule instance. */ MatchRule member(const std::string& m) const; /** * @brief Adjusts the path that this rule applies to. * @param p The new path. * @return The match rule instance. */ MatchRule& path(const types::ObjectPath& p); /** * @brief Adjusts the path that this rule applies to. * @param p The new path. * @return A new match rule instance. */ MatchRule path(const types::ObjectPath& p) const; /** * @brief Adjusts the string method arguments that this rule applies to. * @param p The new method arguments. * @return The match rule instance. */ MatchRule& args(const MatchArgs& p); /** * @brief Adjusts the path that this rule applies to. * @param p The new path. * @return A new match rule instance. */ MatchRule& args(const MatchArgs& p) const; /** * @brief Constructs a valid match rule string from this instance. * @return A string formatted according to DBus match rule rules. */ std::string as_string() const; private: struct Private; std::unique_ptr d; }; } } #endif // CORE_DBUS_MATCH_RULE_H_ dbus-cpp-5.0.3/include/core/dbus/message.h000066400000000000000000000315741407013304700203520ustar00rootroot00000000000000/* * Copyright © 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Thomas Voß */ #ifndef CORE_DBUS_MESSAGE_H_ #define CORE_DBUS_MESSAGE_H_ #include #include #include #include #include #include #include #include #include #include namespace core { namespace dbus { template struct Codec; class Error; /** * @brief The Message class wraps a raw DBus message */ class ORG_FREEDESKTOP_DBUS_DLL_PUBLIC Message : public std::enable_shared_from_this { public: typedef std::shared_ptr Ptr; /** * @brief The Type enum models the type of the message. */ enum class Type : int { invalid = DBUS_MESSAGE_TYPE_INVALID, ///< Invalid message type signal = DBUS_MESSAGE_TYPE_SIGNAL, ///< A signal message method_call = DBUS_MESSAGE_TYPE_METHOD_CALL, ///< A method-call message method_return = DBUS_MESSAGE_TYPE_METHOD_RETURN, ///< A method-return message error = DBUS_MESSAGE_TYPE_ERROR ///< An error message. }; /** * @brief The Reader class allows type-safe reading of arguments from a message. */ class Reader { public: Reader(); ~Reader(); Reader(const Reader&) = default; Reader& operator=(const Reader&) = default; Reader(Reader&&); Reader& operator=(Reader&&); /** * @brief Returns the current type. * */ ArgumentType type() const; /** * @brief Advances this view into the message. */ void pop(); /** * @brief Reads a byte from the underlying message. */ std::int8_t pop_byte(); /** * @brief Reads a boolean from the underlying message. */ bool pop_boolean(); /** * @brief Reads an int16 from the underlying message. */ std::int16_t pop_int16(); /** * @brief Reads a uint16 from the underlying message. */ std::uint16_t pop_uint16(); /** * @brief Reads an int32 from the underlying message. */ std::int32_t pop_int32(); /** * @brief Reads a uint32 from the underlying message. */ std::uint32_t pop_uint32(); /** * @brief Reads an int64 from the underlying message. */ std::int64_t pop_int64(); /** * @brief Reads a uint64 from the underlying message. */ std::uint64_t pop_uint64(); /** * @brief Reads a floating point value from the underlying message. */ double pop_floating_point(); /** * @brief Reads a string from the underlying message. */ const char* pop_string(); /** * @brief Reads an object_path from the underlying message. */ types::ObjectPath pop_object_path(); /** * @brief Reads a signature from the underlying message. */ types::Signature pop_signature(); /** * @brief Reads a unix fd from the underlying message. */ types::UnixFd pop_unix_fd(); /** * @brief Prepares reading of an array from the underlying message. * @return A reader pointing to the array. */ Reader pop_array(); /** * @brief Prepares reading of a structure from the underlying message. * @return A reader pointing into the structure. */ Reader pop_structure(); /** * @brief Prepares reading of a variant from the underlying message. * @return A reader pointing into the variant. */ Reader pop_variant(); /** * @brief Prepares reading of a dict entry from the underlying message. * @return A reader pointing to the array. */ Reader pop_dict_entry(); private: friend class Message; explicit Reader(const std::shared_ptr& msg); const std::shared_ptr& access_message(); struct Private; std::shared_ptr d; }; /** * @brief The Writer class allows type-safe serialization of input arguments to a message. */ class Writer { public: ~Writer(); Writer(const Writer&) = delete; Writer& operator=(const Writer&) = delete; Writer(Writer&&); Writer& operator=(Writer&&); /** * @brief Writes a byte to the underlying message. */ void push_byte(std::int8_t value); /** * @brief Writes a boolean to the underlying message. */ void push_boolean(bool value); /** * @brief Writes an int16 to the underlying message. */ void push_int16(std::int16_t value); /** * @brief Writes a uint16 to the underlying message. */ void push_uint16(std::uint16_t value); /** * @brief Writes an int32 to the underlying message. */ void push_int32(std::int32_t value); /** * @brief Writes a uint32 to the underlying message. */ void push_uint32(std::uint32_t value); /** * @brief Writes an int64 to the underlying message. */ void push_int64(std::int64_t value); /** * @brief Writes a uint64 to the underlying message. */ void push_uint64(std::uint64_t value); /** * @brief Writes a floating point value to the underlying message. */ void push_floating_point(double value); /** * @brief Writes a string to the underlying message. */ void push_stringn(const char* value, std::size_t size); /** * @brief Writes an object_path to the underlying message. */ void push_object_path(const types::ObjectPath& value); /** * @brief Writes a signature to the underlying message. */ void push_signature(const types::Signature& value); /** * @brief Writes a unix fd to the underlying message. */ void push_unix_fd(const types::UnixFd& value); /** * @brief Prepares writing of an array to the underlying message. * @param [in] signature The signature of the contained data type. */ Writer open_array(const types::Signature& signature); /** * @brief Finalizes writing of an array to the underlying message. */ void close_array(Writer writer); /** * @brief Prepares writing of a structure to the underlying message. */ Writer open_structure(); /** * @brief Finalizes writing of a structure to the underlying message. */ void close_structure(Writer writer); /** * @brief Prepares writing of a variant to the underlying message. * @param [in] signature The signature of the contained data type. */ Writer open_variant(const types::Signature& signature); /** * @brief Finalizes writing of a variant to the underlying message. */ void close_variant(Writer writer); /** * @brief Prepares writing of a dict entry to the underlying message. */ Writer open_dict_entry(); /** * @brief Finalizes writing of a dict entry to the underlying message. */ void close_dict_entry(Writer writer); private: friend class Message; explicit Writer(const std::shared_ptr& msg); struct Private; std::unique_ptr d; }; /** * @brief make_method_call creates an instance of Message with type Type::method_call. * @param destination The name of the remote service to send the message to. * @param path The name of the remote object to send the message to. * @param interface The interface to route the message to. * @param method The actual method that should be invoked * @return An instance of message of type Type::method_call. * @throw std::runtime_error if any of the parameters violates the DBus specification. */ static std::shared_ptr make_method_call( const std::string& destination, const types::ObjectPath& path, const std::string& interface, const std::string& method); /** * @brief make_method_return creates a message instance in response to a raw DBus message of type method-call. * @param msg The message to reply to, must not be null. Must be of type Type::method_call. * @return An instance of message of type Type::method_return. */ static std::shared_ptr make_method_return(const Message::Ptr& msg); /** * @brief make_signal creates a message instance wrapping a signal emission. * @param path The path of the object emitting the signal. * @param interface The interface containing the signal. * @param signal The actual signal name. * @return An instance of message of type Type::signal. */ static std::shared_ptr make_signal( const std::string& path, const std::string& interface, const std::string& signal); /** * @brief make_error creates an error message instance in response to a raw DBus message of type method-call. * @param in_reply_to The message to reply to, must not be null. Must be of type Type::method_call. * @param error_name The name of the error. * @param error_desc Human-readable description of the error. * @return An instance of message of type Type::error. */ static std::shared_ptr make_error( const Message::Ptr& in_reply_to, const std::string& error_name, const std::string& error_desc); /** * @brief from_raw_message creates an instance of message from a raw message. * @param msg The message to wrap. * @return An instance of Message with a type corresponding to the type of the raw message. */ static std::shared_ptr from_raw_message(DBusMessage* msg); ~Message(); /** * @brief Queries the type of the message. */ Type type() const; /** * @brief Checks if the message expects a reply, i.e., is of type Type::method_call. */ bool expects_reply() const; /** * @brief Queries the path of the object that this message belongs to. */ types::ObjectPath path() const; /** * @brief Queries the member name that this message corresponds to. */ std::string member() const; /** * @brief Queries the type signature of this message. */ std::string signature() const; /** * @brief Queries the interface name that this message corresponds to. */ std::string interface() const; /** * @brief Queries the name of the destination that this message should go to. */ std::string destination() const; /** * @brief Queries the name of the sender that this message originates from. */ std::string sender() const; /** * @brief Extracts error information from the message. * @throw std::runtime_error if not an error message. */ Error error() const; /** * @brief Creates a Reader instance to read from this message. */ Reader reader(); /** * @brief Creates a Writer instance to write to this message. */ Writer writer(); /** * @brief Meant for testing purposes only. */ void ensure_serial_larger_than_zero_for_testing(); private: friend class Bus; std::shared_ptr clone(); struct Private; std::unique_ptr d; Message(std::unique_ptr d); }; typedef std::shared_ptr MessagePtr; typedef std::unique_ptr MessageUPtr; ORG_FREEDESKTOP_DBUS_DLL_PUBLIC std::ostream& operator<<(std::ostream&, Message::Type); } } namespace std { template<> struct hash { size_t operator()(const core::dbus::Message::Type& type) const { static const hash h {}; return h(static_cast(type)); } }; } #endif // CORE_DBUS_MESSAGE_H_ dbus-cpp-5.0.3/include/core/dbus/message_factory.h000066400000000000000000000065171407013304700221000ustar00rootroot00000000000000/* * Copyright © 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Thomas Voß */ #ifndef CORE_DBUS_MESSAGE_FACTORY_H_ #define CORE_DBUS_MESSAGE_FACTORY_H_ #include #include #include namespace core { namespace dbus { class MessageFactory { public: MessageFactory(const MessageFactory&) = delete; virtual ~MessageFactory() = default; MessageFactory& operator=(const MessageFactory&) = delete; bool operator==(const MessageFactory&) const = delete; /** * @brief make_method_call creates an instance of Message with type Type::method_call. * @param destination The name of the remote service to send the message to. * @param path The name of the remote object to send the message to. * @param interface The interface to route the message to. * @param method The actual method that should be invoked * @return An instance of message of type Type::method_call. * @throw std::runtime_error if any of the parameters violates the DBus specification. */ virtual MessagePtr make_method_call( const std::string& destination, const types::ObjectPath& path, const std::string& interface, const std::string& method) = 0; /** * @brief make_method_return creates a message instance in response to a raw DBus message of type method-call. * @param msg The message to reply to, must not be null. Must be of type Type::method_call. * @return An instance of message of type Type::method_return. */ virtual MessagePtr make_method_return(const MessagePtr& msg) = 0; /** * @brief make_signal creates a message instance wrapping a signal emission. * @param path The path of the object emitting the signal. * @param interface The interface containing the signal. * @param signal The actual signal name. * @return An instance of message of type Type::signal. */ virtual MessagePtr make_signal( const std::string& path, const std::string& interface, const std::string& signal) = 0; /** * @brief make_error creates an error message instance in response to a raw DBus message of type method-call. * @param in_reply_to The message to reply to, must not be null. Must be of type Type::method_call. * @param error_name The name of the error. * @param error_desc Human-readable description of the error. * @return An instance of message of type Type::error. */ virtual MessagePtr make_error( const MessagePtr& in_reply_to, const std::string& error_name, const std::string& error_desc) = 0; protected: MessageFactory() = default; }; } } #endif // CORE_DBUS_MESSAGE_FACTORY_H_ dbus-cpp-5.0.3/include/core/dbus/message_router.h000066400000000000000000000061711407013304700217450ustar00rootroot00000000000000/* * Copyright © 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Thomas Voß */ #ifndef CORE_DBUS_MESSAGE_ROUTER_H_ #define CORE_DBUS_MESSAGE_ROUTER_H_ #include #include #include #include #include #include namespace core { namespace dbus { /** * @brief Takes a raw DBus message and routes it to a handler. */ template class MessageRouter { public: /** * @brief Mapper takes a raw DBus Message and maps it to the Key type of the router. */ typedef std::function Mapper; /** * @brief Handler is a function type that handles raw DBus messages. */ typedef std::function Handler; /** * @brief Constructs an empty router with the specified mapper instance. * @param m An object of type Mapper. */ inline explicit MessageRouter(const Mapper& m) : mapper(m) { } MessageRouter(const MessageRouter&) = delete; MessageRouter& operator=(const MessageRouter&) = delete; /** * @brief Installs a route for a specific key in a thread-safe manner, replacing any previously installed route. * @param key The key to install the route for. * @param handler The handler to install, must not be empty. */ inline void install_route(const Key& key, Handler handler) { std::unique_lock ul(guard); router[key] = handler; } /** * @brief Uninstalls a route for a specific key in a thread-safe manner. * @param key The key to uninstall the route for. */ inline void uninstall_route(const Key& key) { std::unique_lock ul(guard); router.erase(key); } /** * @brief Maps and routes a raw DBus message in a thread-safe manner. * @param msg The message to map and route, must not be null. * @return true if the message has been routes successfully, false otherwise. */ inline bool operator()(const Message::Ptr& msg) { std::unique_lock ul(guard); auto it = router.find(mapper(msg)); if (it != router.end()) { // release the lock so that Handler can modify the Router Handler handler = it->second; ul.unlock(); handler(msg); return true; } return false; } private: std::mutex guard; Mapper mapper; std::unordered_map router; }; } } #endif // CORE_DBUS_MESSAGE_ROUTER_H_ dbus-cpp-5.0.3/include/core/dbus/message_streaming_operators.h000066400000000000000000000022701407013304700245100ustar00rootroot00000000000000/* * Copyright © 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Thomas Voß */ #ifndef CORE_DBUS_MESSAGE_STREAMING_OPERATORS_H_ #define CORE_DBUS_MESSAGE_STREAMING_OPERATORS_H_ #include namespace core { namespace dbus { template Message::Reader operator>>(Message::Reader reader, T& out) { decode_argument(reader, out); return reader; } template Message::Writer operator<<(Message::Writer writer, const T& out) { encode_argument(writer, out); return writer; } } } #endif // CORE_DBUS_MESSAGE_STREAMING_OPERATORS_H_ dbus-cpp-5.0.3/include/core/dbus/object.h000066400000000000000000000211211407013304700201570ustar00rootroot00000000000000/* * Copyright © 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Thomas Voß */ #ifndef CORE_DBUS_OBJECT_H_ #define CORE_DBUS_OBJECT_H_ #include #include #include #include #include #include #include #include #include #include namespace std { /** * @brief Template specialization of std::hash for a std::tuple. */ template<> struct hash> { size_t operator()(const std::tuple& key) const { static const std::hash h {}; // Using XOR as we do not expect first and second to be equal. return h(std::get<0>(key)) ^ h(std::get<1>(key)); } }; /** * @brief Pretty prints a std::tuple. * @param out The output stream to write to. * @param tuple The tuple to print. * @return Returns a reference to the output stream. */ inline std::ostream& operator<<(std::ostream& out, const std::tuple& tuple) { out << "(" << std::get<0>(tuple) << "," << std::get<1>(tuple) << ")"; return out; } } namespace core { namespace dbus { namespace types { class Any; class ObjectPath; class Variant; } class MatchRule; template class Property; template class Result; template class Signal; /** * @brief The Object class models a DBus object living on the bus. */ class Object : public std::enable_shared_from_this { private: typedef std::tuple CacheKey; typedef std::tuple MethodKey; typedef std::tuple PropertyKey; typedef std::tuple SignalKey; template static ThreadSafeLifetimeConstrainedCache>& property_cache(); public: typedef std::shared_ptr Ptr; typedef std::function MethodHandler; ~Object(); /** * @brief Emits a signal with arguments for this object. */ template inline void emit_signal(const Args& ... args); /** * @brief Invokes a method of a remote object blocking the bus instance while waiting for the result. * @tparam Method The method to invoke. * @tparam ResultType The expected type of the result. * @tparam Args Parameter pack of arguments passed to the invocation. * @param [in] args Argument instances passed to the invocation. * @return An invocation result, either signalling an error or containing the result of the invocation. */ template inline Result invoke_method_synchronously(const Args& ... args); /** * @brief Invokes a method of a remote object blocking the current thread while waiting for the result. * @tparam Method The method to invoke. * @tparam ResultType The expected type of the result. * @tparam Args Parameter pack of arguments passed to the invocation. * @param [in] args Argument instances passed to the invocation. * @return A future wrapping an invocation result, either signalling an error or containing the result of the invocation. */ template inline Result transact_method(const Args& ... args); /** * @brief Invokes a method of a remote object returning a std::future to synchronize with the result * @tparam Method The method to invoke. * @tparam ResultType The expected type of the result. * @tparam Args Parameter pack of arguments passed to the invocation. * @param [in] args Argument instances passed to the invocation. * @return A future wrapping an invocation result, either signalling an error or containing the result of the invocation. */ template inline std::future> invoke_method_asynchronously(const Args& ... args); /** * @brief Invokes a method of a remote object invoking the provided callback on completion or in case of errors. * @tparam Method The method to invoke. * @tparam ResultType The expected type of the result. * @tparam Args Parameter pack of arguments passed to the invocation. * @param [in] args Argument instances passed to the invocation. * @param [in] cb The callback to be invoked on completion/on error. * @return A future wrapping an invocation result, either signalling an error or containing the result of the invocation. */ template inline void invoke_method_asynchronously_with_callback( std::function&)> cb, const Args& ... args); /** * @brief Accesses a property of the object. * @return An instance of the property or nullptr in case of errors. */ template std::shared_ptr> inline get_property(); /** * @brief Queries all properties in one go for the object. */ template inline std::map get_all_properties(); /** * @brief Accesses a signal of the object. * @return An instance of the signal or nullptr in case of errors. */ template const std::shared_ptr> inline get_signal(); /** * @brief Adds an object as a child of this object. * @param [in] path The path to associate the object with. * @return An object instance or nullptr in case of errors. */ std::shared_ptr inline add_object_for_path(const types::ObjectPath& path); /** * @brief Installs an implementation for a specific method of this object instance. * @tparam Method The method to install the implementation for. * @param [in] handler The implementation. */ template inline void install_method_handler(const MethodHandler& handler); /** * @brief Uninstalls an implementation for a specific method of this object instance. * @tparam Method The method to uninstall the implementation for. */ template inline void uninstall_method_handler(); /** * @brief Queries whether this object is a stub instance. * @return true if this object is a stub instance, false otherwise. */ inline bool is_stub() const; /** * @brief Requests the object to process a message * @param msg The message to be processed. * @return true iff the msg has been handled. */ inline bool on_new_message(const Message::Ptr& msg); /** * @return object path of the Object */ inline const types::ObjectPath& path() const; private: friend class Service; template friend class Signal; template friend class Property; Object(const std::shared_ptr parent, const types::ObjectPath& path); void add_match(const MatchRule& rule); void remove_match(const MatchRule& rule); void on_properties_changed( const interfaces::Properties::Signals::PropertiesChanged::ArgumentType&); std::shared_ptr parent; types::ObjectPath object_path; MessageRouter signal_router; MessageRouter method_router; MessageRouter get_property_router; MessageRouter set_property_router; std::once_flag add_match_once; std::map< std::tuple, std::function > property_changed_vtable; }; } } #include "impl/object.h" #endif // CORE_DBUS_OBJECT_H_ dbus-cpp-5.0.3/include/core/dbus/pending_call.h000066400000000000000000000042451407013304700213400ustar00rootroot00000000000000/* * Copyright © 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Thomas Voß */ #ifndef CORE_DBUS_PENDING_CALL_H_ #define CORE_DBUS_PENDING_CALL_H_ #include #include #include #include #include namespace core { namespace dbus { class Message; /** * @brief The PendingCall class wraps an active call to a remote peer. */ class ORG_FREEDESKTOP_DBUS_DLL_PUBLIC PendingCall { public: /** * @brief Timeout constant for a call that never times out. */ inline static const std::chrono::milliseconds& inifinite_timeout() { static const std::chrono::milliseconds ms { std::numeric_limits::max() }; return ms; } typedef std::shared_ptr Ptr; /** @brief Function signature callback for call completion notification. */ typedef std::function&)> Notification; PendingCall(const PendingCall&) = delete; virtual ~PendingCall() = default; PendingCall& operator=(const PendingCall&) = delete; bool operator==(const PendingCall&) const = delete; /** * @brief Cancels the outstanding call. */ virtual void cancel() = 0; /** * @brief Sets up notification as the callback when the call eventually completes. * @param notification The function to be called when the call completes. */ virtual void then(const Notification& notification) = 0; protected: PendingCall() = default; }; } } #endif // CORE_DBUS_PENDING_CALL_H_ dbus-cpp-5.0.3/include/core/dbus/property.h000066400000000000000000000051771407013304700206120ustar00rootroot00000000000000/* * Copyright © 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Thomas Voß */ #ifndef CORE_DBUS_PROPERTY_H_ #define CORE_DBUS_PROPERTY_H_ #include #include #include #include #include namespace core { namespace dbus { class Object; /** * @brief Models a DBus property. * @tparam PropertyType Underlying value type of the property. */ template class Property : public core::Property { public: typedef typename PropertyType::ValueType ValueType; typedef core::Property Super; inline ~Property(); /** * @brief Non-mutable access to the contained value. * @return Non-mutable reference to the contained value. */ inline const ValueType& get() const; /** * @brief Adjusts the contained value * @param [in] new_value New value of the property. */ inline void set(const ValueType& new_value); /** * @brief Queries whether the property is writable. * @return true if the property is writable, false otherwise. */ inline bool is_writable() const; /** * @brief Emitted during destruction of an object instance. */ inline const core::Signal& about_to_be_destroyed() const; protected: friend class Object; inline static std::shared_ptr> make_property( const std::shared_ptr& parent); private: inline Property( const std::shared_ptr& parent, const std::string& interface, const std::string& name, bool writable); inline void handle_get(const Message::Ptr& msg); inline void handle_set(const Message::Ptr& msg); inline void handle_changed(const types::Variant& msg); std::shared_ptr parent; std::string interface; std::string name; bool writable; core::Signal signal_about_to_be_destroyed; }; } } #include "impl/property.h" #endif // CORE_DBUS_PROPERTY_H_ dbus-cpp-5.0.3/include/core/dbus/resolver.h000066400000000000000000000025571407013304700205660ustar00rootroot00000000000000/* * Copyright © 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Thomas Voß */ #ifndef CORE_DBUS_RESOLVER_H_ #define CORE_DBUS_RESOLVER_H_ #include #include namespace core { namespace dbus { /** * @brief Resolves an interface on the bus and creates a proxy object for it. * @tparam Interface The interface to be resolved on the bus. * @tparam ServiceStub The stub or proxy wrapping access to the interface. */ template typename ServiceStub::Ptr resolve_service_on_bus(const Bus::Ptr& bus) { static_assert(std::is_base_of, ServiceStub>::value, "Not a stub"); return typename ServiceStub::Ptr(new ServiceStub(bus)); } } } #endif // CORE_DBUS_RESOLVER_H_ dbus-cpp-5.0.3/include/core/dbus/result.h000066400000000000000000000102731407013304700202350ustar00rootroot00000000000000/* * Copyright © 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Thomas Voß */ #ifndef CORE_DBUS_RESULT_H_ #define CORE_DBUS_RESULT_H_ #include #include #include #include #include namespace core { namespace dbus { /** * @brief Wraps a remote method invocation, its error state and result. * @tparam T Result type. */ template class Result { public: /** * @brief from_message parses the result from a raw dbus message. * @throw std::runtime_error in case of errors. * @param message The message to parse the result from. */ inline static Result from_message(const Message::Ptr& message) { Result result; switch(message->type()) { case Message::Type::method_call: throw std::runtime_error("Cannot construct result from method call"); break; case Message::Type::signal: throw std::runtime_error("Cannot construct result from signal"); break; case Message::Type::error: result.d.error = message->error(); break; case Message::Type::method_return: message->reader() >> result.d.value; break; default: break; } return result; } /** * @brief Check if the result is an error. * @return true if the invocation returned an error, false otherwise. */ inline bool is_error() const { return static_cast(d.error); } /** * @brief Accesses the contained error message if any. * @return A string describing the error state. Can be empty if no error occured. */ inline const Error& error() const { return d.error; } /** * @brief Non-mutable access to the contained value. * @return A non-mutable reference to the contained value. */ inline const T& value() const { return d.value; } private: struct Private { Error error; T value; } d; }; /** * @brief Wraps a remote method invocation and its error state. Template specialization for void results. */ template<> class Result { public: /** * @brief from_message parses the result from a raw dbus message. * @throw std::runtime_error in case of errors. * @param message The message to parse the result from. */ inline static Result from_message(const Message::Ptr& message) { Result result; switch(message->type()) { case Message::Type::method_call: throw std::runtime_error("Cannot construct result from method call"); break; case Message::Type::signal: throw std::runtime_error("Cannot construct result from signal"); break; case Message::Type::error: result.d.error = message->error(); break; case Message::Type::method_return: default: break; } return result; } /** * @brief Check if the result is an error. * @return true if the invocation returned an error, false otherwise. */ inline bool is_error() const { return static_cast(d.error); } /** * @brief Accesses the contained error message if any. * @return A string describing the error state. Can be empty if no error occured. */ inline const Error& error() const { return d.error; } private: struct Private { Error error; } d; }; } } #endif // CORE_DBUS_RESULT_H_ dbus-cpp-5.0.3/include/core/dbus/service.h000066400000000000000000000140551407013304700203610ustar00rootroot00000000000000/* * Copyright © 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Thomas Voß */ #ifndef CORE_DBUS_SERVICE_H_ #define CORE_DBUS_SERVICE_H_ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace core { namespace dbus { class Object; /** * \brief Represents a service available on the bus. * \example geoclue/main.cpp * Provides an example of accessing the Geoclue session service on the bus. * \example upower/main.cpp * Provides an example of access the UPower system service on the bus. */ class ORG_FREEDESKTOP_DBUS_DLL_PUBLIC Service : public std::enable_shared_from_this { public: typedef std::shared_ptr Ptr; /** * @brief Exposes a service on the bus, trying to acquire the given name. * @returns An instance of Service or nullptr in case of errors. * @tparam Interface Needs to a model of concept Service. * @param [in] connection Bus to expose the service upon. * @param [in] name The name to acquire for this service. * @param [in] flags Flags specifying behavior when requesting a name on the bus. */ inline static Ptr add_service( const Bus::Ptr& connection, const std::string& name, const Bus::RequestNameFlag& flags = Bus::RequestNameFlag::do_not_queue | Bus::RequestNameFlag::replace_existing) { Ptr instance( new Service( connection, name, flags)); return instance; } /** * @brief Exposes a service on the bus. * @returns An instance of Service or nullptr in case of errors. * @tparam Interface Needs to a model of concept Service. * @param [in] connection Bus to expose the service upon. * @param [in] flags Flags specifying behavior when requesting a name on the bus. */ template inline static Ptr add_service( const Bus::Ptr& connection, const Bus::RequestNameFlag& flags = Bus::RequestNameFlag::do_not_queue | Bus::RequestNameFlag::replace_existing) { static Ptr instance { add_service(connection, traits::Service::interface_name(), flags) }; return instance; } /** * @brief Provides access to a service on the bus via a proxy object. * @returns An instance of Service or nullptr in case of errors. * @tparam Interface Needs to be a model of concept Service. * @param [in] connection Bus to access the service upon. */ template inline static Ptr use_service(const Bus::Ptr& connection) { return use_service(connection, traits::Service::interface_name()); } /** * @brief Provides access to a service on the bus via a proxy object. * @returns An instance of Service or nullptr in case of errors. * @param [in] connection Bus to access the service upon. * @param [in] name Well-known name of the service on the bus. */ static Ptr use_service(const Bus::Ptr& connection, const std::string& name); /** * @brief Provides access to a service on the bus via a proxy object. * @returns An instance of Service. * @throw std::runtime_error in case of errors. * @param [in] connection Bus to access the service upon. * @param [in] name Well-known name of the service on the bus. */ static Ptr use_service_or_throw_if_not_available(const Bus::Ptr& connection, const std::string& name); /** * @brief Provides access to the root object of this service instance. */ const std::shared_ptr& root_object(); /** * @brief Access an existing object on the specified path. * @param [in] path The path to access the object upon. * @return An instance to the object or nullptr if no object on that path exists. */ std::shared_ptr object_for_path(const types::ObjectPath& path); /** * @brief Adds a new object on the specified path. * @param [in] path The path to mount the object upon. * @return An instance to the object or nullptr if the object could not be added. */ std::shared_ptr add_object_for_path(const types::ObjectPath& path); /** * @brief Non-mutable access to the name of the service. */ const std::string& get_name() const; protected: friend class Bus; friend class Object; template friend class Property; Service(const Bus::Ptr& connection, const std::string& name); Service(const Bus::Ptr& connection, const std::string& name, const Bus::RequestNameFlag& flags); bool is_stub() const; const Bus::Ptr& get_connection() const; void add_match(const MatchRule& rule); void remove_match(const MatchRule& rule); private: Bus::Ptr connection; std::string name; std::shared_ptr root; bool stub; }; } } #endif // CORE_DBUS_SERVICE_H_ dbus-cpp-5.0.3/include/core/dbus/service_watcher.h000066400000000000000000000042531407013304700220750ustar00rootroot00000000000000/* * Copyright © 2014 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Pete Woods */ #ifndef CORE_DBUS_SERVICE_WATCHER_H_ #define CORE_DBUS_SERVICE_WATCHER_H_ #include #include #include #include #include namespace core { namespace dbus { class Object; /** * @brief Allows watching for bus name owner changes. */ class ORG_FREEDESKTOP_DBUS_DLL_PUBLIC ServiceWatcher { friend DBus; public: typedef std::shared_ptr Ptr; ServiceWatcher(const ServiceWatcher& rhs) = delete; ServiceWatcher& operator=(const ServiceWatcher& rhs) = delete; bool operator==(const ServiceWatcher&) const = delete; /** * @brief Emitted when DBus detects that an owner change has occurred for the specified name. * @return Signal instance */ const core::Signal& owner_changed() const; /** * @brief Emitted when DBus detects that an owner has been registered for the specified name. * @return Signal instance */ const core::Signal& service_registered() const; /** * @brief Emitted when DBus detects that an owner has been unregistered for the specified name. * @return Signal instance */ const core::Signal& service_unregistered() const; private: ServiceWatcher(std::shared_ptr object, const std::string& name, DBus::WatchMode watch_mode = DBus::WatchMode::owner_change); struct Private; std::shared_ptr d; }; } } #endif // CORE_DBUS_SERVICE_WATCHER_H_ dbus-cpp-5.0.3/include/core/dbus/signal.h000066400000000000000000000144201407013304700201720ustar00rootroot00000000000000/* * Copyright © 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Thomas Voß */ #ifndef CORE_DBUS_SIGNAL_H_ #define CORE_DBUS_SIGNAL_H_ #include #include #include #include #include #include #include #include #include namespace core { namespace dbus { class Object; template struct is_not_void { static const bool value = true; }; template<> struct is_not_void { static const bool value = false; }; /** * @brief Template class Signal models a type-safe DBus signal. * @tparam SignalDescription Needs to be a model of concept SignalDescription. * @tparam Argument The type of the argument that is emitted by this signal. */ template class Signal { public: typedef std::shared_ptr> Ptr; /** * @brief Handler defines the function signature for change callbacks. */ typedef std::function Handler; /** * @brief SubscriptionToken is a type that refers to a signal-slot connection. */ typedef typename std::list::iterator SubscriptionToken; inline ~Signal() noexcept; /** * @brief Emits the signal. */ inline void emit(void); /** * @brief connect creates a connection to the provided handler. * @param h The handler to be invoked when the signal is emitted. * @return A token that corresponds to the signal-slot connection. */ inline SubscriptionToken connect(const Handler& h); /** * @brief disconnect releases a signal-slot connection * @param token Refers to the signal-slot connection that should be released. */ inline void disconnect(const SubscriptionToken& token); inline const core::Signal& about_to_be_destroyed() const; protected: friend class Object; inline static std::shared_ptr> make_signal( const std::shared_ptr& parent, const std::string& interface, const std::string& name); private: inline Signal(const std::shared_ptr& parent, const std::string& interface, const std::string& name); void operator()(const Message::Ptr&); std::shared_ptr parent; std::string interface; std::string name; MatchRule rule; std::mutex handlers_guard; std::list handlers; core::Signal signal_about_to_be_destroyed; }; /** * @brief Template class Signal models a type-safe DBus signal. * @tparam SignalDescription Needs to be a model of concept SignalDescription. * @tparam Argument The type of the argument that is emitted by this signal. */ template class Signal< SignalDescription, typename std::enable_if< is_not_void::value, typename SignalDescription::ArgumentType>::type > { public: typedef std::shared_ptr> Ptr; /** * @brief Handler defines the function signature for change callbacks. */ typedef std::function Handler; /** * @brief SubscriptionToken is a type that refers to a signal-slot connection. */ typedef typename std::multimap::iterator SubscriptionToken; inline ~Signal() noexcept; /** * @brief Emits the signal with the provided argument. * @param [in] arg The parameter to be passed over to handlers. */ inline void emit(const typename SignalDescription::ArgumentType& arg); /** * @brief connect creates a connection to the provided handler. * @param h The handler to be invoked when the signal is emitted. * @return A token that corresponds to the signal-slot connection. */ inline SubscriptionToken connect(const Handler& h); inline SubscriptionToken connect_with_match_args(const Handler& h, const MatchRule::MatchArgs& match_args); /** * @brief disconnect releases a signal-slot connection * @param token Refers to the signal-slot connection that should be released. */ inline void disconnect(const SubscriptionToken& token); inline const core::Signal& about_to_be_destroyed() const; protected: friend class Object; inline static std::shared_ptr> make_signal( const std::shared_ptr& parent, const std::string& interface, const std::string& name); private: inline Signal( const std::shared_ptr& parent, const std::string& interface, const std::string& name); inline void operator()(const Message::Ptr&) noexcept; struct ORG_FREEDESKTOP_DBUS_DLL_LOCAL Shared { Shared( const std::shared_ptr& parent, const std::string& interface, const std::string& name); // We do not need this member anymore, but keep it in place for // the sake of binary compatibility. Leaving a TODO(tvoss) to clean // up on next ABI bump. typename SignalDescription::ArgumentType pad; std::shared_ptr parent; std::string interface; std::string name; MatchRule rule; std::mutex handlers_guard; std::multimap handlers; core::Signal signal_about_to_be_destroyed; }; std::shared_ptr d; }; } } #include "impl/signal.h" #endif // CORE_DBUS_SIGNAL_H_ dbus-cpp-5.0.3/include/core/dbus/skeleton.h000066400000000000000000000040651407013304700205450ustar00rootroot00000000000000/* * Copyright © 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Thomas Voß */ #ifndef CORE_DBUS_SKELETON_H_ #define CORE_DBUS_SKELETON_H_ #include #include #include namespace core { namespace dbus { /** * @brief Skeleton is a template class that helps with exposing interface implementations on the bus. * @tparam T The type of the interface for which we want to expose an implementation for. */ template class ORG_FREEDESKTOP_DBUS_DLL_PUBLIC Skeleton : public T { public: virtual ~Skeleton() noexcept = default; protected: /** * @brief Skeleton announces the service on the given bus instance. * @param bus The bus that the actual service lives upon */ inline explicit Skeleton(const Bus::Ptr& bus) : bus(bus), service(Service::add_service(bus)) { } /** * @brief access_bus provides access to the underlying bus instance. * @return A mutable reference to the underlying bus. */ inline const Bus::Ptr& access_bus() const { return bus; } /** * @brief Provides access to the underlying service object that this object is a proxy for. * @return A mutable reference to the underlying service object. */ inline const Service::Ptr& access_service() const { return service; } private: Bus::Ptr bus; Service::Ptr service; }; } } #endif // CORE_DBUS_SKELETON_H_ dbus-cpp-5.0.3/include/core/dbus/stub.h000066400000000000000000000045051407013304700176750ustar00rootroot00000000000000/* * Copyright © 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Thomas Voß */ #ifndef CORE_DBUS_STUB_H_ #define CORE_DBUS_STUB_H_ #include #include #include #include namespace core { namespace dbus { /** * @brief Stub is a template class that helps with accessing proxy objects on the bus. * @tparam T The type of the interface for which we want to access a proxy for. */ template class ORG_FREEDESKTOP_DBUS_DLL_PUBLIC Stub : public T { public: virtual ~Stub() noexcept(true) = default; protected: /** * @brief Stub creates a proxy for the service on the given bus instance. * @param bus The bus that the actual service lives upon */ inline explicit Stub(const Bus::Ptr& bus) : bus(bus), service(Service::use_service(bus)), root(service->root_object()) { } /** * @brief access_bus provides access to the underlying bus instance. * @return A mutable reference to the underlying bus. */ inline const Bus::Ptr& access_bus() const { return bus; } /** * @brief Provides access to the root object of the service. * @return A mutable reference to the root object. */ inline const Object::Ptr& access_root() const { return root; } /** * @brief Provides access to the underlying service object that this object is a proxy for. * @return A mutable reference to the underlying service object. */ inline const Service::Ptr& access_service() const { return service; } private: Bus::Ptr bus; Service::Ptr service; Object::Ptr root; }; } } #endif // CORE_DBUS_STUB_H_ dbus-cpp-5.0.3/include/core/dbus/traits/000077500000000000000000000000001407013304700200515ustar00rootroot00000000000000dbus-cpp-5.0.3/include/core/dbus/traits/service.h000066400000000000000000000020211407013304700216550ustar00rootroot00000000000000/* * Copyright © 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Thomas Voß */ #ifndef CORE_DBUS_TRAITS_SERVICE_H_ #define CORE_DBUS_TRAITS_SERVICE_H_ #include namespace core { namespace dbus { namespace traits { template struct Service { static const std::string& interface_name() { return Interface::name(); } }; } } } #endif // CORE_DBUS_TRAITS_SERVICE_H_ dbus-cpp-5.0.3/include/core/dbus/traits/timeout.h000066400000000000000000000022601407013304700217100ustar00rootroot00000000000000/* * Copyright © 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Thomas Voß */ #ifndef CORE_DBUS_TRAITS_TIMEOUT_H_ #define CORE_DBUS_TRAITS_TIMEOUT_H_ #include namespace core { namespace dbus { namespace traits { template struct Timeout { typedef std::chrono::milliseconds DurationType; static bool is_timeout_enabled(UnderlyingType* timeout); static DurationType get_timeout_interval(UnderlyingType* timeout); static void invoke_timeout_handler(UnderlyingType* timeout); }; } } } #endif // CORE_DBUS_TRAITS_WATCH_H_ dbus-cpp-5.0.3/include/core/dbus/traits/watch.h000066400000000000000000000027411407013304700213340ustar00rootroot00000000000000/* * Copyright © 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Thomas Voß */ #ifndef CORE_DBUS_TRAITS_WATCH_H_ #define CORE_DBUS_TRAITS_WATCH_H_ #include namespace core { namespace dbus { namespace traits { template struct Watch { static inline int readable_event() { return -1; } static inline int writeable_event() { return -1; } static inline int error_event() { return -1; } static inline int hangup_event() { return -1; } static bool is_watch_enabled(UnderlyingType* watch); static int get_watch_unix_fd(UnderlyingType* watch); static bool is_watch_monitoring_fd_for_readable(UnderlyingType* watch); static bool is_watch_monitoring_fd_for_writable(UnderlyingType* watch); static bool invoke_watch_handler_for_event(UnderlyingType* watch, int event); }; } } } #endif // CORE_DBUS_TRAITS_WATCH_H_ dbus-cpp-5.0.3/include/core/dbus/types/000077500000000000000000000000001407013304700177075ustar00rootroot00000000000000dbus-cpp-5.0.3/include/core/dbus/types/any.h000066400000000000000000000032211407013304700206450ustar00rootroot00000000000000/* * Copyright © 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Thomas Voß */ #ifndef CORE_DBUS_TYPES_ANY_H_ #define CORE_DBUS_TYPES_ANY_H_ #include #include namespace core { namespace dbus { namespace types { /** * @brief Any describes types for which no codec specialization is known at compile time. */ class Any { public: /** * @brief Constructs an empty instance. */ Any(const Message::Reader& reader = Message::Reader()) : reader_(reader) { } /** * @brief Provides non-mutable access to the contained message. * * Users of the library can rely on Any and access to the contained and cloned * message to postpone serialization until runtime. Usually, compile-time static * typing is preferred via template-specializations of Codec to ensure maximum * stability. */ inline Message::Reader& reader() const { return reader_; } private: mutable Message::Reader reader_; }; } } } #endif // CORE_DBUS_TYPES_ANY_H_ dbus-cpp-5.0.3/include/core/dbus/types/object_path.h000066400000000000000000000105051407013304700223430ustar00rootroot00000000000000/* * Copyright © 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Thomas Voß */ #ifndef CORE_DBUS_TYPES_OBJECT_PATH_H_ #define CORE_DBUS_TYPES_OBJECT_PATH_H_ #include #include #include #include namespace core { namespace dbus { namespace types { /** * @brief The ObjectPath class encapsulates a DBus object path. */ class ORG_FREEDESKTOP_DBUS_DLL_PUBLIC ObjectPath { public: /** * @brief root() returns the default object path. * @return The string representation of the default object path. */ static const std::string& root(); /** * @brief The Errors struct summarizes all exceptions thrown by * methods of class ObjectPath. */ struct Errors { Errors() = delete; /** * @brief The InvalidObjectPath struct is thrown if a string representation of an object path is invalid. */ struct InvalidObjectPathStringRepresentation : public std::logic_error { inline InvalidObjectPathStringRepresentation(const std::string& s) : std::logic_error( "Could not construct valid object path from provided string: " + s) { } }; }; /** * @brief Constructs an object path from a string. * @throw Errors::InvalidObjectPathStringRepresentation if path is invalid. * @param [in] path The string to construct the object path from. * * Specifying a default argument here causes valgrind to report a "possible lost". * However, this is spurious and * http://stackoverflow.com/questions/10750299/if-i-specify-a-default-value-for-an-argument-of-type-stdstring-in-c-cou * gives some insight. */ ObjectPath(const std::string& path = ObjectPath::root()); /** * @brief Checks if an object path is empty. * @return true iff the object path is empty. */ bool empty() const; /** * @brief as_string provides a string representation of the object path. * @return A non-mutable reference to a string representation of the object path. */ const std::string& as_string() const; /** * @brief operator < compares two object path instances. * @param rhs The right-hand-side of the comparison. * @return true iff this instance is smaller than the right-hand-side. */ bool operator<(const ObjectPath& rhs) const; /** * @brief operator == compares two object path instances for equality. * @param rhs The right-hand-side of the comparison. * @return true iff this instance equals the right-hand-side. */ bool operator==(const ObjectPath& rhs) const; /** * @brief operator != compares two object path instances for inequality. * @param rhs The right-hand-side of the comparison. * @return true iff this instance does not equal the right-hand-side. */ bool operator!=(const ObjectPath& rhs) const; private: std::string path; }; /** * @brief operator << pretty prints an object path instance. * @param out The stream to pretty print to. * @param path The instance to be printed. * @return The stream that has been written to. */ ORG_FREEDESKTOP_DBUS_DLL_PUBLIC std::ostream& operator<<(std::ostream& out, const ObjectPath& path); } } } namespace std { /** * @brief Enables usage of ObjectPath instances in hashed containers. */ template<> struct ORG_FREEDESKTOP_DBUS_DLL_PUBLIC hash { /** * @brief operator () calculates the hash of an object path instance. * @param p The instance to calculate the hash value for. */ size_t operator()(const core::dbus::types::ObjectPath& p) const; }; } #endif // CORE_DBUS_TYPES_OBJECT_PATH_H_ dbus-cpp-5.0.3/include/core/dbus/types/signature.h000066400000000000000000000025421407013304700220640ustar00rootroot00000000000000/* * Copyright © 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Thomas Voß */ #ifndef CORE_DBUS_TYPES_SIGNATURE_H_ #define CORE_DBUS_TYPES_SIGNATURE_H_ #include #include namespace core { namespace dbus { namespace types { class Signature { public: explicit Signature(const std::string& signature = std::string()) : signature(signature) { } const std::string& as_string() const { return signature; } bool operator<(const Signature& rhs) const { return signature < rhs.signature; } bool operator==(const Signature& rhs) const { return signature == rhs.signature; } private: std::string signature; }; } } } #endif // CORE_DBUS_TYPES_OBJECT_PATH_H_ dbus-cpp-5.0.3/include/core/dbus/types/stl/000077500000000000000000000000001407013304700205115ustar00rootroot00000000000000dbus-cpp-5.0.3/include/core/dbus/types/stl/list.h000066400000000000000000000060751407013304700216450ustar00rootroot00000000000000/* * Copyright © 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Thomas Voß */ #ifndef CORE_DBUS_TYPES_STL_LIST_H_ #define CORE_DBUS_TYPES_STL_LIST_H_ #include #include #include namespace core { namespace dbus { namespace helper { template struct TypeMapper> { constexpr static ArgumentType type_value() { return ArgumentType::array; } constexpr static bool is_basic_type() { return false; } constexpr static bool requires_signature() { return true; } static std::string signature() { static const std::string s = DBUS_TYPE_ARRAY_AS_STRING + TypeMapper::type>::signature(); return s; } }; } template struct Codec> { static void encode_argument(DBusMessageIter* out, const std::list& arg) { DBusMessageIter sub; if (!dbus_message_iter_open_container( out, DBUS_TYPE_ARRAY, helper::TypeMapper::requires_signature() ? helper::signature(T()).c_str() : NULL, std::addressof(sub))) throw std::runtime_error("Problem opening container"); std::for_each( arg.begin(), arg.end(), std::bind(Codec::encode_argument, std::addressof(sub), std::placeholders::_1)); if (!dbus_message_iter_close_container(out, std::addressof(sub))) throw std::runtime_error("Problem closing container"); } static void decode_argument(DBusMessageIter* in, std::list& out) { if (dbus_message_iter_get_arg_type(in) != static_cast(ArgumentType::array)) throw std::runtime_error("Incompatible argument type: dbus_message_iter_get_arg_type(in) != ArgumentType::array"); if (dbus_message_iter_get_element_type(in) != static_cast(helper::TypeMapper::type_value())) throw std::runtime_error("Incompatible element type"); int current_type; DBusMessageIter sub; dbus_message_iter_recurse(in, std::addressof(sub)); while ((current_type = dbus_message_iter_get_arg_type (std::addressof(sub))) != DBUS_TYPE_INVALID) { out.emplace_back(); Codec::decode_argument(std::addressof(sub), out.back()); dbus_message_iter_next(std::addressof(sub)); } } }; } } #endif // CORE_DBUS_TYPES_STL_LIST_H_ dbus-cpp-5.0.3/include/core/dbus/types/stl/map.h000066400000000000000000000107321407013304700214420ustar00rootroot00000000000000/* * Copyright © 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Thomas Voß */ #ifndef CORE_DBUS_TYPES_STL_MAP_H_ #define CORE_DBUS_TYPES_STL_MAP_H_ #include #include #include namespace core { namespace dbus { namespace helper { template struct TypeMapper> { constexpr static ArgumentType type_value() { return ArgumentType::dictionary_entry; } constexpr static bool is_basic_type() { return false; } constexpr static bool requires_signature() { return false; } static std::string signature() { static const std::string s = DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING + TypeMapper::type>::signature() + TypeMapper::type>::signature() + DBUS_DICT_ENTRY_END_CHAR_AS_STRING; return s; } }; template struct TypeMapper> { constexpr static ArgumentType type_value() { return ArgumentType::array; } constexpr static bool is_basic_type() { return false; } constexpr static bool requires_signature() { return true; } static std::string signature() { static const std::string s = DBUS_TYPE_ARRAY_AS_STRING + TypeMapper>::signature(); return s; } }; } template struct Codec> { static void encode_argument(Message::Writer& out, const std::pair& arg) { Codec::type>::encode_argument(out, arg.first); Codec::type>::encode_argument(out, arg.second); } static void decode_argument(Message::Reader& in, std::pair& arg) { Codec::decode_argument(in, arg.first); Codec::decode_argument(in, arg.second); } }; template struct Codec> { static void encode_argument(Message::Writer& out, const std::pair& arg) { Codec::type>::encode_argument(out, arg.first); Codec::type>::encode_argument(out, arg.second); } static void decode_argument(Message::Reader& in, std::pair& arg) { Codec::decode_argument(in, arg.first); Codec::decode_argument(in, arg.second); } }; template struct Codec> { static void encode_argument(Message::Writer& out, const std::map& arg) { auto aw = out.open_array( types::Signature( helper::TypeMapper::value_type>::signature())); { for (const auto& element : arg) { auto de = aw.open_dict_entry(); { Codec>::encode_argument(de, element); } aw.close_dict_entry(std::move(de)); } } out.close_array(std::move(aw)); } static void decode_argument(Message::Reader& in, std::map& out) { out.clear(); auto array_reader = in.pop_array(); while (array_reader.type() != ArgumentType::invalid) { auto de = array_reader.pop_dict_entry(); std::pair v; Codec>::decode_argument(de, v); auto it = out.find(v.first); if (it == out.end()) { bool inserted = false; std::tie(std::ignore, inserted) = out.insert(std::move(v)); if (!inserted) throw std::runtime_error("Could not insert decoded element into map"); } else { it->second = std::move(v.second); } } } }; } } #endif // CORE_DBUS_TYPES_STL_MAP_H_ dbus-cpp-5.0.3/include/core/dbus/types/stl/string.h000066400000000000000000000032771407013304700222010ustar00rootroot00000000000000/* * Copyright © 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Thomas Voß */ #ifndef CORE_DBUS_TYPES_STL_STRING_H_ #define CORE_DBUS_TYPES_STL_STRING_H_ #include #include #include namespace core { namespace dbus { namespace helper { template<> struct TypeMapper { constexpr static inline ArgumentType type_value() { return ArgumentType::string; } constexpr static bool is_basic_type() { return false; } constexpr static bool requires_signature() { return true; } static std::string signature() { return DBUS_TYPE_STRING_AS_STRING; } }; } template<> struct Codec { static void encode_argument(Message::Writer& out, const std::string& arg) { out.push_stringn(arg.c_str(), arg.size()); } static void decode_argument(Message::Reader& in, std::string& arg) { const char* s = in.pop_string(); if (s != nullptr) arg = s; } }; } } #endif // CORE_DBUS_TYPES_STL_STRING_H_ dbus-cpp-5.0.3/include/core/dbus/types/stl/tuple.h000066400000000000000000000076231407013304700220230ustar00rootroot00000000000000/* * Copyright © 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Thomas Voß */ #ifndef CORE_DBUS_TYPES_STL_TUPLE_H_ #define CORE_DBUS_TYPES_STL_TUPLE_H_ #include #include #include namespace core { namespace dbus { namespace helper { namespace detail { template struct StaticRecursiveSignature { static std::string signature() { Tuple t; typedef decltype(std::get(t)) ElementType; static const std::string s = TypeMapper::type>::signature() + StaticRecursiveSignature::signature(); return s; } }; template struct StaticRecursiveSignature { static std::string signature() { Tuple t; typedef decltype(std::get(t)) ElementType; static const std::string s = TypeMapper::type>::signature(); return s; } }; } template struct TypeMapper> { constexpr static ArgumentType type_value() { return ArgumentType::structure; } constexpr static bool is_basic_type() { return false; } constexpr static bool requires_signature() { return false; } static std::string signature() { static const std::string s = detail::StaticRecursiveSignature, sizeof...(Args)-1, sizeof...(Args)>::signature(); return s; } }; } namespace detail { template struct CodecApply { static void decode_argument(Message::Reader& in, Tuple& t) { typedef decltype(std::get(t)) ElementType; Codec::type>::decode_argument(in, std::get(t)); CodecApply::decode_argument(in, t); } static void encode_argument(Message::Writer& out, const Tuple& t) { typedef decltype(std::get(t)) ElementType; Codec::type>::encode_argument(out, std::get(t)); CodecApply::encode_argument(out, t); } }; template struct CodecApply { static void decode_argument(Message::Reader& in, Tuple& t) { typedef decltype(std::get(t)) ElementType; Codec::type>::decode_argument(in, std::get(t)); } static void encode_argument(Message::Writer& out, const Tuple& t) { typedef decltype(std::get(t)) ElementType; Codec::type>::encode_argument(out, std::get(t)); } }; } template struct Codec> { static void encode_argument(Message::Writer& out, const std::tuple& arg) { detail::CodecApply, sizeof...(Args)-1, sizeof...(Args)>::encode_argument(out, arg); } static void decode_argument(Message::Reader& in, std::tuple& out) { detail::CodecApply, sizeof...(Args)-1, sizeof...(Args)>::decode_argument(in, out); } }; } } #endif // CORE_DBUS_TYPES_STL_TUPLE_H_ dbus-cpp-5.0.3/include/core/dbus/types/stl/vector.h000066400000000000000000000042761407013304700221750ustar00rootroot00000000000000/* * Copyright © 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Thomas Voß */ #ifndef CORE_DBUS_TYPES_STL_VECTOR_H_ #define CORE_DBUS_TYPES_STL_VECTOR_H_ #include #include #include #include namespace core { namespace dbus { namespace helper { template struct TypeMapper> { constexpr static ArgumentType type_value() { return ArgumentType::array; } constexpr static bool is_basic_type() { return false; } constexpr static bool requires_signature() { return true; } static std::string signature() { static const std::string s = DBUS_TYPE_ARRAY_AS_STRING + TypeMapper::type>::signature(); return s; } }; } template struct Codec> { static void encode_argument(Message::Writer& out, const std::vector& arg) { auto aw = out.open_array( types::Signature( helper::TypeMapper::signature())); { for(auto element : arg) core::dbus::encode_argument(aw, element); } out.close_array(std::move(aw)); } static void decode_argument(Message::Reader& in, std::vector& out) { Message::Reader ar = in.pop_array(); while (ar.type() != ArgumentType::invalid) { T value; Codec::decode_argument(ar, value); out.push_back(value); } } }; } } #endif // CORE_DBUS_TYPES_STL_VECTOR_H_ dbus-cpp-5.0.3/include/core/dbus/types/struct.h000066400000000000000000000042161407013304700214070ustar00rootroot00000000000000/* * Copyright © 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Thomas Voß */ #ifndef CORE_DBUS_TYPES_STRUCT_H_ #define CORE_DBUS_TYPES_STRUCT_H_ #include namespace core { namespace dbus { namespace types { template struct Struct { bool operator==(const Struct& rhs) const { return value == rhs.value; } T value; }; } namespace helper { template struct TypeMapper> { constexpr inline static ArgumentType type_value() { return ArgumentType::structure; } constexpr inline static bool is_basic_type() { return false; } constexpr inline static bool requires_signature() { return false; } inline static std::string signature() { static const std::string s = DBUS_STRUCT_BEGIN_CHAR_AS_STRING + TypeMapper::signature() + DBUS_STRUCT_END_CHAR_AS_STRING; return s; } }; } template struct Codec> { inline static void encode_argument(Message::Writer& out, const types::Struct& arg) { auto sw = out.open_structure(); { Codec::encode_argument(sw, arg.value); } out.close_structure(std::move(sw)); } inline static void decode_argument(Message::Reader& in, types::Struct& out) { auto struct_reader = in.pop_structure(); Codec::decode_argument(struct_reader, out.value); } }; } } #endif // CORE_DBUS_TYPES_STRUCT_H_ dbus-cpp-5.0.3/include/core/dbus/types/unix_fd.h000066400000000000000000000023201407013304700215110ustar00rootroot00000000000000/* * Copyright © 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Thomas Voß */ #ifndef CORE_DBUS_TYPES_UNIX_FD_H_ #define CORE_DBUS_TYPES_UNIX_FD_H_ #include #include namespace core { namespace dbus { namespace types { class UnixFd { public: explicit UnixFd(int fd = -1) : fd(fd) { } const int& to_int() const { return fd; } void from_int(int fd) { this->fd = fd; } bool operator==(const UnixFd& rhs) const { return fd == rhs.fd; } private: int fd; }; } } } #endif // CORE_DBUS_TYPES_OBJECT_PATH_H_ dbus-cpp-5.0.3/include/core/dbus/types/variant.h000066400000000000000000000132551407013304700215320ustar00rootroot00000000000000/* * Copyright © 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Thomas Voß */ #ifndef CORE_DBUS_TYPES_VARIANT_H_ #define CORE_DBUS_TYPES_VARIANT_H_ #include #include #include #include #include #include #include #include #include namespace core { namespace dbus { namespace types { class Variant { protected: typedef std::function Encoder; typedef std::function Decoder; inline Variant(const Encoder& encoder, const types::Signature& signature) : encoder(encoder), decoder(), signature_(signature) { } inline Variant(const Decoder& decoder, const types::Signature& signature) : encoder(), decoder(decoder), signature_(signature) { } public: template static inline Variant encode(T t) { Encoder encoder = [t](dbus::Message::Writer& writer) { Codec::encode_argument(writer, t); }; return Variant( encoder, types::Signature( core::dbus::helper::TypeMapper::signature())); } template static inline Variant decode(T& t) { Decoder decoder = [&t](dbus::Message::Reader& reader) { Codec::decode_argument(reader, t); }; return Variant( decoder, types::Signature( core::dbus::helper::TypeMapper::signature())); } inline Variant() { decoder = [this](dbus::Message::Reader& reader) { core::dbus::Codec::decode_argument(reader, any); }; } inline Variant(const Variant&) = default; inline Variant(Variant&& rhs) : encoder(std::move(rhs.encoder)), decoder(std::move(rhs.decoder)), any(std::move(rhs.any)), signature_(std::move(rhs.signature_)) { } virtual ~Variant() = default; inline Variant& operator=(Variant&& rhs) { encoder = std::move(rhs.encoder); decoder = std::move(rhs.decoder); signature_ = std::move(rhs.signature_); any = std::move(rhs.any); return *this; } virtual void decode(Message::Reader& reader) { if (!decoder) throw std::runtime_error("Variant::decode: Missing a decoder specification."); decoder(reader); } virtual void encode(Message::Writer& writer) const { if (!encoder) throw std::runtime_error("Variant::encode: Missing an encoder specification."); encoder(writer); } virtual const types::Signature& signature() const { return signature_; } template T as() const { T result; any.reader() >> result; return result; } protected: inline void set_encoder(const Encoder& encoder) { this->encoder = encoder; } inline void set_decoder(const Decoder& decoder) { this->decoder = decoder; } inline void set_signature(const types::Signature& signature) { this->signature_ = signature; } private: Encoder encoder; Decoder decoder; types::Any any; types::Signature signature_; }; template class TypedVariant : public Variant { public: explicit TypedVariant(const T& t = T()) : value(t) { auto decoder = [this](dbus::Message::Reader& reader) { Codec::decode_argument(reader, value); }; auto encoder = [this](dbus::Message::Writer& writer) { Codec::encode_argument(writer, value); }; set_decoder(decoder); set_encoder(encoder); set_signature(types::Signature{helper::TypeMapper::signature()}); } inline const T& get() const { return value; } inline void set(const T& t) { value = t; } private: T value; }; } /** * @brief Template specialization for variant argument types. */ template<> struct Codec { inline static void encode_argument(Message::Writer& out, const types::Variant& variant) { auto vw = out.open_variant(variant.signature()); { variant.encode(vw); } out.close_variant(std::move(vw)); } inline static void decode_argument(Message::Reader& in, types::Variant& variant) { auto vr = in.pop_variant(); variant.decode(vr); } }; template struct Codec> { inline static void encode_argument(Message::Writer& out, const types::TypedVariant& variant) { Codec::encode_argument(out, variant); } inline static void decode_argument(Message::Reader& in, types::TypedVariant& variant) { Codec::decode_argument(in, variant); } }; } } #endif // CORE_DBUS_TYPES_VARIANT_H_ dbus-cpp-5.0.3/include/core/dbus/visibility.h000066400000000000000000000020711407013304700211030ustar00rootroot00000000000000/* * Copyright © 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Thomas Voß */ #ifndef CORE_DBUS_VISIBILITY_H_ #define CORE_DBUS_VISIBILITY_H_ #if __GNUC__ >= 4 #define ORG_FREEDESKTOP_DBUS_DLL_PUBLIC __attribute__ ((visibility ("default"))) #define ORG_FREEDESKTOP_DBUS_DLL_LOCAL __attribute__ ((visibility ("hidden"))) #else #define ORG_FREEDESKTOP_DBUS_DLL_PUBLIC #define ORG_FREEDESKTOP_DBUS_DLL_LOCAL #endif #endif // CORE_DBUS_VISIBILITY_H_ dbus-cpp-5.0.3/include/core/dbus/well_known_bus.h000066400000000000000000000022041407013304700217420ustar00rootroot00000000000000/* * Copyright © 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Thomas Voß */ #ifndef CORE_ORG_DBUS_H_ #define CORE_ORG_DBUS_H_ #include namespace core { namespace dbus { /** * @brief The WellKnownBus enum lists all the buses known to the underlying dbus reference implementation. */ enum class WellKnownBus { session = DBUS_BUS_SESSION, ///< The session bus system = DBUS_BUS_SYSTEM, ///< The system bus starter = DBUS_BUS_STARTER ///< The bus that started us }; } } #endif // CORE_ORG_DBUS_H_ dbus-cpp-5.0.3/src/000077500000000000000000000000001407013304700140225ustar00rootroot00000000000000dbus-cpp-5.0.3/src/CMakeLists.txt000066400000000000000000000012601407013304700165610ustar00rootroot00000000000000# Copyright © 2013 Canonical Ltd. # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License version 3 as # published by the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # # Authored by: Thomas Voss add_subdirectory(core) dbus-cpp-5.0.3/src/core/000077500000000000000000000000001407013304700147525ustar00rootroot00000000000000dbus-cpp-5.0.3/src/core/CMakeLists.txt000066400000000000000000000012601407013304700175110ustar00rootroot00000000000000# Copyright © 2013 Canonical Ltd. # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License version 3 as # published by the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # # Authored by: Thomas Voss add_subdirectory(dbus) dbus-cpp-5.0.3/src/core/dbus/000077500000000000000000000000001407013304700157075ustar00rootroot00000000000000dbus-cpp-5.0.3/src/core/dbus/CMakeLists.txt000066400000000000000000000047271407013304700204610ustar00rootroot00000000000000# Copyright © 2013 Canonical Ltd. # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License version 3 as # published by the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # # Authored by: Thomas Voss find_package(PkgConfig) find_package(Threads) pkg_check_modules(DBUS dbus-1) include_directories( ${CMAKE_SOURCE_DIR}/include ${DBUS_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS} ${PROCESS_CPP_INCLUDE_DIR} ) configure_file( fixture.cpp.in ${CMAKE_CURRENT_BINARY_DIR}/fixture.cpp @ONLY ) add_library( dbus-cpp SHARED ${CMAKE_CURRENT_BINARY_DIR}/fixture.cpp bus.cpp dbus.cpp error.cpp match_rule.cpp message.cpp service.cpp service_watcher.cpp asio/executor.cpp types/object_path.cpp ) # We compile with all symbols visible by default. For the shipping library, we strip # out all symbols that are not in core::dbus::* set(symbol_map "${CMAKE_SOURCE_DIR}/symbols.map") set_target_properties(dbus-cpp PROPERTIES LINK_FLAGS "${ldflags} -Wl,--version-script,${symbol_map}") set_target_properties(dbus-cpp PROPERTIES LINK_DEPENDS ${symbol_map}) target_link_libraries( dbus-cpp ${Boost_LIBRARIES} ${DBUS_LIBRARIES} ${LIBXML2_LIBRARIES} ${PROCESS_CPP_LIBRARIES} ) set_target_properties( dbus-cpp PROPERTIES VERSION ${DBUS_CPP_VERSION_MAJOR}.${DBUS_CPP_VERSION_MINOR}.${DBUS_CPP_VERSION_PATCH} SOVERSION ${DBUS_CPP_VERSION_MAJOR} ) install( TARGETS dbus-cpp LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ) # We want to test compiler functionality in our testing framework and # thus collect symbols in this temporary helper library that is not # installed but just linked to the actual compiler executable. add_library( dbus-cppc-helper STATIC compiler.cpp generator.cpp introspection_parser.cpp ) target_link_libraries( dbus-cppc-helper ${Boost_LIBRARIES} ${LIBXML2_LIBRARIES} ) add_executable( dbus-cppc compiler_main.cpp ) target_link_libraries( dbus-cppc dbus-cppc-helper ) install( TARGETS dbus-cppc RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} ) dbus-cpp-5.0.3/src/core/dbus/asio/000077500000000000000000000000001407013304700166425ustar00rootroot00000000000000dbus-cpp-5.0.3/src/core/dbus/asio/executor.cpp000066400000000000000000000277561407013304700212250ustar00rootroot00000000000000/* * Copyright © 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Thomas Voß */ #include #include #include #include #include #include #include #include #include #include #include #include namespace core { namespace dbus { namespace traits { template<> struct Timeout { typedef int DurationType; static inline bool is_timeout_enabled(DBusTimeout* timeout) { return TRUE == dbus_timeout_get_enabled(timeout); } static inline int get_timeout_interval(DBusTimeout* timeout) { return DurationType(dbus_timeout_get_interval(timeout)); } static inline void invoke_timeout_handler(DBusTimeout* timeout) { dbus_timeout_handle(timeout); } }; template<> struct Watch { inline static int readable_event() { return DBUS_WATCH_READABLE; } inline static int writeable_event() { return DBUS_WATCH_WRITABLE; } inline static int error_event() { return DBUS_WATCH_ERROR; } inline static int hangup_event() { return DBUS_WATCH_HANGUP; } static inline bool is_watch_enabled(DBusWatch* watch) { return TRUE == dbus_watch_get_enabled(watch); } static inline int get_watch_unix_fd(DBusWatch* watch) { return dbus_watch_get_unix_fd(watch); } static inline bool is_watch_monitoring_fd_for_readable(DBusWatch* watch) { return dbus_watch_get_flags(watch) & DBUS_WATCH_READABLE; } static bool is_watch_monitoring_fd_for_writable(DBusWatch* watch) { return dbus_watch_get_flags(watch) & DBUS_WATCH_WRITABLE; } static bool invoke_watch_handler_for_event(DBusWatch* watch, int event) { return dbus_watch_handle(watch, event); } }; } namespace asio { class Executor : public core::dbus::Executor { public: template struct Timeout : std::enable_shared_from_this> { Timeout(boost::asio::io_service& io_service, UnderlyingTimeoutType* timeout) : io_service(io_service), timer(io_service), timeout(timeout) { if (!timeout) throw std::runtime_error("Precondition violated: timeout has to be non-null"); } ~Timeout() { // cancel(); } void start() { if (!traits::Timeout::is_timeout_enabled(timeout)) { return; } // We do not keep ourselves alive to prevent from races during destruction. std::weak_ptr> wp{this->shared_from_this()}; timer.expires_from_now( boost::posix_time::milliseconds( traits::Timeout::get_timeout_interval( timeout))); timer.async_wait([wp](const boost::system::error_code& ec) { auto sp = wp.lock(); if (sp) sp->on_timeout(ec); }); } void cancel() { try { timer.cancel(); } catch(...) { // Really not sure what we should do about exceptions here. } } void on_timeout(const boost::system::error_code& ec) { if (ec == boost::asio::error::operation_aborted) return; if (ec) return; traits::Timeout::invoke_timeout_handler(timeout); } boost::asio::io_service& io_service; boost::asio::deadline_timer timer; UnderlyingTimeoutType* timeout; }; template struct Watch : std::enable_shared_from_this> { Watch(boost::asio::io_service& io_service, UnderlyingWatchType* watch) : io_service(io_service), stream_descriptor(io_service), watch(watch) { if (!watch) throw std::runtime_error("Precondition violated: watch has to be non-null"); } ~Watch() noexcept { stream_descriptor.cancel(); stream_descriptor.release(); } void start() { stream_descriptor.assign(traits::Watch::get_watch_unix_fd(watch)); restart(); } void restart() { // We do not keep ourselves alive to prevent from races during destruction. std::weak_ptr> wp{this->shared_from_this()}; if (traits::Watch::is_watch_monitoring_fd_for_readable(watch)) { stream_descriptor.async_read_some(boost::asio::null_buffers(), [wp](boost::system::error_code ec, std::size_t bytes_transferred) { auto sp = wp.lock(); if (sp) sp->on_stream_descriptor_event( traits::Watch::readable_event(), ec, bytes_transferred); }); } if (traits::Watch::is_watch_monitoring_fd_for_writable(watch)) { stream_descriptor.async_write_some(boost::asio::null_buffers(), [wp](boost::system::error_code ec, std::size_t bytes_transferred) { auto sp = wp.lock(); if (sp) sp->on_stream_descriptor_event( traits::Watch::writeable_event(), ec, bytes_transferred); }); } } void cancel() { try { stream_descriptor.cancel(); } catch (...) { } } void on_stream_descriptor_event(int event, const boost::system::error_code& error, std::size_t) { if (error == boost::asio::error::operation_aborted) { return; } if (error) { traits::Watch::invoke_watch_handler_for_event( watch, traits::Watch::error_event()); } else { if (!traits::Watch::invoke_watch_handler_for_event(watch, event)) throw std::runtime_error("Insufficient memory while handling watch event"); restart(); } } boost::asio::io_service& io_service; boost::asio::posix::stream_descriptor stream_descriptor; UnderlyingWatchType* watch; }; template struct Holder { static void ptr_delete(void* p) { delete static_cast*>(p); } Holder(const T& t) : value(t) { } T value; }; static dbus_bool_t on_dbus_add_watch(DBusWatch* watch, void* data) { if (dbus_watch_get_enabled(watch) == FALSE) return TRUE; auto thiz = static_cast(data); auto w = std::shared_ptr>(new Watch<>(thiz->io_service, watch)); auto holder = new Holder>>(w); dbus_watch_set_data(watch, holder, Holder>>::ptr_delete); w->start(); return TRUE; } static void on_dbus_remove_watch(DBusWatch* watch, void*) { auto w = static_cast>>*>(dbus_watch_get_data(watch)); if (!w) return; w->value->cancel(); } static void on_dbus_watch_toggled(DBusWatch* watch, void*) { auto holder = static_cast>>*>(dbus_watch_get_data(watch)); if (!holder) return; dbus_watch_get_enabled(watch) == TRUE ? holder->value->restart() : holder->value->cancel(); } static dbus_bool_t on_dbus_add_timeout(DBusTimeout* timeout, void* data) { auto thiz = static_cast(data); auto t = std::shared_ptr>(new Timeout<>(thiz->io_service, timeout)); auto holder = new Holder>>(t); dbus_timeout_set_data( timeout, holder, Holder>>::ptr_delete); t->start(); return TRUE; } static void on_dbus_remove_timeout(DBusTimeout* timeout, void*) { static_cast>>*>(dbus_timeout_get_data(timeout))->value->cancel(); } static void on_dbus_timeout_toggled(DBusTimeout* timeout, void*) { auto holder = static_cast>>*>(dbus_timeout_get_data(timeout)); holder->value->start(); } static void on_dbus_wakeup_event_loop(void* data) { auto thiz = static_cast(data); auto bus = thiz->bus; thiz->io_service.post([bus]() { while (dbus_connection_get_dispatch_status(bus->raw()) == DBUS_DISPATCH_DATA_REMAINS) { dbus_connection_dispatch(bus->raw()); } }); } public: Executor(const Bus::Ptr& bus, boost::asio::io_service& io) : bus(bus), io_service(io), work(io_service) { if (!bus) throw std::runtime_error("Precondition violated, cannot construct executor for null bus."); if (!dbus_connection_set_watch_functions( bus->raw(), on_dbus_add_watch, on_dbus_remove_watch, on_dbus_watch_toggled, this, nullptr)) throw std::runtime_error("Problem installing watch functions."); if (!dbus_connection_set_timeout_functions( bus->raw(), on_dbus_add_timeout, on_dbus_remove_timeout, on_dbus_timeout_toggled, this, nullptr)) throw std::runtime_error("Problem installing timeout functions."); dbus_connection_set_wakeup_main_function( bus->raw(), on_dbus_wakeup_event_loop, this, nullptr); } ~Executor() noexcept { stop(); } void run() { io_service.run(); } void stop() { io_service.stop(); } private: Bus::Ptr bus; boost::asio::io_service& io_service; boost::asio::io_service::work work; }; ORG_FREEDESKTOP_DBUS_DLL_PUBLIC Executor::Ptr make_executor(const Bus::Ptr& bus) { static boost::asio::io_service io; return std::make_shared(bus, io); } ORG_FREEDESKTOP_DBUS_DLL_PUBLIC Executor::Ptr make_executor(const Bus::Ptr& bus, boost::asio::io_service& io) { return std::make_shared(bus, io); } } } } dbus-cpp-5.0.3/src/core/dbus/bus.cpp000066400000000000000000000254041407013304700172110ustar00rootroot00000000000000/* * Copyright © 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Thomas Voß */ #include #include #include #include #include #include #include #include "message_p.h" #include "message_factory_impl.h" #include "pending_call_impl.h" namespace { struct VTable { static void unregister_object_path(DBusConnection*, void* data) { delete static_cast(data); } static DBusHandlerResult on_new_message( DBusConnection*, DBusMessage* message, void* data) { auto thiz = static_cast(data); auto sp = thiz->object.lock(); // We return early if the underlying object is dead. if (not sp) return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; if (sp->on_new_message( core::dbus::Message::from_raw_message( message))) return DBUS_HANDLER_RESULT_HANDLED; return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; } std::weak_ptr object; }; DBusHandlerResult static_handle_message( DBusConnection* connection, DBusMessage* message, void* user_data) { (void) connection; auto thiz = static_cast(user_data); return static_cast( thiz->handle_message( core::dbus::Message::from_raw_message( message))); } void init_libdbus_thread_support_and_install_shutdown_handler() { static const bool install_dbus_shutdown_handler { not core::posix::this_process::env::get("DBUS_CPP_INSTALL_DBUS_SHUTDOWN_HANDLER").empty() }; static std::once_flag once; std::call_once(once, []() { dbus_threads_init_default(); if (install_dbus_shutdown_handler) std::atexit(dbus_shutdown); }); } } namespace core { namespace dbus { Bus::Name::Name(Bus::Name&& rhs) : name(std::move(rhs.name)) { } Bus::Name& Bus::Name::operator=(Bus::Name&& rhs) { name = std::move(rhs.name); return *this; } Bus::Name::Name(const std::string &name) : name(name) { } const std::string& Bus::Name::as_string() const { return name; } struct Bus::Private { Private() : connection(nullptr), message_factory_impl(new impl::MessageFactory()), message_type_router([](const Message::Ptr& msg) { return msg->type(); }), signal_router([](const Message::Ptr& msg){ return msg->path(); }) { init_libdbus_thread_support_and_install_shutdown_handler(); } std::shared_ptr connection; std::shared_ptr message_factory_impl; Executor::Ptr executor; MessageTypeRouter message_type_router; SignalRouter signal_router; }; Bus::MessageHandlerResult Bus::handle_message(const Message::Ptr& message) { d->message_type_router(message); return Bus::MessageHandlerResult::not_yet_handled; } Bus::Bus(const std::string& address) : d(new Private()) { Error se; d->connection.reset( dbus_connection_open_private(address.c_str(), std::addressof(se.raw())), [](DBusConnection*){} ); if (!d->connection) throw std::runtime_error(se.print()); d->message_type_router.install_route( Message::Type::signal, std::bind( &Bus::SignalRouter::operator(), std::ref(d->signal_router), std::placeholders::_1)); dbus_connection_add_filter( d->connection.get(), static_handle_message, this, nullptr); auto message = dbus::Message::make_method_call( DBus::name(), DBus::path(), DBus::interface(), "Hello"); auto reply = send_with_reply_and_block_for_at_most(message, std::chrono::seconds(1)); if (reply->type() == Message::Type::error) throw std::runtime_error(reply->error().print()); dbus_connection_set_exit_on_disconnect(d->connection.get(), FALSE); } Bus::Bus(WellKnownBus bus) : d(new Private()) { Error se; d->connection.reset( dbus_bus_get_private(static_cast(bus), std::addressof(se.raw())), [](DBusConnection*){} ); if (!d->connection) throw std::runtime_error(se.print()); d->message_type_router.install_route( Message::Type::signal, std::bind( &Bus::SignalRouter::operator(), std::ref(d->signal_router), std::placeholders::_1)); dbus_connection_add_filter( d->connection.get(), static_handle_message, this, nullptr); dbus_connection_set_exit_on_disconnect(d->connection.get(), FALSE); } Bus::~Bus() noexcept { dbus_connection_remove_filter(d->connection.get(), static_handle_message, this); dbus_connection_close(d->connection.get()); dbus_connection_unref(d->connection.get()); } const std::shared_ptr Bus::message_factory() { return d->message_factory_impl; } Bus::Name Bus::request_name_on_bus( const std::string& name, Bus::RequestNameFlag flags) { Error error; auto rc = dbus_bus_request_name( d->connection.get(), name.c_str(), static_cast(flags), std::addressof(error.raw())); Bus::Name result{name}; switch (rc) { case DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER: return result; case DBUS_REQUEST_NAME_REPLY_IN_QUEUE: return result; case DBUS_REQUEST_NAME_REPLY_EXISTS: throw Bus::Errors::AlreadyOwned{}; break; case DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER: throw Bus::Errors::AlreadyOwner{}; break; case -1: throw std::runtime_error(error.print()); } return result; } void Bus::release_name_on_bus(Bus::Name&& name) { Error error; dbus_bus_release_name( d->connection.get(), name.as_string().c_str(), std::addressof(error.raw())); } uint32_t Bus::send(const std::shared_ptr& msg) { dbus_uint32_t serial; if (!dbus_connection_send( d->connection.get(), msg->d->dbus_message.get(), std::addressof(serial))) throw std::runtime_error("Problem sending message"); return serial; } std::shared_ptr Bus::send_with_reply_and_block_for_at_most( const std::shared_ptr& msg, const std::chrono::milliseconds& milliseconds) { // TODO(tvoss): Enable this once method handlers have been adjusted to // operate on contexts. // if (d->executor) // { // throw std::logic_error("Calling Bus::send_with_reply_and_block_for_at_most on a " // "connection that is run by an executor, i.e., an event loop " // "is not supported as the underlying implementation in libdbus " // "is racy"); //} Error se; auto result = dbus_connection_send_with_reply_and_block( d->connection.get(), msg->d->dbus_message.get(), milliseconds.count(), std::addressof(se.raw())); if (!result) throw std::runtime_error(se.print()); auto reply = Message::from_raw_message(result); dbus_message_unref(result); return reply; } PendingCall::Ptr Bus::send_with_reply_and_timeout( const std::shared_ptr& msg, const std::chrono::milliseconds& timeout) { DBusPendingCall* pending_call; auto result = dbus_connection_send_with_reply( d->connection.get(), msg->d->dbus_message.get(), std::addressof(pending_call), timeout.count()); if (result == FALSE) throw Errors::NoMemory{}; if (!pending_call) throw std::runtime_error("Connection disconnected or tried to send fd's over a transport that does not support it"); return impl::PendingCall::create(pending_call); } void Bus::add_match(const MatchRule& rule) { Error se; dbus_bus_add_match(d->connection.get(), rule.as_string().c_str(), std::addressof(se.raw())); if (se) throw std::runtime_error(se.print()); } void Bus::remove_match(const MatchRule& rule) { Error se; dbus_bus_remove_match(d->connection.get(), rule.as_string().c_str(), std::addressof(se.raw())); if (se) throw std::runtime_error(se.print()); } bool Bus::has_owner_for_name(const std::string& name) { return dbus_bus_name_has_owner(d->connection.get(), name.c_str(), nullptr); } void Bus::install_executor(const Executor::Ptr& e) { d->executor = e; } void Bus::stop() { if (!d->executor) throw std::runtime_error("Missing executor, cannot stop."); d->executor->stop(); } void Bus::run() { if (!d->executor) throw std::runtime_error("Missing executor, cannot run."); d->executor->run(); } void Bus::register_object_for_path( const types::ObjectPath& path, const std::shared_ptr& object) { auto vtable = new DBusObjectPathVTable { VTable::unregister_object_path, VTable::on_new_message, nullptr, nullptr, nullptr, nullptr }; Error e; auto result = dbus_connection_try_register_object_path( d->connection.get(), path.as_string().c_str(), vtable, new VTable{object}, std::addressof(e.raw())); if (!result || e) { delete vtable; throw std::runtime_error(e.print()); } } void Bus::unregister_object_path( const types::ObjectPath& path) { dbus_connection_unregister_object_path( d->connection.get(), path.as_string().c_str()); } Bus::SignalRouter& Bus::access_signal_router() { return d->signal_router; } DBusConnection* Bus::raw() const { return d->connection.get(); } } } dbus-cpp-5.0.3/src/core/dbus/compiler.cpp000066400000000000000000000206521407013304700202320ustar00rootroot00000000000000/* * Copyright © 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Thomas Voß */ #include #include #include #include namespace core { namespace dbus { struct Compiler::Private { std::shared_ptr parser; std::shared_ptr generator; struct Context { Context() { } void reset() { root = current = std::shared_ptr(); } void adjust_up() { current = current->parent(); } template void adjust_down(const T& t) { if (!root) { root = std::make_shared(std::shared_ptr(), t); current = root; } else { auto element = std::make_shared(current, t); current->add_child(element); current = element; } } std::shared_ptr root; std::shared_ptr current; } context; void on_node(const IntrospectionParser::Node& node) { context.adjust_down(node); } void on_node_done() { context.adjust_up(); } void on_interface(const IntrospectionParser::Interface& interface) { context.adjust_down(interface); } void on_interface_done() { context.adjust_up(); } void on_method(const IntrospectionParser::Method& method) { context.adjust_down(method); } void on_method_done() { context.adjust_up(); } void on_signal(const IntrospectionParser::Signal& signal) { context.adjust_down(signal); } void on_signal_done() { context.adjust_up(); } void on_property(const IntrospectionParser::Property& property) { context.adjust_down(property); } void on_argument(const IntrospectionParser::Argument& argument) { context.adjust_down(argument); } void on_argument_done() { context.adjust_up(); } void on_annotation(const IntrospectionParser::Annotation& annotation) { context.adjust_down(annotation); } void on_annotation_done() { context.adjust_up(); } }; Compiler::Compiler( const std::shared_ptr& parser, const std::shared_ptr& generator) : d{new Private{parser, generator, Private::Context{}}} { // TODO: Assert on null deps here. d->parser->on_node(std::bind(&Private::on_node, d.get(), std::placeholders::_1)); d->parser->on_node_done(std::bind(&Private::on_node_done, d.get())); d->parser->on_interface(std::bind(&Private::on_interface, d.get(), std::placeholders::_1)); d->parser->on_interface_done(std::bind(&Private::on_interface_done, d.get())); d->parser->on_method(std::bind(&Private::on_method, d.get(), std::placeholders::_1)); d->parser->on_method_done(std::bind(&Private::on_method_done, d.get())); d->parser->on_property(std::bind(&Private::on_property, d.get(), std::placeholders::_1)); d->parser->on_signal(std::bind(&Private::on_signal, d.get(), std::placeholders::_1)); d->parser->on_signal_done(std::bind(&Private::on_signal_done, d.get())); d->parser->on_argument(std::bind(&Private::on_argument, d.get(), std::placeholders::_1)); d->parser->on_argument_done(std::bind(&Private::on_argument_done, d.get())); d->parser->on_annotation(std::bind(&Private::on_annotation, d.get(), std::placeholders::_1)); d->parser->on_annotation_done(std::bind(&Private::on_annotation_done, d.get())); } Compiler::~Compiler() { } bool Compiler::process_introspection_file_with_generator_config( const std::string& fn, const GeneratorConfiguration& config = Generator::default_configuration()) { d->context.reset(); if (!d->parser->invoke_for(fn)) return false; std::ifstream in_file(fn); if (!in_file) return false; if (!d->generator->invoke_for_model_with_configuration(d->context.root, in_file, config)) return false; return true; } namespace { struct CommandLineOptions { static const char* key_input_file() { return "input-file"; } CommandLineOptions() : allowed_options("Allowed options") { static const int unlimited = -1; allowed_options.add_options() (CommandLineOptions::key_input_file(), boost::program_options::value>(), "DBUS XML introspection input files to the compiler"); positional_options.add(CommandLineOptions::key_input_file(), unlimited); } bool parse(int argc, const char* argv[]) { try { boost::program_options::variables_map vm; boost::program_options::store( boost::program_options::command_line_parser( argc, argv).options(allowed_options).positional(positional_options).run(), vm); boost::program_options::notify(vm); files = vm[CommandLineOptions::key_input_file()].as>(); } catch(...) { return false; } return true; } std::string usage() const { std::stringstream ss; ss << allowed_options; return ss.str(); } boost::program_options::options_description allowed_options; boost::program_options::positional_options_description positional_options; std::vector files; }; struct AnsiiControlSequences { struct Style { static constexpr const char* Bold() { return "\033[1m"; } static constexpr const char* Normal() { return "\033[0m"; } }; struct Colors { static constexpr const char* DefaultForeground() { return "\033[39m"; } static constexpr const char* Green() { return "\033[32m"; } static constexpr const char* Red() { return "\033[91m"; } }; }; struct Ok { friend std::ostream& operator<<(std::ostream& out, const Ok&) { out << AnsiiControlSequences::Style::Bold() << AnsiiControlSequences::Colors::Green() << "[OK ]" << AnsiiControlSequences::Colors::DefaultForeground() << AnsiiControlSequences::Style::Normal(); return out; } }; struct Fail { friend std::ostream& operator<<(std::ostream& out, const Fail&) { out << AnsiiControlSequences::Style::Bold() << AnsiiControlSequences::Colors::Red() << "[FAIL]" << AnsiiControlSequences::Colors::DefaultForeground() << AnsiiControlSequences::Style::Normal(); return out; } }; } int Compiler::main(int argc, const char* argv[]) { CommandLineOptions cli_options; if (!cli_options.parse(argc, argv)) { std::cout << "Could not parse command line arguments, aborting now." << std::endl; std::cout << cli_options.usage() << std::endl; return EXIT_FAILURE; } auto parser = std::make_shared(); auto generator = std::make_shared(); dbus::Compiler compiler(parser, generator); for (auto file : cli_options.files) { auto result = compiler.process_introspection_file_with_generator_config( file, dbus::Generator::default_configuration()); if (result) std::cout << Ok() << " "; else std::cout << Fail() << " "; std::cout << file << std::endl; if (!result) exit(EXIT_FAILURE); } return EXIT_SUCCESS; } } } dbus-cpp-5.0.3/src/core/dbus/compiler_main.cpp000066400000000000000000000016511407013304700212340ustar00rootroot00000000000000/* * Copyright © 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Thomas Voß */ #include #include #include namespace dbus = core::dbus; int main(int argc, const char* argv[]) { return dbus::Compiler::main(argc, argv); } dbus-cpp-5.0.3/src/core/dbus/dbus.cpp000066400000000000000000000071721407013304700173570ustar00rootroot00000000000000/* * Copyright © 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Thomas Voß */ #include #include #include #include #include #include namespace core { namespace dbus { struct DBus::ListNames { typedef DBus Interface; inline static const std::string& name() { static const std::string s { "ListNames" }; return s; } inline static const std::chrono::milliseconds default_timeout() { return std::chrono::seconds{1}; } }; struct DBus::Hello { typedef DBus Interface; inline static const std::string& name() { static const std::string s { "Hello" }; return s; } inline static const std::chrono::milliseconds default_timeout() { return std::chrono::seconds{1}; } }; struct DBus::GetConnectionUnixProcessID { typedef DBus Interface; inline static const std::string& name() { static const std::string s { "GetConnectionUnixProcessID" }; return s; } inline static const std::chrono::milliseconds default_timeout() { return std::chrono::seconds{1}; } }; struct DBus::GetConnectionUnixUser { typedef DBus Interface; static const std::string& name() { static const std::string s { "GetConnectionUnixUser" }; return s; } inline static const std::chrono::milliseconds default_timeout() { return std::chrono::seconds{1}; } }; const std::string& DBus::name() { static const std::string s{DBUS_SERVICE_DBUS}; return s; } const types::ObjectPath& DBus::path() { static const types::ObjectPath path{DBUS_PATH_DBUS}; return path; } const std::string& DBus::interface() { static const std::string s{DBUS_INTERFACE_DBUS}; return s; } DBus::DBus(const Bus::Ptr& bus) : bus(bus), service(Service::use_service(bus)), object(service->object_for_path(DBus::path())) { } std::vector DBus::list_names() const { return object->invoke_method_synchronously>().value(); } uint32_t DBus::get_connection_unix_process_id(const std::string& name) const { return object->invoke_method_synchronously(name).value(); } uint32_t DBus::get_connection_unix_user(const std::string& name) const { return object->invoke_method_synchronously(name).value(); } std::string DBus::hello() const { // TODO: We really should switch to method transaction here. return object->invoke_method_synchronously().value(); } std::unique_ptr DBus::make_service_watcher(const std::string& name, WatchMode watch_mode) { return std::unique_ptr(new ServiceWatcher(object, name, watch_mode)); } } } dbus-cpp-5.0.3/src/core/dbus/error.cpp000066400000000000000000000030441407013304700175450ustar00rootroot00000000000000/* * Copyright © 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Thomas Voß */ #include #include #include namespace core { namespace dbus { struct Error::Private { Private() { dbus_error_init(std::addressof(error)); } ~Private() { dbus_error_free(std::addressof(error)); } DBusError error; }; Error::Error() : d(new Private()) { } Error::Error(Error&& that) : d(std::move(that.d)) { } Error::~Error() { } Error& Error::operator=(Error&& rhs) { d = std::move(rhs.d); return *this; } std::string Error::name() const { return d->error.name; } std::string Error::message() const { return d->error.message; } std::string Error::print() const { return name() + ": " + message(); } Error::operator bool() const { return dbus_error_is_set(std::addressof(d->error)); } DBusError& Error::raw() { return d->error; } } } dbus-cpp-5.0.3/src/core/dbus/fixture.cpp.in000066400000000000000000000166651407013304700205240ustar00rootroot00000000000000/* * Copyright © 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Thomas Voß */ #include #include #include #include #include #include namespace { static constexpr const char* dbus_session_bus_address { "DBUS_SESSION_BUS_ADDRESS" }; static constexpr const char* dbus_system_bus_address { "DBUS_SYSTEM_BUS_ADDRESS" }; static constexpr const char* dbus_starter_address { "DBUS_STARTER_ADDRESS" }; static constexpr const char* dbus_starter_bus_type { "DBUS_STARTER_BUS_TYPE" }; boost::optional find_executable(const boost::filesystem::path& name) { if (name.is_absolute()) return name; std::stringstream ss{core::posix::this_process::env::get("PATH")}; std::string token; while (std::getline(ss, token, ':')) { auto path = boost::filesystem::path{token} / name; if (boost::filesystem::exists(path)) return path; } return boost::optional(); } boost::filesystem::path dbus_daemon() { if (auto path = find_executable("dbus-daemon")) return *path; throw std::runtime_error("Could not locate the dbus-daemon executable, please check your installation."); } boost::filesystem::path timeout() { if (auto path = find_executable("timeout")) return *path; throw std::runtime_error("Could not locate the timeout executable, please check your installation."); } } struct core::dbus::Fixture::Private { struct Session { Session(const std::string& config_file) { std::vector argv { "--kill-after=5", std::to_string(core::dbus::Fixture::default_daemon_timeout().count()), dbus_daemon().native(), "--config-file", config_file, "--print-address" }; std::map env; core::posix::this_process::env::for_each([&env](const std::string& key, const std::string& value) { env.insert(std::make_pair(key, value)); }); daemon = core::posix::exec( timeout().native(), argv, env, core::posix::StandardStream::stdout); daemon.cout() >> address; if (address.empty()) throw std::runtime_error("Session: Could not read address of bus instance."); // We clean up the env prior to injecting the new addresses. std::error_code ec; // And just ignore all error codes. core::posix::this_process::env::unset(dbus_session_bus_address, ec); core::posix::this_process::env::unset(dbus_starter_address, ec); core::posix::this_process::env::unset(dbus_starter_bus_type, ec); core::posix::this_process::env::set_or_throw(dbus_session_bus_address, address); core::posix::this_process::env::set_or_throw(dbus_starter_address, address); core::posix::this_process::env::set_or_throw(dbus_starter_bus_type, "session"); } ~Session() { try { daemon.send_signal_or_throw(core::posix::Signal::sig_term); daemon.wait_for(core::posix::wait::Flags::untraced); } catch(...) { // We drop any exception to make the dtor exception safe. } } core::posix::ChildProcess daemon = core::posix::ChildProcess::invalid(); std::string address; } session; struct System { System(const std::string& config_file) { std::vector argv { "--kill-after=5", std::to_string(core::dbus::Fixture::default_daemon_timeout().count()), dbus_daemon().native(), "--config-file", config_file, "--print-address" }; std::map env; core::posix::this_process::env::for_each([&env](const std::string& key, const std::string& value) { env.insert(std::make_pair(key, value)); }); daemon = core::posix::exec( timeout().native(), argv, env, core::posix::StandardStream::stdout); daemon.cout() >> address; if (address.empty()) throw std::runtime_error("System: Could not read address of bus instance."); // We clean up the env prior to injecting the new addresses. std::error_code ec; // And just ignore all error codes. core::posix::this_process::env::unset(dbus_system_bus_address, ec); core::posix::this_process::env::set_or_throw(dbus_system_bus_address, address); } ~System() { try { daemon.send_signal_or_throw(core::posix::Signal::sig_term); daemon.wait_for(core::posix::wait::Flags::untraced); } catch(...) { // We drop any exception to make the dtor exception safe. } } core::posix::ChildProcess daemon = core::posix::ChildProcess::invalid(); std::string address; } system; }; core::dbus::Fixture::Seconds& core::dbus::Fixture::default_daemon_timeout() { static core::dbus::Fixture::Seconds instance{60}; return instance; } const std::string& core::dbus::Fixture::default_session_bus_config_file() { static const std::string s{"@CMAKE_INSTALL_PREFIX@/@CMAKE_INSTALL_DATAROOTDIR@/dbus-cpp/session.conf"}; return s; } const std::string& core::dbus::Fixture::default_system_bus_config_file() { static const std::string s{"@CMAKE_INSTALL_PREFIX@/@CMAKE_INSTALL_DATAROOTDIR@/dbus-cpp/system.conf"}; return s; } core::dbus::Fixture::Fixture(const std::string& session_bus_configuration_file, const std::string& system_bus_configuration_file) : d(new Private{Private::Session{session_bus_configuration_file}, Private::System{system_bus_configuration_file}}) { } core::dbus::Fixture::~Fixture() { } std::string core::dbus::Fixture::session_bus_address() { return d->session.address; } std::shared_ptr core::dbus::Fixture::create_connection_to_session_bus() { return std::shared_ptr(new core::dbus::Bus{d->session.address}); } std::string core::dbus::Fixture::system_bus_address() { return d->system.address; } std::shared_ptr core::dbus::Fixture::create_connection_to_system_bus() { return std::shared_ptr(new core::dbus::Bus{d->system.address}); } dbus-cpp-5.0.3/src/core/dbus/generator.cpp000066400000000000000000000673541407013304700204200ustar00rootroot00000000000000/* * Copyright © 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Thomas Voß */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include typedef boost::filesystem::path Path; typedef boost::filesystem::fstream File; namespace core { namespace dbus { namespace detail { struct TypeMangler { struct Comma { enum class State { not_required, not_armed, armed }; mutable State state = State::not_required; friend std::ostream& operator<<(std::ostream& out, const Comma& comma) { switch(comma.state) { case State::not_required: comma.state = State::not_armed; break; case State::not_armed: comma.state = State::armed; break; case State::armed: out << ","; comma.state = State::not_armed; break; } return out; } }; struct State { struct Element { core::dbus::ArgumentType argument; std::shared_ptr parent; std::vector> children; }; State() : root(new Element()), current(root) { } bool update_for_type(ArgumentType arg) { if (ArgumentType::invalid == arg) return false; is_void = false; static const std::vector> no_children; std::shared_ptr new_element(new Element{arg, current, no_children}); current->children.push_back(new_element); return true; } bool update_for_array_start() { current = current->children.back(); return true; } bool update_for_struct_start() { current = current->children.back(); return true; } bool update_for_struct_end() { current = current->parent; return true; } bool update_for_dict_entry_start() { current = current->children.back(); return true; } bool update_for_dict_entry_end() { current = current->parent; return true; } bool is_void = true; std::shared_ptr root; std::shared_ptr current; }; bool update_from_signature(const std::string& s) { return update_from_signature(s.begin(), s.end()); } bool update_from_signature(std::string::const_iterator it, std::string::const_iterator itE) { while (it != itE) { if (!update(*it)) return false; ++it; } return true; } bool update(char c) { bool result = false; switch (static_cast(c)) { case DBUS_STRUCT_BEGIN_CHAR: result = state.update_for_type(ArgumentType::structure); result = state.update_for_struct_start(); break; case DBUS_STRUCT_END_CHAR: result = state.update_for_struct_end(); break; case DBUS_DICT_ENTRY_BEGIN_CHAR: result = state.update_for_type(ArgumentType::dictionary_entry); result = state.update_for_dict_entry_start(); break; case DBUS_DICT_ENTRY_END_CHAR: result = state.update_for_dict_entry_end(); break; case DBUS_TYPE_ARRAY: result = state.update_for_type(static_cast(c)); result = state.update_for_array_start(); break; default: result = state.update_for_type(static_cast(c)); break; } return result; } bool is_void() const { return state.is_void; } std::string print(const std::shared_ptr& element, const Comma& comma) { std::stringstream ss; switch (element->argument) { case ArgumentType::invalid: if (element->children.size() > 1) ss << comma << "std::tuple<"; { Comma scoped_comma; for (auto child : element->children) ss << print(child, scoped_comma); } if (element->children.size() > 1) ss << ">"; ss << comma; break; case ArgumentType::byte: ss << comma << "std::uint8_t" << comma; break; case ArgumentType::boolean: ss << comma << "bool" << comma; break; case ArgumentType::int16: ss << comma << "std::int16_t" << comma; break; case ArgumentType::uint16: ss << comma << "std::uint16_t" << comma; break; case ArgumentType::int32: ss << comma << "std::int32_t" << comma; break; case ArgumentType::uint32: ss << comma << "std::uint32_t" << comma; break; case ArgumentType::int64: ss << comma << "std::int64_t" << comma; break; case ArgumentType::uint64: ss << comma << "std::uint64_t" << comma; break; case ArgumentType::floating_point: ss << comma << "double" << comma; break; case ArgumentType::string: ss << comma << "std::string" << comma; break; case ArgumentType::object_path: ss << comma << "core::dbus::types::ObjectPath" << comma; break; case ArgumentType::signature: ss << comma << "core::dbus::types::Signature" << comma; break; case ArgumentType::unix_fd: ss << comma << "core::dbus::types::UnixFd" << comma; break; case ArgumentType::variant: ss << comma << "core::dbus::types::Variant<>" << comma; break; case ArgumentType::array: ss << comma << "std::vector<"; { Comma scoped_comma; for (auto child : element->children) ss << print(child, scoped_comma); } ss << ">" << comma; break; case ArgumentType::structure: ss << comma << "std::tuple<"; { Comma scoped_comma; for (auto child : element->children) ss << print(child, scoped_comma); } ss << ">" << comma; break; case ArgumentType::dictionary_entry: ss << comma << "std::pair<"; { ss << print(element->children.front(), Comma()) << ", " << print(element->children.back(), Comma()) << ">" << comma; } break; default: break; } return ss.str(); } std::string print_type() { return state.is_void ? "void" : print(state.root, Comma()); } State state; }; class Interface { public: static const Interface& empty() { static const Interface interface{}; return interface; } Interface(const std::string& name) : d(new Private(name)) { } Interface(const Interface&) = default; Interface& operator=(const Interface& rhs) { d = rhs.d; return *this; } bool operator==(const Interface& rhs) const { return d == rhs.d; } const std::string& name() const { return d->name; } private: Interface() { } struct Private { Private(const std::string& name) : name(name) { } ~Private() { } std::string name; }; std::shared_ptr d; }; class Method { public: static const Method& empty() { static const Method method; return method; } Method(const std::string& name) : d(new Private(name)) { } Method(const Method&) = default; Method& operator=(const Method& rhs) { d = rhs.d; return *this; } bool operator==(const Method& rhs) const { return d == rhs.d; } const std::string& name() const { return d->name; } TypeMangler& in_type_mangler() { return d->in_type_mangler; } TypeMangler& out_type_mangler() { return d->out_type_mangler; } private: Method() { } struct Private { Private(const std::string& name) : name(name) { } std::string name; TypeMangler in_type_mangler; TypeMangler out_type_mangler; }; std::shared_ptr d; }; class Property { public: static const Property& empty() { static const Property property; return property; } Property(const std::string& name) : d(new Private(name)) { } Property(const Property&) = default; Property& operator=(const Property& rhs) { d = rhs.d; return *this; } bool operator==(const Property& rhs) const { return d == rhs.d; } const std::string& name() const { return d->name; } TypeMangler& argument_type_mangler() { return d->argument_type_mangler; } private: Property() { } struct Private { Private(const std::string& name) : name(name) { } std::string name; TypeMangler argument_type_mangler; }; std::shared_ptr d; }; class Signal { public: static const Signal& empty() { static const Signal signal; return signal; } Signal(const std::string& name) : d(new Private(name)) { } Signal(const Signal&) = default; Signal& operator=(const Signal& rhs) { d = rhs.d; return *this; } bool operator==(const Signal& rhs) const { return d == rhs.d; } const std::string& name() const { return d->name; } TypeMangler& argument_type_mangler() { return d->argument_type_mangler; } private: Signal() { } struct Private { Private(const std::string& name) : name(name) { } std::string name; TypeMangler argument_type_mangler; }; std::shared_ptr d; }; std::tuple, std::string> parse_namespaces_and_interface_from_dbus_name( const std::string& name) { using boost::algorithm::is_any_of; using boost::algorithm::make_split_iterator; static const std::string separator = "."; auto copy = name; boost::algorithm::split_iterator it = make_split_iterator( copy, boost::algorithm::token_finder(is_any_of(separator.c_str()))); auto itt(it); itt++; std::vector namespaces; while (!itt.eof()) { namespaces.push_back(std::string(it->begin(), it->end())); it++; itt++; } return std::make_tuple(namespaces, std::string(it->begin(), it->end())); } } struct Generator::Private { struct Context { struct { std::size_t count = 0; struct { std::string path; struct { File protocol_file; std::stringstream buffer; detail::Interface current = detail::Interface::empty(); struct { detail::Method current = detail::Method::empty(); } method; struct { std::size_t count = 0; detail::Property current = detail::Property::empty(); } properties; struct { std::size_t count = 0; detail::Signal current = detail::Signal::empty(); } signals; } interface; } node; } namespaces; std::stringstream raw_file_buffer; }; }; const GeneratorConfiguration& Generator::default_configuration() { static const GeneratorConfiguration config = { []() { auto tag = boost::uuids::random_generator()(); auto tag_string = boost::uuids::to_string(tag); boost::algorithm::to_upper(tag_string); boost::algorithm::replace_all(tag_string, "-", "_"); tag_string = "AUTO_" + tag_string; return tag_string; }, []() { auto ts = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now()); return std::asctime(std::localtime(&ts)); } }; return config; } Generator::Generator() : d(new Private{}) { } Generator::~Generator() { } bool Generator::invoke_for_model_with_configuration( const std::shared_ptr& element, std::istream& raw_file_contents, const GeneratorConfiguration& config) { using boost::filesystem::current_path; Private::Context context; bool state_is_tag_open = false; for (auto it = std::istreambuf_iterator(raw_file_contents); it != std::istreambuf_iterator(); ++it) { auto c = *it; switch (c) { case '<': state_is_tag_open = true; context.raw_file_buffer << c; continue; case '>': state_is_tag_open = false; context.raw_file_buffer << c; continue; case '"': context.raw_file_buffer << R"(\")"; continue; } if (std::iscntrl(c)) continue; if (!state_is_tag_open && std::isspace(c)) continue; context.raw_file_buffer << c; } auto visitor = [&context, &config](const Compiler::Element& element) { if (element.type() == Compiler::Element::Type::node) { context.namespaces.node.path = element.node().name; } else if (element.type() == Compiler::Element::Type::interface) { auto name = element.interface().name; auto ns_and_interface = detail::parse_namespaces_and_interface_from_dbus_name(name); std::vector namespaces = std::get<0>(ns_and_interface); std::string interface = std::get<1>(ns_and_interface); context.namespaces.node.interface.protocol_file.open( current_path() / (interface + ".h"), std::ios_base::out | std::ios_base::trunc); context.namespaces.node.interface.buffer << "/*" << std::endl << " * " << "Auto-generated header file." << std::endl << " * " << "Build timestamp: " << config.build_time_stamp_generator() << std::endl << "*/" << std::endl; auto include_guard = config.include_guard_generator(); context.namespaces.node.interface.buffer << "#ifndef " << include_guard << "_H_" << std::endl << "#define " << include_guard << "_H_" << std::endl << std::endl; context.namespaces.node.interface.buffer << "#include " << std::endl << std::endl << "#include " << std::endl << "#include " << std::endl << "#include " << std::endl << "#include " << std::endl << std::endl << "#include " << std::endl << std::endl; for (auto ns : namespaces) { context.namespaces.node.interface.buffer << "namespace " << ns << std::endl << "{" << std::endl; context.namespaces.count++; } context.namespaces.node.interface.buffer << "struct " << interface << std::endl << "{" << std::endl; context.namespaces.node.interface.buffer << "static const std::string& default_path() { static const std::string s{\"" << context.namespaces.node.path << "\"}; return s; }" << std::endl; context.namespaces.node.interface.buffer << "static const std::string& name() { static const std::string s{\"" << element.interface().name << "\"}; return s; }" << std::endl; context.namespaces.node.interface.buffer << "static const std::string& introspect() { static const std::string s{\"" << context.raw_file_buffer.str() << "\"}; return s; }" << std::endl; context.namespaces.node.interface.current = detail::Interface{interface}; } else if (element.type() == Compiler::Element::Type::property) { // We are stateful here in that we have to check whether // any signals are present on this interface. If so, we // have to close the enclosing struct, too. if (context.namespaces.node.interface.signals.count > 0) { context.namespaces.node.interface.buffer << "};" << std::endl; } // We are stateful here in that we have to check whether // any properties have been visited before. If so, we // have to open the enclosing struct, too. if (context.namespaces.node.interface.properties.count == 0) { context.namespaces.node.interface.buffer << "struct Properties" << std::endl << "{" << std::endl; } context.namespaces.node.interface.properties.count++; context.namespaces.node.interface.properties.current = detail::Property(element.property().name); context.namespaces.node.interface.buffer << "struct " << element.property().name << std::endl << "{" << std::endl; context.namespaces.node.interface.buffer << "typedef " << context.namespaces.node.interface.current.name() << " Interface;" << std::endl; context.namespaces.node.interface.buffer << "static const std::string& name() { static const std::string s{\"" << element.property().name << "\"}; return s; }" << std::endl; switch(element.property().access) { case IntrospectionParser::Property::Access::read: context.namespaces.node.interface.buffer << "static const bool readable = true;" << std::endl << "static const bool writable = false;" << std::endl; break; case IntrospectionParser::Property::Access::write: context.namespaces.node.interface.buffer << "static const bool readable = false;" << std::endl << "static const bool writable = true;" << std::endl; break; case IntrospectionParser::Property::Access::read_write: context.namespaces.node.interface.buffer << "static const bool readable = true;" << std::endl << "static const bool writable = true;" << std::endl; break; } context. namespaces. node. interface. properties. current. argument_type_mangler().update_from_signature( element.property().type); context.namespaces.node.interface.buffer << "typedef " << context.namespaces.node.interface.properties.current.argument_type_mangler().print_type() << " ArgumentType;" << std::endl; } else if (element.type() == Compiler::Element::Type::method) { context.namespaces.node.interface.buffer << "struct " << element.method().name << std::endl << "{" << std::endl; context.namespaces.node.interface.buffer << "typedef " << context.namespaces.node.interface.current.name() << " Interface;" << std::endl; context.namespaces.node.interface.buffer << "static const std::string& name() { static const std::string s{\"" << element.method().name << "\"}; return s; }" << std::endl; context.namespaces.node.interface.buffer << "static const std::chrono::milliseconds& default_timeout() { static const std::chrono::seconds s{10}; return s; }" << std::endl; context.namespaces.node.interface.method.current = detail::Method(element.method().name); } else if (element.type() == Compiler::Element::Type::signal) { // We are stateful here in that we have to check whether // any signals have been visited before. If so, we // have to open the enclosing struct, too. if (context.namespaces.node.interface.signals.count == 0) { context.namespaces.node.interface.buffer << "struct Signals" << std::endl << "{" << std::endl; } context.namespaces.node.interface.signals.count++; context.namespaces.node.interface.signals.current = detail::Signal(element.signal().name); context.namespaces.node.interface.buffer << "struct " << element.signal().name << std::endl << "{" << std::endl; context.namespaces.node.interface.buffer << "typedef " << context.namespaces.node.interface.current.name() << " Interface;" << std::endl; context.namespaces.node.interface.buffer << "static const std::string& name() { static const std::string s{\"" << element.signal().name << "\"}; return s; }" << std::endl; } else if (element.type() == Compiler::Element::Type::argument) { if (!(context.namespaces.node.interface.method.current == detail::Method::empty())) { switch(element.argument().direction) { case IntrospectionParser::Argument::Direction::in: context.namespaces.node.interface.method.current.in_type_mangler().update_from_signature( element.argument().type.begin(), element.argument().type.end()); break; case IntrospectionParser::Argument::Direction::out: context.namespaces.node.interface.method.current.out_type_mangler().update_from_signature( element.argument().type.begin(), element.argument().type.end()); break; case IntrospectionParser::Argument::Direction::context: context.namespaces.node.interface.method.current.in_type_mangler().update_from_signature( element.argument().type.begin(), element.argument().type.end()); context.namespaces.node.interface.method.current.out_type_mangler().update_from_signature( element.argument().type.begin(), element.argument().type.end()); break; } } else if (!(context.namespaces.node.interface.signals.current == detail::Signal::empty())) { context.namespaces.node.interface.signals.current.argument_type_mangler().update_from_signature(element.argument().type); } } }; auto post_visitor = [&context](const Compiler::Element& element) { if (element.type() == Compiler::Element::Type::interface) { // We are stateful here in that we have to check whether // any properties are present on this interface. If so, we // have to close the enclosing struct, too. if (context.namespaces.node.interface.properties.count > 0) context.namespaces.node.interface.buffer << "};" << std::endl; context.namespaces.node.interface.buffer << "};" << std::endl; for (unsigned int i = 0; i < context.namespaces.count; i++) { context.namespaces.node.interface.buffer << "}" << std::endl; } context.namespaces.node.interface.buffer << "#endif" << std::endl; } else if (element.type() == Compiler::Element::Type::property) { context.namespaces.node.interface.buffer << "};" << std::endl; context.namespaces.node.interface.properties.current = detail::Property::empty(); } else if (element.type() == Compiler::Element::Type::method) { context.namespaces.node.interface.buffer << "typedef " << context.namespaces.node.interface.method.current.in_type_mangler().print_type() << " ArgumentType;" << std::endl << "typedef " << context.namespaces.node.interface.method.current.out_type_mangler().print_type() << " ResultType;" << std::endl << "};" << std::endl; context.namespaces.node.interface.method.current = detail::Method::empty(); } else if (element.type() == Compiler::Element::Type::signal) { context.namespaces.node.interface.buffer << "typedef " << context.namespaces.node.interface.signals.current.argument_type_mangler().print_type() << " ArgumentType;" << std::endl << "};" << std::endl; context.namespaces.node.interface.signals.current = detail::Signal::empty(); } }; element->apply( std::function(), visitor, post_visitor); context.namespaces.node.interface.protocol_file << context.namespaces.node.interface.buffer.str(); return true; } } } dbus-cpp-5.0.3/src/core/dbus/introspection_parser.cpp000066400000000000000000000332501407013304700226720ustar00rootroot00000000000000/* * Copyright © 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Thomas Voß */ #include #include #include #include #include namespace core { namespace dbus { namespace { std::string safe_string_construct(const char* c) { return std::string((c ? c : "")); } } struct IntrospectionParser::Private { std::function on_node; std::function on_node_done; std::function on_interface; std::function on_interface_done; std::function on_method; std::function on_method_done; std::function on_property; std::function on_signal; std::function on_signal_done; std::function on_argument; std::function on_argument_done; std::function on_annotation; std::function on_annotation_done; }; IntrospectionParser::IntrospectionParser() : d(new Private()) { } IntrospectionParser::~IntrospectionParser() { } #define NAMED_ENUMERATION_ELEMENT(element) {element, #element} bool IntrospectionParser::invoke_for(const std::string& filename) { static const char* empty_encoding = nullptr; // We consciously do not check the dtd here static const int parser_options = 0; auto reader = std::shared_ptr( xmlReaderForFile(filename.c_str(), empty_encoding, parser_options), [](xmlTextReaderPtr reader) { if (reader == nullptr) return; xmlFreeTextReader(reader); }); if (!reader) return false; const std::map> vtable_done = { {Node::element_name(), d->on_node_done}, {Interface::element_name(), d->on_interface_done}, {Method::element_name(), d->on_method_done}, {Argument::element_name(), d->on_argument_done}, {Annotation::element_name(), d->on_annotation_done}, {Signal::element_name(), d->on_signal_done} }; const std::map> vtable = { { Annotation::element_name(), [this](xmlTextReaderPtr reader) { if (!d->on_annotation) return; d->on_annotation( Annotation{ safe_string_construct(reinterpret_cast(xmlTextReaderGetAttribute(reader, BAD_CAST Annotation::name_attribute_name()))), safe_string_construct(reinterpret_cast(xmlTextReaderGetAttribute(reader, BAD_CAST Annotation::value_attribute_name())))}); } }, { Node::element_name(), [this](xmlTextReaderPtr reader) { if (!d->on_node) return; auto attribute_name = reinterpret_cast( xmlTextReaderGetAttribute(reader, BAD_CAST Node::name_attribute_name())); d->on_node(Node{safe_string_construct(attribute_name)}); } }, { Interface::element_name(), [this](xmlTextReaderPtr reader) { if (!d->on_interface) return; d->on_interface( Interface{ safe_string_construct(reinterpret_cast( xmlTextReaderGetAttribute( reader, BAD_CAST Interface::name_attribute_name())))}); } }, { Argument::element_name(), [this](xmlTextReaderPtr reader) { if (!d->on_argument) return; static const std::map direction_lut = { {"", Argument::Direction::context}, {"in", Argument::Direction::in}, {"out", Argument::Direction::out} }; auto name_attribute = reinterpret_cast( xmlTextReaderGetAttribute( reader, BAD_CAST Argument::name_attribute_name())); Argument::Direction dir = Argument::Direction::context; try { dir = direction_lut.at( safe_string_construct(reinterpret_cast( xmlTextReaderGetAttribute( reader, BAD_CAST Argument::direction_attribute_name())))); } catch(const std::out_of_range& e) { throw std::runtime_error( std::string("Could not interpret direction for argument with name: ") + safe_string_construct(name_attribute)); } d->on_argument( Argument{ safe_string_construct(name_attribute), safe_string_construct(reinterpret_cast( xmlTextReaderGetAttribute( reader, BAD_CAST Argument::type_attribute_name()))), dir}); } }, { Method::element_name(), [this](xmlTextReaderPtr reader) { if (!d->on_method) return; d->on_method( Method{ safe_string_construct( reinterpret_cast( xmlTextReaderGetAttribute( reader, BAD_CAST Method::name_attribute_name())))}); } }, { Signal::element_name(), [this](xmlTextReaderPtr reader) { if (!d->on_signal) return; d->on_signal( Signal{ safe_string_construct( reinterpret_cast( xmlTextReaderGetAttribute( reader, BAD_CAST Signal::name_attribute_name())))}); } }, { Property::element_name(), [this](xmlTextReaderPtr reader) { if (!d->on_property) return; static const std::map access_lut = { {"read", Property::Access::read}, {"write", Property::Access::write}, {"readwrite", Property::Access::read_write} }; auto property_name = reinterpret_cast( xmlTextReaderGetAttribute( reader, BAD_CAST Property::name_attribute_name())); Property::Access a; try { a = access_lut.at( safe_string_construct(reinterpret_cast( xmlTextReaderGetAttribute( reader, BAD_CAST Property::access_attribute_name())))); } catch(const std::out_of_range& e) { throw std::runtime_error( std::string("Could not determine read/write setup of property ") + property_name); } d->on_property( Property{ safe_string_construct(property_name), safe_string_construct(reinterpret_cast( xmlTextReaderGetAttribute( reader, BAD_CAST Property::type_attribute_name()))), a}); } } }; enum class NodeType : int { attribute = 2, cdata = 4, comment = 8, document = 9, document_fragment = 11, document_type = 10, element = 1, end_element = 15, entity = 6, end_entity = 16, entity_reference = 5, none = 0, notation = 12, processing_instruction = 7, significant_whitespace = 14, text = 3, whitespace = 13, xml_declaration = 17 }; static std::map node_type_lut= { NAMED_ENUMERATION_ELEMENT(NodeType::attribute), NAMED_ENUMERATION_ELEMENT(NodeType::cdata), NAMED_ENUMERATION_ELEMENT(NodeType::comment), NAMED_ENUMERATION_ELEMENT(NodeType::document), NAMED_ENUMERATION_ELEMENT(NodeType::document_fragment), NAMED_ENUMERATION_ELEMENT(NodeType::document_type), NAMED_ENUMERATION_ELEMENT(NodeType::element), NAMED_ENUMERATION_ELEMENT(NodeType::end_element), NAMED_ENUMERATION_ELEMENT(NodeType::entity), NAMED_ENUMERATION_ELEMENT(NodeType::end_entity), NAMED_ENUMERATION_ELEMENT(NodeType::entity_reference), NAMED_ENUMERATION_ELEMENT(NodeType::none), NAMED_ENUMERATION_ELEMENT(NodeType::notation), NAMED_ENUMERATION_ELEMENT(NodeType::processing_instruction), NAMED_ENUMERATION_ELEMENT(NodeType::significant_whitespace), NAMED_ENUMERATION_ELEMENT(NodeType::text), NAMED_ENUMERATION_ELEMENT(NodeType::whitespace), NAMED_ENUMERATION_ELEMENT(NodeType::xml_declaration) }; enum class Status : int { has_more = 1, done = 0, error = -1, }; int status = xmlTextReaderRead(reader.get()); if (Status::error == static_cast(status)) return false; while (Status::has_more == static_cast(status)) { auto node_name = reinterpret_cast( xmlTextReaderConstName(reader.get())); switch(static_cast(xmlTextReaderNodeType(reader.get()))) { case NodeType::element: if (vtable.count(safe_string_construct(node_name)) > 0) { vtable.at(safe_string_construct(node_name))(reader.get()); } if (xmlTextReaderIsEmptyElement(reader.get())) { if (vtable_done.count(safe_string_construct(node_name)) > 0) { vtable_done.at(safe_string_construct(node_name))(); } } break; case NodeType::end_element: if (vtable_done.count( safe_string_construct((const char*) xmlTextReaderConstName(reader.get()))) > 0) { vtable_done.at(safe_string_construct((const char*) xmlTextReaderConstName(reader.get())))(); } break; default: break; } status = xmlTextReaderRead(reader.get()); } if (Status::error == static_cast(status)) return false; return Status::done == static_cast(status); } void IntrospectionParser::on_node(const std::function& f) { d->on_node = f; } void IntrospectionParser::on_node_done(const std::function& f) { d->on_node_done = f; } void IntrospectionParser::on_interface(const std::function& f) { d->on_interface = f; } void IntrospectionParser::on_interface_done(const std::function& f) { d->on_interface_done = f; } void IntrospectionParser::on_method(const std::function& f) { d->on_method = f; } void IntrospectionParser::on_method_done(const std::function& f) { d->on_method_done = f; } void IntrospectionParser::on_property(const std::function& f) { d->on_property = f; } void IntrospectionParser::on_signal(const std::function& f) { d->on_signal = f; } void IntrospectionParser::on_signal_done(const std::function& f) { d->on_signal_done = f; } void IntrospectionParser::on_argument(const std::function& f) { d->on_argument = f; } void IntrospectionParser::on_argument_done(const std::function& f) { d->on_argument_done = f; } void IntrospectionParser::on_annotation(const std::function& f) { d->on_annotation = f; } void IntrospectionParser::on_annotation_done(const std::function& f) { d->on_annotation_done = f; } } } dbus-cpp-5.0.3/src/core/dbus/match_rule.cpp000066400000000000000000000074121407013304700205420ustar00rootroot00000000000000/* * Copyright © 2012 Canonical Ltd-> * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Thomas Voß */ #include #include #include #include namespace dbus = core::dbus; namespace { struct Comma { Comma() : is_required(false) { } friend std::ostream& operator<<(std::ostream& out, const Comma& c) { if (c.is_required) out << ","; c.is_required = !c.is_required; return out; } mutable bool is_required; }; } struct dbus::MatchRule::Private { Message::Type type = Message::Type::invalid; std::string sender; std::string interface; std::string member; types::ObjectPath path; dbus::MatchRule::MatchArgs args; }; dbus::MatchRule::MatchRule() : d(new Private()) { } dbus::MatchRule::~MatchRule() { } dbus::MatchRule::MatchRule(const dbus::MatchRule& rhs) : d(new Private(*rhs.d)) { } dbus::MatchRule& dbus::MatchRule::operator=(const MatchRule& rhs) { *d = *rhs.d; return *this; } dbus::MatchRule& dbus::MatchRule::type(dbus::Message::Type t) { d->type = t; return *this; } dbus::MatchRule dbus::MatchRule::type(dbus::Message::Type t) const { MatchRule result {*this}; result.d->type = t; return result; } dbus::MatchRule& dbus::MatchRule::sender(const std::string& s) { d->sender = s; return *this; } dbus::MatchRule dbus::MatchRule::sender(const std::string& s) const { MatchRule result {*this}; result.d->sender = s; return result; } dbus::MatchRule& dbus::MatchRule::interface(const std::string& i) { d->interface = i; return *this; } dbus::MatchRule dbus::MatchRule::interface(const std::string& i) const { MatchRule result {*this}; result.d->interface = i; return result; } dbus::MatchRule& dbus::MatchRule::member(const std::string& m) { d->member = m; return *this; } dbus::MatchRule dbus::MatchRule::member(const std::string& m) const { MatchRule result {*this}; result.d->member = m; return result; } dbus::MatchRule& dbus::MatchRule::path(const types::ObjectPath& p) { d->path = p; return *this; } dbus::MatchRule dbus::MatchRule::path(const dbus::types::ObjectPath& p) const { MatchRule result {*this}; return result.path(p); } dbus::MatchRule& dbus::MatchRule::args(const MatchArgs& p) { d->args = p; return *this; } dbus::MatchRule& dbus::MatchRule::args(const MatchArgs& p) const { MatchRule result {*this}; return result.args(p); } std::string dbus::MatchRule::as_string() const { Comma comma; std::stringstream ss; if (d->type != Message::Type::invalid) ss << "type='" << d->type << "'" << comma; if (!d->sender.empty()) ss << comma << "sender='" << d->sender << "'" << comma; if (!d->interface.empty()) ss << comma << "interface='" << d->interface << "'" << comma; if (!d->member.empty()) ss << comma << "member='" << d->member << "'" << comma; if (!d->path.empty()) ss << comma << "path='" << d->path.as_string() << "'" << comma; for(const MatchArg& arg: d->args) { ss << comma << "arg" << arg.first << "='" << arg.second << "'" << comma; } return ss.str(); } dbus-cpp-5.0.3/src/core/dbus/message.cpp000066400000000000000000000451261407013304700200470ustar00rootroot00000000000000/* * Copyright © 2012 Canonical Ltd-> * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Thomas Voß */ #include #include #include #include #include #include "message_p.h" #include #include #include #include #include #include #include #include namespace core { namespace dbus { Message::Reader::Reader() { } Message::Reader::Reader(const std::shared_ptr& msg) : d(new Private(msg)) { if (!msg) throw std::runtime_error( "Precondition violated, cannot construct Reader for null message."); } Message::Reader::Reader(Message::Reader&& that) : d(std::move(that.d)) { } Message::Reader& Message::Reader::operator=(Message::Reader&& rhs) { d = std::move(rhs.d); return *this; } Message::Reader::~Reader() { } ArgumentType Message::Reader::type() const { return static_cast( dbus_message_iter_get_arg_type( std::addressof(d->iter))); } void Message::Reader::pop() { dbus_message_iter_next(std::addressof(d->iter)); } std::int8_t Message::Reader::pop_byte() { d->ensure_argument_type_or_throw(ArgumentType::byte); std::int8_t result; dbus_message_iter_get_basic( std::addressof(d->iter), std::addressof(result)); dbus_message_iter_next(std::addressof(d->iter)); return result; } bool Message::Reader::pop_boolean() { d->ensure_argument_type_or_throw(ArgumentType::boolean); dbus_bool_t result; dbus_message_iter_get_basic( std::addressof(d->iter), std::addressof(result)); dbus_message_iter_next(std::addressof(d->iter)); return !!result; } std::int16_t Message::Reader::pop_int16() { d->ensure_argument_type_or_throw(ArgumentType::int16); std::int16_t result; dbus_message_iter_get_basic( std::addressof(d->iter), std::addressof(result)); dbus_message_iter_next(std::addressof(d->iter)); return result; } std::uint16_t Message::Reader::pop_uint16() { d->ensure_argument_type_or_throw(ArgumentType::uint16); std::uint16_t result; dbus_message_iter_get_basic( std::addressof(d->iter), std::addressof(result)); dbus_message_iter_next(std::addressof(d->iter)); return result; } std::int32_t Message::Reader::pop_int32() { d->ensure_argument_type_or_throw(ArgumentType::int32); std::int32_t result; dbus_message_iter_get_basic( std::addressof(d->iter), std::addressof(result)); dbus_message_iter_next(std::addressof(d->iter)); return result; } std::uint32_t Message::Reader::pop_uint32() { d->ensure_argument_type_or_throw(ArgumentType::uint32); std::uint32_t result; dbus_message_iter_get_basic( std::addressof(d->iter), std::addressof(result)); dbus_message_iter_next(std::addressof(d->iter)); return result; } std::int64_t Message::Reader::pop_int64() { d->ensure_argument_type_or_throw(ArgumentType::int64); std::int64_t result; dbus_message_iter_get_basic( std::addressof(d->iter), std::addressof(result)); dbus_message_iter_next(std::addressof(d->iter)); return result; } std::uint64_t Message::Reader::pop_uint64() { d->ensure_argument_type_or_throw(ArgumentType::uint64); std::uint64_t result; dbus_message_iter_get_basic( std::addressof(d->iter), std::addressof(result)); dbus_message_iter_next(std::addressof(d->iter)); return result; } double Message::Reader::pop_floating_point() { d->ensure_argument_type_or_throw(ArgumentType::floating_point); double result; dbus_message_iter_get_basic( std::addressof(d->iter), std::addressof(result)); dbus_message_iter_next(std::addressof(d->iter)); return result; } const char* Message::Reader::pop_string() { d->ensure_argument_type_or_throw(ArgumentType::string); return d->pop_string_unchecked(); } types::ObjectPath Message::Reader::pop_object_path() { d->ensure_argument_type_or_throw(ArgumentType::object_path); return types::ObjectPath(d->pop_string_unchecked()); } types::Signature Message::Reader::pop_signature() { d->ensure_argument_type_or_throw(ArgumentType::signature); return types::Signature(d->pop_string_unchecked()); } types::UnixFd Message::Reader::pop_unix_fd() { d->ensure_argument_type_or_throw(ArgumentType::unix_fd); int result = -1; dbus_message_iter_get_basic( std::addressof(d->iter), std::addressof(result)); dbus_message_iter_next(std::addressof(d->iter)); return types::UnixFd(result); } Message::Reader Message::Reader::pop_array() { Reader result(d->msg); dbus_message_iter_recurse( std::addressof(d->iter), std::addressof(result.d->iter)); dbus_message_iter_next(std::addressof(d->iter)); return result; } Message::Reader Message::Reader::pop_structure() { Reader result(d->msg); dbus_message_iter_recurse( std::addressof(d->iter), std::addressof(result.d->iter)); dbus_message_iter_next(std::addressof(d->iter)); return result; } Message::Reader Message::Reader::pop_variant() { Reader result(d->msg); dbus_message_iter_recurse( std::addressof(d->iter), std::addressof(result.d->iter)); dbus_message_iter_next(std::addressof(d->iter)); return result; } Message::Reader Message::Reader::pop_dict_entry() { Reader result(d->msg); dbus_message_iter_recurse( std::addressof(d->iter), std::addressof(result.d->iter)); dbus_message_iter_next(std::addressof(d->iter)); return result; } const std::shared_ptr& Message::Reader::access_message() { return d->msg; } Message::Writer::Writer(const std::shared_ptr& msg) : d(new Private{msg, DBusMessageIter()}) { if (!msg) throw std::runtime_error( "Precondition violated, cannot construct Writer for null message."); ::memset(std::addressof(d->iter), 0, sizeof(d->iter)); } Message::Writer::~Writer() { } Message::Writer::Writer(Message::Writer&& that) : d(std::move(that.d)) { } Message::Writer& Message::Writer::operator=(Message::Writer&& rhs) { d = std::move(rhs.d); return *this; } void Message::Writer::push_byte(std::int8_t value) { if (!dbus_message_iter_append_basic( std::addressof(d->iter), static_cast(ArgumentType::byte), std::addressof(value))) throw std::runtime_error("Not enough memory to append data to message."); } void Message::Writer::push_boolean(bool value) { auto bool_value = value ? TRUE : FALSE; if (!dbus_message_iter_append_basic( std::addressof(d->iter), static_cast(ArgumentType::boolean), std::addressof(bool_value))) throw std::runtime_error("Not enough memory to append data to message."); } void Message::Writer::push_int16(std::int16_t value) { if (!dbus_message_iter_append_basic( std::addressof(d->iter), static_cast(ArgumentType::int16), std::addressof(value))) throw std::runtime_error("Not enough memory to append data to message."); } void Message::Writer::push_uint16(std::uint16_t value) { if (!dbus_message_iter_append_basic( std::addressof(d->iter), static_cast(ArgumentType::uint16), std::addressof(value))) throw std::runtime_error("Not enough memory to append data to message."); } void Message::Writer::push_int32(std::int32_t value) { if (!dbus_message_iter_append_basic( std::addressof(d->iter), static_cast(ArgumentType::int32), std::addressof(value))) throw std::runtime_error("Not enough memory to append data to message."); } void Message::Writer::push_uint32(std::uint32_t value) { if (!dbus_message_iter_append_basic( std::addressof(d->iter), static_cast(ArgumentType::uint32), std::addressof(value))) throw std::runtime_error("Not enough memory to append data to message."); } void Message::Writer::push_int64(std::int64_t value) { if (!dbus_message_iter_append_basic( std::addressof(d->iter), static_cast(ArgumentType::int64), std::addressof(value))) throw std::runtime_error("Not enough memory to append data to message."); } void Message::Writer::push_uint64(std::uint64_t value) { if (!dbus_message_iter_append_basic( std::addressof(d->iter), static_cast(ArgumentType::uint64), std::addressof(value))) throw std::runtime_error("Not enough memory to append data to message."); } void Message::Writer::push_floating_point(double value) { if (!dbus_message_iter_append_basic( std::addressof(d->iter), static_cast(ArgumentType::floating_point), std::addressof(value))) throw std::runtime_error("Not enough memory to append data to message."); } void Message::Writer::push_stringn(const char* value, std::size_t) { if (!dbus_message_iter_append_basic( std::addressof(d->iter), static_cast(ArgumentType::string), std::addressof(value))) throw std::runtime_error("Not enough memory to append data to message."); } void Message::Writer::push_object_path(const types::ObjectPath& value) { const char* s = value.as_string().c_str(); if (!dbus_message_iter_append_basic( std::addressof(d->iter), static_cast(ArgumentType::object_path), &s)) throw std::runtime_error("Not enough memory to append data to message."); } void Message::Writer::push_signature(const types::Signature& value) { const char* s = value.as_string().c_str(); if (!dbus_message_iter_append_basic( std::addressof(d->iter), static_cast(ArgumentType::signature), &s)) throw std::runtime_error("Not enough memory to append data to message."); } void Message::Writer::push_unix_fd(const types::UnixFd& value) { if (!dbus_message_iter_append_basic( std::addressof(d->iter), static_cast(ArgumentType::unix_fd), std::addressof(value.to_int()))) throw std::runtime_error("Not enough memory to append data to message."); } Message::Writer Message::Writer::open_array(const types::Signature& signature) { Writer w(d->msg); if (!dbus_message_iter_open_container( std::addressof(d->iter), static_cast(ArgumentType::array), signature.as_string().c_str(), std::addressof(w.d->iter))) throw std::runtime_error("Problem opening container"); return w; } void Message::Writer::close_array(Message::Writer w) { dbus_message_iter_close_container( std::addressof(d->iter), std::addressof(w.d->iter)); } Message::Writer Message::Writer::open_structure() { Writer w(d->msg); if (!dbus_message_iter_open_container( std::addressof(d->iter), static_cast(ArgumentType::structure), nullptr, std::addressof(w.d->iter))) throw std::runtime_error("Problem opening container"); return w; } void Message::Writer::close_structure(Message::Writer w) { dbus_message_iter_close_container( std::addressof(d->iter), std::addressof(w.d->iter)); } Message::Writer Message::Writer::open_variant(const types::Signature& signature) { // TODO(tvoss): We really should check that the signature refers to a // single complete type here. Writer w(d->msg); if (!dbus_message_iter_open_container( std::addressof(d->iter), static_cast(ArgumentType::variant), signature.as_string().c_str(), std::addressof(w.d->iter))) throw std::runtime_error("Problem opening container"); return w; } void Message::Writer::close_variant(Writer w) { dbus_message_iter_close_container( std::addressof(d->iter), std::addressof(w.d->iter)); } Message::Writer Message::Writer::open_dict_entry() { Writer w(d->msg); if (!dbus_message_iter_open_container( std::addressof(d->iter), static_cast(ArgumentType::dictionary_entry), nullptr, std::addressof(w.d->iter))) throw std::runtime_error("Problem opening container"); return w; } void Message::Writer::close_dict_entry(Message::Writer w) { dbus_message_iter_close_container( std::addressof(d->iter), std::addressof(w.d->iter)); } std::shared_ptr Message::make_method_call( const std::string& destination, const types::ObjectPath& path, const std::string& interface, const std::string& method) { return std::shared_ptr( new Message( std::unique_ptr( new Message::Private( dbus_message_new_method_call( destination.c_str(), path.as_string().c_str(), interface.c_str(), method.c_str()))))); } std::shared_ptr Message::make_method_return(const Message::Ptr& msg) { return std::shared_ptr( new Message( std::unique_ptr( new Message::Private( dbus_message_new_method_return( msg->d->dbus_message.get()))))); } std::shared_ptr Message::make_signal( const std::string& path, const std::string& interface, const std::string& signal) { return std::shared_ptr( new Message( std::unique_ptr( new Message::Private( dbus_message_new_signal( path.c_str(), interface.c_str(), signal.c_str()))))); } std::shared_ptr Message::make_error( const Message::Ptr& in_reply_to, const std::string& error_name, const std::string& error_desc) { return std::shared_ptr( new Message( std::unique_ptr( new Message::Private( dbus_message_new_error( in_reply_to->d->dbus_message.get(), error_name.c_str(), error_desc.c_str()))))); } std::shared_ptr Message::from_raw_message(DBusMessage* msg) { return std::shared_ptr( new Message( std::unique_ptr( new Message::Private( msg, true)))); } Message::Type Message::type() const { return static_cast(dbus_message_get_type(d->dbus_message.get())); } bool Message::expects_reply() const { return !dbus_message_get_no_reply(d->dbus_message.get()); } types::ObjectPath Message::path() const { return types::ObjectPath(dbus_message_get_path(d->dbus_message.get())); } std::string Message::member() const { return dbus_message_get_member(d->dbus_message.get()); } std::string Message::signature() const { return dbus_message_get_signature(d->dbus_message.get()); } std::string Message::interface() const { return dbus_message_get_interface(d->dbus_message.get()); } std::string Message::destination() const { return dbus_message_get_destination(d->dbus_message.get()); } std::string Message::sender() const { return dbus_message_get_sender(d->dbus_message.get()); } Error Message::error() const { if (type() != Message::Type::error) throw std::runtime_error("Message does not contain error information"); Error result; dbus_set_error_from_message(std::addressof(result.raw()), d->dbus_message.get()); return result; } Message::Reader Message::reader() { Reader result{shared_from_this()}; if (!dbus_message_iter_init( d->dbus_message.get(), std::addressof(result.d->iter))) throw std::runtime_error( "Could not initialize reader, message does not have arguments"); return result; } Message::Writer Message::writer() { Writer w(shared_from_this()); dbus_message_iter_init_append( d->dbus_message.get(), std::addressof(w.d->iter)); return w; } void Message::ensure_serial_larger_than_zero_for_testing() { dbus_message_set_serial(d->dbus_message.get(), 2); } Message::Message(std::unique_ptr p) : d(std::move(p)) { if (!d->dbus_message) throw std::runtime_error( "Precondition violated, cannot construct Message from null DBusMessage."); } Message::~Message() { } std::shared_ptr Message::clone() { return std::shared_ptr(new Message(d->clone())); } std::ostream& operator<<(std::ostream& out, Message::Type type) { switch (type) { case Message::Type::error: return out << "error"; case Message::Type::invalid: return out << "invalid"; case Message::Type::method_call: return out << "method_call"; case Message::Type::method_return: return out << "method_return"; case Message::Type::signal: return out << "signal"; } return out; } } } dbus-cpp-5.0.3/src/core/dbus/message_factory_impl.h000066400000000000000000000037051407013304700222610ustar00rootroot00000000000000/* * Copyright © 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Thomas Voß */ #ifndef CORE_DBUS_MESSAGE_FACTORY_IMPL_H_ #define CORE_DBUS_MESSAGE_FACTORY_IMPL_H_ #include namespace core { namespace dbus { namespace impl { struct MessageFactory : public core::dbus::MessageFactory { MessageFactory() = default; inline std::shared_ptr make_method_call( const std::string& destination, const types::ObjectPath& path, const std::string& interface, const std::string& method) { return Message::make_method_call(destination, path, interface, method); } inline std::shared_ptr make_method_return(const Message::Ptr& msg) { return Message::make_method_return(msg); } inline std::shared_ptr make_signal( const std::string& path, const std::string& interface, const std::string& signal) { return Message::make_signal(path, interface, signal); } inline std::shared_ptr make_error( const Message::Ptr& in_reply_to, const std::string& error_name, const std::string& error_desc) { return Message::make_error(in_reply_to, error_name, error_desc); } }; } } } #endif // CORE_DBUS_MESSAGE_FACTORY_H_ dbus-cpp-5.0.3/src/core/dbus/message_impl.h000066400000000000000000000313071407013304700205310ustar00rootroot00000000000000/* * Copyright © 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Thomas Voß */ #ifndef CORE_DBUS_MESSAGE_H_ #define CORE_DBUS_MESSAGE_H_ #include #include #include #include #include #include #include #include #include #include #include #include #include namespace core { namespace dbus { template struct Codec; class Error; namespace impl { /** * @brief The Message class wraps a raw DBus message */ class Message : public std::enable_shared_from_this { public: typedef std::shared_ptr Ptr; /** * @brief The Type enum models the type of the message. */ enum class Type : int { invalid = DBUS_MESSAGE_TYPE_INVALID, ///< Invalid message type signal = DBUS_MESSAGE_TYPE_SIGNAL, ///< A signal message method_call = DBUS_MESSAGE_TYPE_METHOD_CALL, ///< A method-call message method_return = DBUS_MESSAGE_TYPE_METHOD_RETURN, ///< A method-return message error = DBUS_MESSAGE_TYPE_ERROR ///< An error message. }; /** * @brief The Reader class allows type-safe reading of arguments from a message. */ class Reader { public: ~Reader(); Reader(const Reader&) = delete; Reader& operator=(const Reader&) = delete; Reader(Reader&&); Reader& operator=(Reader&&); /** * @brief Returns the current type. * */ ArgumentType type() const; /** * @brief Advances this view into the message. */ void pop(); /** * @brief Reads a byte from the underlying message. */ std::int8_t pop_byte(); /** * @brief Reads a boolean from the underlying message. */ bool pop_boolean(); /** * @brief Reads an int16 from the underlying message. */ std::int16_t pop_int16(); /** * @brief Reads a uint16 from the underlying message. */ std::uint16_t pop_uint16(); /** * @brief Reads an int32 from the underlying message. */ std::int32_t pop_int32(); /** * @brief Reads a uint32 from the underlying message. */ std::uint32_t pop_uint32(); /** * @brief Reads an int64 from the underlying message. */ std::int64_t pop_int64(); /** * @brief Reads a uint64 from the underlying message. */ std::uint64_t pop_uint64(); /** * @brief Reads a floating point value from the underlying message. */ double pop_floating_point(); /** * @brief Reads a string from the underlying message. */ const char* pop_string(); /** * @brief Reads an object_path from the underlying message. */ types::ObjectPath pop_object_path(); /** * @brief Reads a signature from the underlying message. */ types::Signature pop_signature(); /** * @brief Reads a unix fd from the underlying message. */ types::UnixFd pop_unix_fd(); /** * @brief Prepares reading of an array from the underlying message. * @return A reader pointing to the array. */ Reader pop_array(); /** * @brief Prepares reading of a structure from the underlying message. * @return A reader pointing into the structure. */ Reader pop_structure(); /** * @brief Prepares reading of a variant from the underlying message. * @return A reader pointing into the variant. */ Reader pop_variant(); /** * @brief Prepares reading of a dict entry from the underlying message. * @return A reader pointing to the array. */ Reader pop_dict_entry(); private: friend struct Codec; friend class Message; explicit Reader(const std::shared_ptr& msg); const std::shared_ptr& access_message(); struct Private; std::unique_ptr d; }; /** * @brief The Writer class allows type-safe serialization of input arguments to a message. */ class Writer { public: ~Writer(); Writer(const Writer&) = delete; Writer& operator=(const Writer&) = delete; Writer(Writer&&); Writer& operator=(Writer&&); /** * @brief Writes a byte to the underlying message. */ void push_byte(std::int8_t value); /** * @brief Writes a boolean to the underlying message. */ void push_boolean(bool value); /** * @brief Writes an int16 to the underlying message. */ void push_int16(std::int16_t value); /** * @brief Writes a uint16 to the underlying message. */ void push_uint16(std::uint16_t value); /** * @brief Writes an int32 to the underlying message. */ void push_int32(std::int32_t value); /** * @brief Writes a uint32 to the underlying message. */ void push_uint32(std::uint32_t value); /** * @brief Writes an int64 to the underlying message. */ void push_int64(std::int64_t value); /** * @brief Writes a uint64 to the underlying message. */ void push_uint64(std::uint64_t value); /** * @brief Writes a floating point value to the underlying message. */ void push_floating_point(double value); /** * @brief Writes a string to the underlying message. */ void push_stringn(const char* value, std::size_t size); /** * @brief Writes an object_path to the underlying message. */ void push_object_path(const types::ObjectPath& value); /** * @brief Writes a signature to the underlying message. */ void push_signature(const types::Signature& value); /** * @brief Writes a unix fd to the underlying message. */ void push_unix_fd(const types::UnixFd& value); /** * @brief Prepares writing of an array to the underlying message. * @param [in] signature The signature of the contained data type. */ Writer open_array(const types::Signature& signature); /** * @brief Finalizes writing of an array to the underlying message. */ void close_array(Writer writer); /** * @brief Prepares writing of a structure to the underlying message. */ Writer open_structure(); /** * @brief Finalizes writing of a structure to the underlying message. */ void close_structure(Writer writer); /** * @brief Prepares writing of a variant to the underlying message. * @param [in] signature The signature of the contained data type. */ Writer open_variant(const types::Signature& signature); /** * @brief Finalizes writing of a variant to the underlying message. */ void close_variant(Writer writer); /** * @brief Prepares writing of a dict entry to the underlying message. */ Writer open_dict_entry(); /** * @brief Finalizes writing of a dict entry to the underlying message. */ void close_dict_entry(Writer writer); private: friend class Message; explicit Writer(const std::shared_ptr& msg); struct Private; std::unique_ptr d; }; /** * @brief make_method_call creates an instance of Message with type Type::method_call. * @param destination The name of the remote service to send the message to. * @param path The name of the remote object to send the message to. * @param interface The interface to route the message to. * @param method The actual method that should be invoked * @return An instance of message of type Type::method_call. * @throw std::runtime_error if any of the parameters violates the DBus specification. */ static std::shared_ptr make_method_call( const std::string& destination, const types::ObjectPath& path, const std::string& interface, const std::string& method); /** * @brief make_method_return creates a message instance in response to a raw DBus message of type method-call. * @param msg The message to reply to, must not be null. Must be of type Type::method_call. * @return An instance of message of type Type::method_return. */ static std::shared_ptr make_method_return(const Message::Ptr& msg); /** * @brief make_signal creates a message instance wrapping a signal emission. * @param path The path of the object emitting the signal. * @param interface The interface containing the signal. * @param signal The actual signal name. * @return An instance of message of type Type::signal. */ static std::shared_ptr make_signal( const std::string& path, const std::string& interface, const std::string& signal); /** * @brief make_error creates an error message instance in response to a raw DBus message of type method-call. * @param in_reply_to The message to reply to, must not be null. Must be of type Type::method_call. * @param error_name The name of the error. * @param error_desc Human-readable description of the error. * @return An instance of message of type Type::error. */ static std::shared_ptr make_error( const Message::Ptr& in_reply_to, const std::string& error_name, const std::string& error_desc); /** * @brief from_raw_message creates an instance of message from a raw message. * @param msg The message to wrap. * @return An instance of Message with a type corresponding to the type of the raw message. */ static std::shared_ptr from_raw_message(DBusMessage* msg); ~Message(); /** * @brief Queries the type of the message. */ Type type() const; /** * @brief Checks if the message expects a reply, i.e., is of type Type::method_call. */ bool expects_reply() const; /** * @brief Queries the path of the object that this message belongs to. */ types::ObjectPath path() const; /** * @brief Queries the member name that this message corresponds to. */ std::string member() const; /** * @brief Queries the type signature of this message. */ std::string signature() const; /** * @brief Queries the interface name that this message corresponds to. */ std::string interface() const; /** * @brief Queries the name of the destination that this message should go to. */ std::string destination() const; /** * @brief Queries the name of the sender that this message originates from. */ std::string sender() const; /** * @brief Extracts error information from the message. * @throw std::runtime_error if not an error message. */ Error error() const; /** * @brief Creates a Reader instance to read from this message. */ Reader reader(); /** * @brief Creates a Writer instance to write to this message. */ Writer writer(); /** * @brief Extracts the raw DBus message contained within this instance. Use with care. */ DBusMessage* get() const; private: friend struct Codec; friend class MessageFactory; Message( DBusMessage* msg, bool ref_on_construction = false); std::shared_ptr clone(); std::shared_ptr dbus_message; }; } } } #include "impl/message.h> #endif // CORE_DBUS_MESSAGE_H_ dbus-cpp-5.0.3/src/core/dbus/message_p.h000066400000000000000000000051051407013304700200240ustar00rootroot00000000000000/* * Copyright © 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Thomas Voß */ #ifndef CORE_DBUS_MESSAGE_P_H_ #define CORE_DBUS_MESSAGE_P_H_ #include #include #include namespace core { namespace dbus { struct Message::Reader::Private { Private(const std::shared_ptr& msg) : msg(msg) { ::memset(std::addressof(iter), 0, sizeof(iter)); } ~Private() { } void ensure_argument_type_or_throw(ArgumentType expected_type) { auto actual_type = static_cast(dbus_message_iter_get_arg_type(std::addressof(iter))); if (actual_type != expected_type) { std::stringstream ss; ss << "Mismatch between expected and actual type reported by iterator: " << std::endl << "\t Expected: " << expected_type << std::endl << "\t Actual: " << actual_type; throw std::runtime_error(ss.str()); } } const char* pop_string_unchecked() { char* result = nullptr; dbus_message_iter_get_basic( std::addressof(iter), std::addressof(result)); dbus_message_iter_next(std::addressof(iter)); return result; } std::shared_ptr msg; DBusMessageIter iter; }; struct Message::Writer::Private { std::shared_ptr msg; DBusMessageIter iter; }; struct Message::Private { Private(DBusMessage* msg, bool ref_on_construction = false) : dbus_message( msg, [](DBusMessage* msg) {if (msg) dbus_message_unref(msg);}) { if (ref_on_construction) dbus_message_ref(msg); } std::unique_ptr clone() { return std::unique_ptr( new Private( dbus_message_copy(dbus_message.get()))); } std::shared_ptr dbus_message; }; } } #endif // CORE_DBUS_MESSAGE_P_H_ dbus-cpp-5.0.3/src/core/dbus/pending_call_impl.h000066400000000000000000000163751407013304700215340ustar00rootroot00000000000000/* * Copyright © 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Thomas Voß */ #ifndef CORE_DBUS_PENDING_CALL_IMPL_H_ #define CORE_DBUS_PENDING_CALL_IMPL_H_ #include #include #include #include namespace { // Better save than sorry. We wrap common error handling here. bool is_pending_call_completed(DBusPendingCall* pending_call) { if (not pending_call) return false; return dbus_pending_call_get_completed(pending_call) == TRUE; } } namespace core { namespace dbus { namespace impl { class PendingCall : public core::dbus::PendingCall { private: // We explicitly maintain the state of the pending call // to avoid races during initialization and callbacks happening. enum class State { // We haven't received a result yet. pending, // We have received a result and either called out // to application code or stored the answer to // our request in a message for later processing completed }; // We keep an instance alive by passing the pending call // wrapped in an ordinary heap-allocated wrapper to the // notification callback. struct Wrapper { std::shared_ptr pending_call; }; // The callback that is passed to libdbus. static void on_pending_call_completed(DBusPendingCall* call, void* cookie) { auto wrapper = static_cast(cookie); if (not wrapper) return; // We tie cleanup of the wrapper to the scope of the callback. // With that, even an exception being thrown would _not_ result // in an instance being leaked. struct Scope { ~Scope() { // We always unref this message, even if notify_locked or // from_raw_message throws. if (message) dbus_message_unref(message); } // We only need this later on, when we have stolen the reply // from the pending call. DBusMessage* message; } scope{nullptr}; // We synchronize to avoid races on construction. std::lock_guard lg{wrapper->pending_call->guard}; // And we only steal the reply if the call actually completed. if (is_pending_call_completed(call)) if (nullptr != (scope.message = dbus_pending_call_steal_reply(call))) wrapper->pending_call->notify_locked(Message::from_raw_message(scope.message)); } // Announce incoming reply and invoke the callback if set. // Atomically maintains the state of this call instance. void notify_locked(const Message::Ptr& msg) { if (state.exchange(State::completed) == State::completed) return; message = msg; if (callback) callback(message); } public: // Creates a new PendingCall instance given the opaque call instance // handed out by libdbus. Throws in case of errors. inline static core::dbus::PendingCall::Ptr create(DBusPendingCall* call) { auto result = std::shared_ptr { new core::dbus::impl::PendingCall{call} }; // Our scope contains two objects that are dynamically created: // * The actual PendingCall implementation (managed by a shared pointer) // * A helper object of type Wrapper for passing around the pending call instance. // The latter one needs some manual memory mgmt. until we are sure that it got handed // over to libdbus correctly. struct Scope { // Whenever we go out of scope, we unref the call (we do not need it anymore) // and we potentially (if armed) delete the wrapper. ~Scope() { dbus_pending_call_unref(call); if (message) dbus_message_unref(message); } // The raw call instance. DBusPendingCall* call; // Non-null if we managed to steal the reply. DBusMessage* message; } scope { // The raw call that we got handed from the caller. call, // Initialize the message to null to make sure that we // do not unref garbage. nullptr }; // We synchronize to avoid races on construction. std::lock_guard lg{result->guard}; // We dispatch to the static on_pending_call_completed when // the call completes. // Please refer to the source-code comments in on_pending_call_completed. if (FALSE == dbus_pending_call_set_notify( result->pending_call, PendingCall::on_pending_call_completed, new Wrapper{result}, [](void* p){ delete static_cast(p); })) { throw std::runtime_error("Error setting up pending call notification."); } // And here comes the beauty of libdbus, and its racy architecture: if (is_pending_call_completed(call)) { // We took too long while setting up the pending call notification. // For that we now have to inject the message here. if (nullptr != (scope.message = dbus_pending_call_steal_reply(call))) result->notify_locked(Message::from_raw_message(scope.message)); } return result; } // Cancels the outstanding call. void cancel() override { dbus_pending_call_cancel(pending_call); } // Installs a continuation and invokes it if the call already completed. void then(const core::dbus::PendingCall::Notification& notification) override { std::lock_guard lg(guard); callback = notification; // We already have a reply and invoke the callback directly. if (message) callback(message); } private: PendingCall(DBusPendingCall* call) : state(State::pending), pending_call(call) { if (not call) throw std::runtime_error { "core::dbus::PendingCall cannot be constructed for null object." }; } // Our internal state, initialized to State::pending. std::atomic state; // Our pending call instance. DBusPendingCall* pending_call; // We synchronize access to the following two members. std::mutex guard; // The reply message. Message::Ptr message; // The callback, invoked when either the call completed or // if the callback is installed when the call already completed. PendingCall::Notification callback; }; } } } #endif // CORE_DBUS_PENDING_CALL_IMPL_H_ dbus-cpp-5.0.3/src/core/dbus/service.cpp000066400000000000000000000072601407013304700200600ustar00rootroot00000000000000/* * Copyright © 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Thomas Voß */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace core { namespace dbus { Service::Ptr Service::use_service(const Bus::Ptr& connection, const std::string& name) { return Ptr(new Service(connection, name)); } Service::Ptr Service::use_service_or_throw_if_not_available(const Bus::Ptr& connection, const std::string& name) { if (!connection->has_owner_for_name(name)) throw std::runtime_error(name + " is not owned on the bus"); return Ptr(new Service(connection, name)); } const std::string& Service::get_name() const { return name; } bool Service::is_stub() const { return stub; } const Bus::Ptr& Service::get_connection() const { return connection; } void Service::add_match(const MatchRule& rule) { connection->add_match(rule.sender(name)); } void Service::remove_match(const MatchRule& rule) { connection->remove_match(rule.sender(name)); } Service::Service(const Bus::Ptr& connection, const std::string& name) : connection(connection), name(name), stub(true) { } Service::Service(const Bus::Ptr& connection, const std::string& name, const Bus::RequestNameFlag& flags) : connection(connection), name(name), stub(false) { Error error; auto rc = dbus_bus_request_name( connection->raw(), name.c_str(), static_cast(flags), std::addressof(error.raw())); if (error) throw std::runtime_error(error.name() + ": " + error.message()); switch (rc) { case DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER: break; case DBUS_REQUEST_NAME_REPLY_IN_QUEUE: break; case DBUS_REQUEST_NAME_REPLY_EXISTS: throw Bus::Errors::AlreadyOwned{}; break; case DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER: throw Bus::Errors::AlreadyOwner{}; break; case -1: throw std::runtime_error(error.print()); } } const std::shared_ptr& Service::root_object() { if (!root) root = std::shared_ptr(new Object(shared_from_this(), types::ObjectPath::root())); return root; } std::shared_ptr Service::object_for_path(const types::ObjectPath& path) { return std::shared_ptr(new Object(shared_from_this(), path)); } std::shared_ptr Service::add_object_for_path(const types::ObjectPath& path) { auto object = std::shared_ptr(new Object(shared_from_this(), path)); connection->register_object_for_path(path, object); return object; } } } dbus-cpp-5.0.3/src/core/dbus/service_watcher.cpp000066400000000000000000000057771407013304700216100ustar00rootroot00000000000000/* * Copyright © 2014 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Pete Woods */ #include #include #include #include #include namespace core { namespace dbus { namespace { struct NameOwnerChanged { static const std::string& name() { static const std::string s { "NameOwnerChanged" }; return s; } typedef DBus Interface; typedef std::tuple ArgumentType; }; } struct dbus::ServiceWatcher::Private { void signal_handler(const NameOwnerChanged::ArgumentType& args) { const std::string& old_owner(std::get<1>(args)); const std::string& new_owner(std::get<2>(args)); if (old_owner.empty() && !new_owner.empty()) { service_registered(); } if (!old_owner.empty() && new_owner.empty()) { service_unregistered(); } owner_changed(old_owner, new_owner); } core::Signal owner_changed; core::Signal service_registered; core::Signal service_unregistered; std::shared_ptr object; std::shared_ptr< core::dbus::Signal> signal; }; dbus::ServiceWatcher::ServiceWatcher(std::shared_ptr object, const std::string& name, DBus::WatchMode watch_mode) : d(new Private()) { d->object = object; MatchRule::MatchArgs match_args{ { 0, name } }; switch (watch_mode) { case DBus::WatchMode::owner_change: break; case DBus::WatchMode::registration: match_args.push_back({ 1, std::string() }); break; case DBus::WatchMode::unregistration: match_args.push_back({ 2, std::string() }); break; } d->signal = d->object->get_signal(); d->signal->connect_with_match_args( std::bind(&Private::signal_handler, d, std::placeholders::_1), match_args); } const core::Signal& dbus::ServiceWatcher::owner_changed() const { return d->owner_changed; } const core::Signal& dbus::ServiceWatcher::service_registered() const { return d->service_registered; } const core::Signal& dbus::ServiceWatcher::service_unregistered() const { return d->service_unregistered; } } } dbus-cpp-5.0.3/src/core/dbus/types/000077500000000000000000000000001407013304700170535ustar00rootroot00000000000000dbus-cpp-5.0.3/src/core/dbus/types/object_path.cpp000066400000000000000000000042201407013304700220370ustar00rootroot00000000000000/* * Copyright © 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Thomas Voß */ #include #include #include #include namespace core { namespace dbus { namespace types { const std::string& ObjectPath::root() { static const std::string s{"/"}; return s; } // Specifying a default argument here causes valgrind to report a "possible lost". // However, this is spurious and // http://stackoverflow.com/questions/10750299/if-i-specify-a-default-value-for-an-argument-of-type-stdstring-in-c-cou // gives some insight. ObjectPath::ObjectPath(const std::string& path) : path(path) { Error e; if (!dbus_validate_path(path.c_str(), std::addressof(e.raw()))) throw ObjectPath::Errors::InvalidObjectPathStringRepresentation{path}; } bool ObjectPath::empty() const { return path.empty(); } const std::string& ObjectPath::as_string() const { return path; } bool ObjectPath::operator<(const ObjectPath& rhs) const { return path < rhs.path; } bool ObjectPath::operator==(const ObjectPath& rhs) const { return path == rhs.path; } bool ObjectPath::operator!=(const ObjectPath& rhs) const { return path != rhs.path; } std::ostream& operator<<(std::ostream& out, const ObjectPath& path) { out << path.as_string() << std::endl; return out; } } } } size_t std::hash::operator()( const core::dbus::types::ObjectPath& p) const { static const std::hash h {}; return h(p.as_string()); } dbus-cpp-5.0.3/symbols.map000066400000000000000000000004111407013304700154160ustar00rootroot00000000000000{ global: extern "C++" { core::dbus::*; typeinfo?for?core::dbus::*; typeinfo?name?for?core::dbus::*; VTT?for?core::dbus::*; virtual?thunk?to?core::dbus::*; vtable?for?core::dbus::*; std::hash*; }; local: extern "C++" { *; }; };dbus-cpp-5.0.3/tests/000077500000000000000000000000001407013304700143755ustar00rootroot00000000000000dbus-cpp-5.0.3/tests/CMakeLists.txt000066400000000000000000000135141407013304700171410ustar00rootroot00000000000000# Copyright © 2013 Canonical Ltd. # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License version 3 as # published by the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # # Authored by: Thomas Voss # Build with system gmock and embedded gtest find_package(GMock) find_package(Threads) add_definitions(-DCORE_DBUS_ENABLE_GOOGLE_TEST_FIXTURE) configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/test_data.h.in ${CMAKE_CURRENT_BINARY_DIR}/test_data.h @ONLY) include_directories( ${CMAKE_CURRENT_BINARY_DIR} ) include_directories( ${DBUS_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS} ${GTEST_INCLUDE_DIRS} ${PROCESS_CPP_INCLUDE_DIRS} ) add_executable( async_execution_load_test async_execution_load_test.cpp ) add_executable( bus_test bus_test.cpp ) add_executable( cache_test cache_test.cpp ) add_executable( dbus_test dbus_test.cpp ) add_executable( codec_test codec_test.cpp ) add_executable( compiler_test compiler_test.cpp ) add_executable( executor_test executor_test.cpp ) add_executable( stl_codec_test stl_codec_test.cpp ) add_executable( message_test message_test.cpp ) add_executable( match_rule_test match_rule_test.cpp ) add_executable( message_router_test message_router_test.cpp ) add_executable( service_test service_test.cpp ) add_executable( service_watcher_test service_watcher_test.cpp ) add_executable( types_test types_test.cpp ) add_executable( signal_delivery_test signal_delivery_test.cpp ) target_link_libraries( async_execution_load_test dbus-cpp dbus-cppc-helper ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES} ${DBUS_LIBRARIES} ${GMOCK_LIBRARIES} ${GTEST_BOTH_LIBRARIES} ${PROCESS_CPP_LIBRARIES} ) target_link_libraries( bus_test dbus-cpp dbus-cppc-helper ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES} ${DBUS_LIBRARIES} ${GMOCK_LIBRARIES} ${GTEST_BOTH_LIBRARIES} ${PROCESS_CPP_LIBRARIES} ) target_link_libraries( cache_test dbus-cpp ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES} ${DBUS_LIBRARIES} ${GMOCK_LIBRARIES} ${GTEST_BOTH_LIBRARIES} ${PROCESS_CPP_LIBRARIES} ) target_link_libraries( dbus_test dbus-cpp dbus-cppc-helper ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES} ${DBUS_LIBRARIES} ${GMOCK_LIBRARIES} ${GTEST_BOTH_LIBRARIES} ) target_link_libraries( executor_test dbus-cpp dbus-cppc-helper ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES} ${DBUS_LIBRARIES} ${GMOCK_LIBRARIES} ${GTEST_BOTH_LIBRARIES} ) target_link_libraries( codec_test dbus-cpp dbus-cppc-helper ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES} ${DBUS_LIBRARIES} ${GMOCK_LIBRARIES} ${GTEST_BOTH_LIBRARIES} ) target_link_libraries( compiler_test dbus-cpp dbus-cppc-helper ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES} ${DBUS_LIBRARIES} ${LIBXML2_LIBRARIES} ${GMOCK_LIBRARY} ${GMOCK_LIBRARIES} ${GTEST_BOTH_LIBRARIES} ) target_link_libraries( stl_codec_test dbus-cpp dbus-cppc-helper ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES} ${DBUS_LIBRARIES} ${GMOCK_LIBRARIES} ${GTEST_BOTH_LIBRARIES} ) target_link_libraries( message_test dbus-cpp dbus-cppc-helper ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES} ${DBUS_LIBRARIES} ${GMOCK_LIBRARIES} ${GTEST_BOTH_LIBRARIES} ) target_link_libraries( match_rule_test dbus-cpp dbus-cppc-helper ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES} ${DBUS_LIBRARIES} ${GMOCK_LIBRARIES} ${GTEST_BOTH_LIBRARIES} ) target_link_libraries( message_router_test dbus-cpp dbus-cppc-helper ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES} ${DBUS_LIBRARIES} ${GMOCK_LIBRARIES} ${GTEST_BOTH_LIBRARIES} ) target_link_libraries( service_test dbus-cpp dbus-cppc-helper ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES} ${DBUS_LIBRARIES} ${GMOCK_LIBRARIES} ${GTEST_BOTH_LIBRARIES} ) target_link_libraries( service_watcher_test dbus-cpp dbus-cppc-helper ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES} ${DBUS_LIBRARIES} ${GMOCK_LIBRARIES} ${GTEST_BOTH_LIBRARIES} ) target_link_libraries( types_test dbus-cpp ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES} ${DBUS_LIBRARIES} ${GMOCK_LIBRARIES} ${GTEST_BOTH_LIBRARIES} ) target_link_libraries( signal_delivery_test dbus-cpp ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES} ${DBUS_LIBRARIES} ${GMOCK_LIBRARIES} ${GTEST_BOTH_LIBRARIES} ) add_test(async_execution_load_test ${CMAKE_CURRENT_BINARY_DIR}/async_execution_load_test) add_test(bus_test ${CMAKE_CURRENT_BINARY_DIR}/bus_test) add_test(cache_test ${CMAKE_CURRENT_BINARY_DIR}/cache_test) add_test(dbus_test ${CMAKE_CURRENT_BINARY_DIR}/dbus_test) add_test(executor_test ${CMAKE_CURRENT_BINARY_DIR}/executor_test) add_test(codec_test ${CMAKE_CURRENT_BINARY_DIR}/codec_test) add_test(compiler_test ${CMAKE_CURRENT_BINARY_DIR}/compiler_test) add_test(stl_codec_test ${CMAKE_CURRENT_BINARY_DIR}/stl_codec_test) add_test(types_test ${CMAKE_CURRENT_BINARY_DIR}/types_test) add_test(message_test ${CMAKE_CURRENT_BINARY_DIR}/message_test) add_test(match_rule_test ${CMAKE_CURRENT_BINARY_DIR}/match_rule_test) add_test(message_router_test ${CMAKE_CURRENT_BINARY_DIR}/message_router_test) add_test(service_test ${CMAKE_CURRENT_BINARY_DIR}/service_test) add_test(service_watcher_test ${CMAKE_CURRENT_BINARY_DIR}/service_watcher_test) add_test(signal_delivery_test ${CMAKE_CURRENT_BINARY_DIR}/signal_delivery_test) dbus-cpp-5.0.3/tests/async_execution_load_test.cpp000066400000000000000000000106161407013304700223430ustar00rootroot00000000000000/* * Copyright © 2014 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Thomas Voß */ #include #include #include #include #include #include #include #include #include #include "test_data.h" namespace { // Our fixture for starting up private system- and session-bus instances. struct AsyncExecutionLoadTest : public core::dbus::testing::Fixture { }; auto session_bus_config_file = core::dbus::testing::Fixture::default_session_bus_config_file() = core::testing::session_bus_configuration_file(); auto system_bus_config_file = core::dbus::testing::Fixture::default_system_bus_config_file() = core::testing::system_bus_configuration_file(); struct DBus { static const std::string& name() { static const std::string s{DBUS_SERVICE_DBUS}; return s; } DBUS_CPP_METHOD_WITH_TIMEOUT_DEF(ListNames, DBus, 25000) }; struct CountingEventCollector { CountingEventCollector(int expected) : expected{expected}, counter{0} { } void update() { if (++counter == expected) wait_condition.notify_all(); } ::testing::AssertionResult wait_for(const std::chrono::milliseconds& ms) { std::unique_lock ul(guard); auto result = wait_condition.wait_for(ul, ms, [this]() { return counter == expected; }); if (result) return ::testing::AssertionSuccess(); return ::testing::AssertionFailure() << "Current count of " << counter << " does not match " << expected; } int expected; std::atomic counter; std::mutex guard; std::condition_variable wait_condition; }; void invoke_list_names_n_times_and_update_event_collector( // The object referring to the bus daemon const core::dbus::Object::Ptr& dbus, // Number of iterations std::size_t n, // The event collector instance that should be updated const std::shared_ptr& ec) { for (unsigned int i = 0; i < n; i++) { dbus->invoke_method_asynchronously_with_callback>([ec](const core::dbus::Result>& vs) { if (not vs.is_error()) ec->update(); }); } } } TEST_F(AsyncExecutionLoadTest, RepeatedlyInvokingAnAsyncFunctionWorks) { using namespace ::testing; auto bus = session_bus(); bus->install_executor(core::dbus::asio::make_executor(bus)); std::thread worker{[bus]() { bus->run(); }}; auto service = core::dbus::Service::use_service(bus, DBus::name()); auto dbus = service->object_for_path(core::dbus::types::ObjectPath{DBUS_PATH_DBUS}); auto ec = std::make_shared(500); std::thread t1{[dbus, ec]() {invoke_list_names_n_times_and_update_event_collector(dbus, 100, ec);}}; std::thread t2{[dbus, ec]() {invoke_list_names_n_times_and_update_event_collector(dbus, 100, ec);}}; std::thread t3{[dbus, ec]() {invoke_list_names_n_times_and_update_event_collector(dbus, 100, ec);}}; std::thread t4{[dbus, ec]() {invoke_list_names_n_times_and_update_event_collector(dbus, 100, ec);}}; std::thread t5{[dbus, ec]() {invoke_list_names_n_times_and_update_event_collector(dbus, 100, ec);}}; EXPECT_TRUE(ec->wait_for(std::chrono::minutes{5})); bus->stop(); if (t1.joinable()) t1.join(); if (t2.joinable()) t2.join(); if (t3.joinable()) t3.join(); if (t4.joinable()) t4.join(); if (t5.joinable()) t5.join(); if (worker.joinable()) worker.join(); } dbus-cpp-5.0.3/tests/bus_test.cpp000066400000000000000000000125331407013304700167350ustar00rootroot00000000000000/* * Copyright © 2013 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Thomas Voß */ #include #include #include #include #include #include #include #include #include #include "test_data.h" #include #include #include #include #include namespace dbus = core::dbus; namespace { struct Bus : public core::dbus::testing::Fixture { }; auto session_bus_config_file = core::dbus::testing::Fixture::default_session_bus_config_file() = core::testing::session_bus_configuration_file(); auto system_bus_config_file = core::dbus::testing::Fixture::default_system_bus_config_file() = core::testing::system_bus_configuration_file(); } TEST_F(Bus, BlockingMethodInvocationSucceedsForValidMessage) { static const char* expected_signature = DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_STRING_AS_STRING; auto msg = core::dbus::Message::make_method_call( dbus::DBus::name(), dbus::DBus::path(), dbus::DBus::name(), "ListNames"); auto bus = session_bus(); const std::chrono::milliseconds timeout = std::chrono::seconds(10); std::shared_ptr reply = nullptr; EXPECT_NO_THROW( reply = bus->send_with_reply_and_block_for_at_most( msg, timeout)); EXPECT_NE(nullptr, reply.get()); EXPECT_EQ(core::dbus::Message::Type::method_return, reply->type()); EXPECT_EQ(expected_signature, reply->signature()); } TEST_F(Bus, NonBlockingMethodInvocationSucceedsForValidMessage) { auto msg = core::dbus::Message::make_method_call( dbus::DBus::name(), dbus::DBus::path(), dbus::DBus::name(), "ListNames"); auto bus = session_bus(); bus->install_executor(dbus::asio::make_executor(bus)); std::thread t{[bus](){bus->run();}}; const std::chrono::milliseconds timeout = std::chrono::seconds(10); auto call = bus->send_with_reply_and_timeout(msg, timeout); auto promise = std::make_shared>>(); auto future = promise->get_future(); call->then([promise](const core::dbus::Message::Ptr& reply) { std::vector result; reply->reader() >> result; promise->set_value(result); }); EXPECT_TRUE(future.get().size() > 0); bus->stop(); if (t.joinable()) t.join(); } TEST_F(Bus, HasOwnerForNameReturnsTrueForExistingName) { auto bus = session_bus(); EXPECT_TRUE(bus->has_owner_for_name(dbus::DBus::name())); } TEST_F(Bus, HasOwnerForNameReturnsFalseForNonExistingName) { auto bus = session_bus(); static const std::string non_existing_name = "com.canonical.does.not.exist"; EXPECT_FALSE(bus->has_owner_for_name(non_existing_name)); } TEST_F(Bus, AddingAndRemovingAValidMatchRuleDoesNotThrow) { auto bus = session_bus(); static const dbus::MatchRule valid_match_rule = dbus::MatchRule().type(dbus::Message::Type::signal); struct ScopedMatch { ScopedMatch(core::dbus::Bus::Ptr bus, const dbus::MatchRule& match_rule) : bus(bus), match_rule(match_rule) { EXPECT_NO_THROW(bus->add_match(match_rule);); } ~ScopedMatch() { EXPECT_NO_THROW(bus->remove_match(match_rule);); } core::dbus::Bus::Ptr bus; dbus::MatchRule match_rule; }; ScopedMatch match(bus, valid_match_rule); } namespace { dbus::Message::Ptr a_signal_message(const std::string& path, const std::string& interface, const std::string& name) { return dbus::Message::make_signal( path, interface, name); } } TEST_F(Bus, InstallingARouteForSignalsResultsInTheRouteBeingInvoked) { const std::string path{"/org/gnome/SettingsDaemon/Power"}; const core::dbus::types::ObjectPath to_route_for(path); bool invoked {false}; auto bus = session_bus(); bus->install_executor(core::dbus::asio::make_executor(bus)); bus->access_signal_router().install_route(to_route_for,[&](const dbus::Message::Ptr&) { invoked = true; bus->stop(); }); auto signal = a_signal_message( to_route_for.as_string(), "org.gnome.SettingsDaemon.Power", "LaLeLu"); bus->access_signal_router()(signal); } dbus-cpp-5.0.3/tests/cache_test.cpp000066400000000000000000000044351407013304700172110ustar00rootroot00000000000000/* * Copyright © 2013 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Thomas Voß */ #include #include namespace { struct Dummy { ~Dummy() { signal_about_to_be_destroyed(); } const core::Signal& about_to_be_destroyed() const { return signal_about_to_be_destroyed; } core::Signal signal_about_to_be_destroyed; }; } TEST(Cache, an_inserted_object_is_retrievable) { const std::string key{"key"}; core::dbus::ThreadSafeLifetimeConstrainedCache cache; auto object = std::make_shared(); EXPECT_TRUE(cache.insert_value_for_key(key, object)); EXPECT_TRUE(cache.has_value_for_key(key)); EXPECT_EQ(object, cache.retrieve_value_for_key(key)); } TEST(Cache, a_removed_object_is_not_retrievable) { const std::string key{"key"}; core::dbus::ThreadSafeLifetimeConstrainedCache cache; auto object = std::make_shared(); EXPECT_TRUE(cache.insert_value_for_key(key, object)); EXPECT_TRUE(cache.has_value_for_key(key)); cache.remove_value_for_key(key); EXPECT_FALSE(cache.has_value_for_key(key)); EXPECT_EQ(std::shared_ptr(), cache.retrieve_value_for_key(key)); } TEST(Cache, an_object_going_out_of_scope_is_automatically_removed_from_the_cache) { const std::string key{"key"}; core::dbus::ThreadSafeLifetimeConstrainedCache cache; { auto object = std::make_shared(); EXPECT_TRUE(cache.insert_value_for_key(key, object)); EXPECT_TRUE(cache.has_value_for_key(key)); } EXPECT_FALSE(cache.has_value_for_key(key)); } dbus-cpp-5.0.3/tests/codec_test.cpp000066400000000000000000000442541407013304700172260ustar00rootroot00000000000000/* * Copyright © 2013 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Thomas Voß */ #include #include #include #include #include #include #include #include #include #include // STL includes #include #include #include #include #include #include #include namespace dbus = core::dbus; TEST(Codec, BasicTypesMatchSizeAndAlignOfDBusTypes) { ::testing::StaticAssertTypeEq::Type>(); ::testing::StaticAssertTypeEq::Type>(); ::testing::StaticAssertTypeEq::Type>(); ::testing::StaticAssertTypeEq::Type>(); ::testing::StaticAssertTypeEq::Type>(); ::testing::StaticAssertTypeEq::Type>(); ::testing::StaticAssertTypeEq::Type>(); ::testing::StaticAssertTypeEq::Type>(); ::testing::StaticAssertTypeEq::Type>(); ASSERT_EQ(sizeof(dbus_bool_t), sizeof(typename core::dbus::helper::DBusTypeMapper::Type)); ASSERT_EQ(sizeof(unsigned char), sizeof(typename core::dbus::helper::DBusTypeMapper::Type)); ASSERT_EQ(sizeof(dbus_int16_t), sizeof(typename core::dbus::helper::DBusTypeMapper::Type)); ASSERT_EQ(sizeof(dbus_uint16_t), sizeof(typename core::dbus::helper::DBusTypeMapper::Type)); ASSERT_EQ(sizeof(dbus_int32_t), sizeof(typename core::dbus::helper::DBusTypeMapper::Type)); ASSERT_EQ(sizeof(dbus_uint32_t), sizeof(typename core::dbus::helper::DBusTypeMapper::Type)); ASSERT_EQ(sizeof(dbus_int64_t), sizeof(typename core::dbus::helper::DBusTypeMapper::Type)); ASSERT_EQ(sizeof(dbus_uint64_t), sizeof(typename core::dbus::helper::DBusTypeMapper::Type)); ASSERT_EQ(sizeof(double), sizeof(typename core::dbus::helper::DBusTypeMapper::Type)); ASSERT_EQ(alignof(dbus_bool_t), alignof(typename core::dbus::helper::DBusTypeMapper::Type)); ASSERT_EQ(alignof(unsigned char), alignof(typename core::dbus::helper::DBusTypeMapper::Type)); ASSERT_EQ(alignof(dbus_int16_t), alignof(typename core::dbus::helper::DBusTypeMapper::Type)); ASSERT_EQ(alignof(dbus_uint16_t), alignof(typename core::dbus::helper::DBusTypeMapper::Type)); ASSERT_EQ(alignof(dbus_int32_t), alignof(typename core::dbus::helper::DBusTypeMapper::Type)); ASSERT_EQ(alignof(dbus_uint32_t), alignof(typename core::dbus::helper::DBusTypeMapper::Type)); ASSERT_EQ(alignof(dbus_int64_t), alignof(typename core::dbus::helper::DBusTypeMapper::Type)); ASSERT_EQ(alignof(dbus_uint64_t), alignof(typename core::dbus::helper::DBusTypeMapper::Type)); ASSERT_EQ(alignof(double), alignof(typename core::dbus::helper::DBusTypeMapper::Type)); } TEST(Codec, BasicTypesMapToCorrectDBusTypes) { ASSERT_EQ(core::dbus::ArgumentType::boolean, core::dbus::helper::TypeMapper::type_value()); ASSERT_EQ(core::dbus::ArgumentType::byte, core::dbus::helper::TypeMapper::type_value()); ASSERT_EQ(core::dbus::ArgumentType::int16, core::dbus::helper::TypeMapper::type_value()); ASSERT_EQ(core::dbus::ArgumentType::uint16, core::dbus::helper::TypeMapper::type_value()); ASSERT_EQ(core::dbus::ArgumentType::int32, core::dbus::helper::TypeMapper::type_value()); ASSERT_EQ(core::dbus::ArgumentType::uint32, core::dbus::helper::TypeMapper::type_value()); ASSERT_EQ(core::dbus::ArgumentType::floating_point, core::dbus::helper::TypeMapper::type_value()); ASSERT_EQ(core::dbus::ArgumentType::floating_point, core::dbus::helper::TypeMapper::type_value()); } TEST(Codec, StlCompoundTypesMapToCorrectDBusTypes) { ASSERT_EQ(core::dbus::ArgumentType::string, core::dbus::helper::TypeMapper::type_value()); ASSERT_EQ(core::dbus::ArgumentType::array, core::dbus::helper::TypeMapper>::type_value()); ASSERT_EQ(core::dbus::ArgumentType::array, core::dbus::helper::TypeMapper>::type_value()); typedef std::map Map; // Need to circumvent a macro restriction with this. ASSERT_EQ(core::dbus::ArgumentType::array, core::dbus::helper::TypeMapper< Map >::type_value()); typedef std::pair Pair; // Need to circumvent a macro restriction with this. ASSERT_EQ(core::dbus::ArgumentType::dictionary_entry, core::dbus::helper::TypeMapper::type_value()); } TEST(Codec, BasicTypeSignaturesMapToCorrectDBusSignatures) { ASSERT_STREQ(DBUS_TYPE_BOOLEAN_AS_STRING, core::dbus::helper::TypeMapper::signature().c_str()); ASSERT_STREQ(DBUS_TYPE_BYTE_AS_STRING, core::dbus::helper::TypeMapper::signature().c_str()); ASSERT_STREQ(DBUS_TYPE_INT16_AS_STRING, core::dbus::helper::TypeMapper::signature().c_str()); ASSERT_STREQ(DBUS_TYPE_UINT16_AS_STRING, core::dbus::helper::TypeMapper::signature().c_str()); ASSERT_STREQ(DBUS_TYPE_INT32_AS_STRING, core::dbus::helper::TypeMapper::signature().c_str()); ASSERT_STREQ(DBUS_TYPE_UINT32_AS_STRING, core::dbus::helper::TypeMapper::signature().c_str()); ASSERT_STREQ(DBUS_TYPE_DOUBLE_AS_STRING, core::dbus::helper::TypeMapper::signature().c_str()); ASSERT_STREQ(DBUS_TYPE_DOUBLE_AS_STRING, core::dbus::helper::TypeMapper::signature().c_str()); } TEST(Codec, CompoundTypeSignaturesMapToCorrectDBusSignatures) { ASSERT_STREQ( DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_STRING_AS_STRING, core::dbus::helper::TypeMapper>::signature().c_str()); ASSERT_STREQ( DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_STRING_AS_STRING, core::dbus::helper::TypeMapper>::signature().c_str()); typedef std::map Map; ASSERT_STREQ( DBUS_TYPE_ARRAY_AS_STRING DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_STRING_AS_STRING DBUS_DICT_ENTRY_END_CHAR_AS_STRING, core::dbus::helper::TypeMapper::signature().c_str()); } namespace { const bool default_bool { true }; const int8_t default_int8 { 8 }; const int16_t default_int16 { -16 }; const uint16_t default_uint16 { 16 }; const int32_t default_int32 { -32 }; const uint32_t default_uint32 { 32 }; const int64_t default_int64 { -64 }; const uint64_t default_uint64 { 64 }; const float default_float { std::numeric_limits::min() }; const double default_double { std::numeric_limits::min() }; core::dbus::Message::Ptr a_method_call() { return core::dbus::Message::make_method_call( dbus::DBus::name(), dbus::DBus::path(), dbus::DBus::interface(), "ListNames"); } std::tuple< core::dbus::Message::Ptr, std::function > a_method_call_with_basic_types_as_arguments() { auto msg = a_method_call(); auto writer = msg->writer(); EXPECT_NO_THROW(core::dbus::Codec::encode_argument(writer, default_bool);); EXPECT_NO_THROW(core::dbus::Codec::encode_argument(writer, default_int8);); EXPECT_NO_THROW(core::dbus::Codec::encode_argument(writer, default_int16);); EXPECT_NO_THROW(core::dbus::Codec::encode_argument(writer, default_uint16);); EXPECT_NO_THROW(core::dbus::Codec::encode_argument(writer, default_int32);); EXPECT_NO_THROW(core::dbus::Codec::encode_argument(writer, default_uint32);); EXPECT_NO_THROW(core::dbus::Codec::encode_argument(writer, default_int64);); EXPECT_NO_THROW(core::dbus::Codec::encode_argument(writer, default_uint64);); EXPECT_NO_THROW(core::dbus::Codec::encode_argument(writer, default_float);); EXPECT_NO_THROW(core::dbus::Codec::encode_argument(writer, default_double);); std::function signature = []() { return DBUS_TYPE_BOOLEAN_AS_STRING DBUS_TYPE_BYTE_AS_STRING DBUS_TYPE_INT16_AS_STRING DBUS_TYPE_UINT16_AS_STRING DBUS_TYPE_INT32_AS_STRING DBUS_TYPE_UINT32_AS_STRING DBUS_TYPE_INT64_AS_STRING DBUS_TYPE_UINT64_AS_STRING DBUS_TYPE_DOUBLE_AS_STRING DBUS_TYPE_DOUBLE_AS_STRING; }; return std::make_tuple(msg, signature); } template ::testing::AssertionResult check_value(core::dbus::Message::Reader& reader, const T& expected_value) { return expected_value == core::dbus::decode_argument(reader) ? ::testing::AssertionSuccess() : ::testing::AssertionFailure(); } } TEST(Codec, EncodingOfBasicTypeYieldsCorrectMessageSignatures) { auto tuple = a_method_call_with_basic_types_as_arguments(); EXPECT_EQ(std::get<0>(tuple)->signature(), std::get<1>(tuple)()); } TEST(Codec, DecodingAMessageOfBasicTypesYieldsCorrectValues) { auto tuple = a_method_call_with_basic_types_as_arguments(); auto reader = std::get<0>(tuple)->reader(); EXPECT_TRUE(check_value(reader, default_bool)); EXPECT_TRUE(check_value(reader, default_int8)); EXPECT_TRUE(check_value(reader, default_int16)); EXPECT_TRUE(check_value(reader, default_uint16)); EXPECT_TRUE(check_value(reader, default_int32)); EXPECT_TRUE(check_value(reader, default_uint32)); EXPECT_TRUE(check_value(reader, default_int64)); EXPECT_TRUE(check_value(reader, default_uint64)); EXPECT_TRUE(check_value(reader, default_float)); EXPECT_TRUE(check_value(reader, default_double)); } TEST(ObjectPath, TypeMapperSpecializationReturnsCorrectValues) { namespace dbus = core::dbus; ASSERT_EQ(dbus::ArgumentType::object_path, dbus::helper::TypeMapper::type_value()); ASSERT_TRUE(dbus::helper::TypeMapper::is_basic_type()); ASSERT_TRUE(dbus::helper::TypeMapper::requires_signature()); ASSERT_STREQ(DBUS_TYPE_OBJECT_PATH_AS_STRING, dbus::helper::TypeMapper::signature().c_str()); } TEST(ObjectPath, EncodingAndDecodingWorksCorrectly) { namespace dbus = core::dbus; const dbus::types::ObjectPath expected_value { dbus::DBus::path() }; auto msg = a_method_call(); auto writer = msg->writer(); ASSERT_NO_THROW(dbus::encode_argument(writer, expected_value);); auto reader = msg->reader(); ASSERT_EQ(expected_value, dbus::decode_argument(reader)); } TEST(Unixfd, TypeMapperSpecializationReturnsCorrectValues) { namespace dbus = core::dbus; ASSERT_EQ(dbus::ArgumentType::unix_fd, dbus::helper::TypeMapper::type_value()); ASSERT_TRUE(dbus::helper::TypeMapper::is_basic_type()); ASSERT_TRUE(dbus::helper::TypeMapper::requires_signature()); ASSERT_STREQ(DBUS_TYPE_UNIX_FD_AS_STRING, dbus::helper::TypeMapper::signature().c_str()); } #include TEST(UnixFd, EncodingAndDecodingWorksCorrectly) { namespace dbus = core::dbus; const dbus::types::UnixFd expected_value { eventfd(0,0) }; auto msg = a_method_call(); auto writer = msg->writer(); ASSERT_NO_THROW(dbus::encode_argument(writer, expected_value);); auto reader = msg->reader(); auto fd = dbus::decode_argument(reader); // We cannot just check for equality of fd and expected_value as libdbus duplicates the fd. static const uint64_t magic_value { 42 }; EXPECT_TRUE(write(expected_value.to_int(), std::addressof(magic_value), sizeof(magic_value)) >= 0); uint64_t result {0}; EXPECT_TRUE(read(fd.to_int(), std::addressof(result), sizeof(result)) >= 0); ASSERT_EQ(magic_value, result); } TEST(Variant, TypeMapperSpecializationReturnsCorrectValues) { namespace dbus = core::dbus; ASSERT_EQ(dbus::ArgumentType::variant, dbus::helper::TypeMapper::type_value()); ASSERT_TRUE(dbus::helper::TypeMapper::is_basic_type()); ASSERT_TRUE(dbus::helper::TypeMapper::requires_signature()); ASSERT_STREQ(DBUS_TYPE_VARIANT_AS_STRING, dbus::helper::TypeMapper::signature().c_str()); } TEST(Variant, EncodingAndDecodingWorksCorrectly) { namespace dbus = core::dbus; typedef dbus::types::Struct> Struct; const Struct expected_value = Struct{std::make_tuple(42., 42., 56)}; auto msg = a_method_call(); { auto writer = msg->writer(); ASSERT_NO_THROW(dbus::encode_argument(writer, dbus::types::Variant::encode(expected_value));); } auto reader = msg->reader(); Struct my_struct; auto variant = std::move(dbus::types::Variant::decode(my_struct)); dbus::decode_argument( reader, variant); ASSERT_EQ(expected_value, my_struct); } TEST(Signature, TypeMapperSpecializationReturnsCorrectValues) { namespace dbus = core::dbus; ASSERT_EQ(dbus::ArgumentType::signature, dbus::helper::TypeMapper::type_value()); ASSERT_TRUE(dbus::helper::TypeMapper::is_basic_type()); ASSERT_TRUE(dbus::helper::TypeMapper::requires_signature()); ASSERT_STREQ(DBUS_TYPE_SIGNATURE_AS_STRING, dbus::helper::TypeMapper::signature().c_str()); } TEST(Signature, EncodingAndDecodingWorksCorrectly) { namespace dbus = core::dbus; const dbus::types::Signature expected_value { "(ii)" }; auto msg = a_method_call(); auto writer = msg->writer(); { ASSERT_NO_THROW(dbus::encode_argument(writer, expected_value);); } auto reader = msg->reader(); auto signature = dbus::decode_argument(reader); ASSERT_EQ(expected_value, signature); } TEST(Properties, DictionaryMappingToVariantsIsEncodedCorrectly) { namespace dbus = core::dbus; const std::string key{"key"}; auto msg = a_method_call(); { auto writer = msg->writer(); auto array = writer.open_array(dbus::types::Signature{"{sv}"}); for(unsigned int i = 0; i < 5; i++) { auto entry = array.open_dict_entry(); { entry.push_stringn(key.c_str(), key.size()); auto variant = entry.open_variant(dbus::types::Signature{dbus::helper::TypeMapper::signature()}); { variant.push_uint32(i); } entry.close_variant(std::move(variant)); } array.close_dict_entry(std::move(entry)); } writer.close_array(std::move(array)); } unsigned int counter = 0; auto reader = msg->reader(); auto array = reader.pop_array(); while (array.type() != dbus::ArgumentType::invalid) { auto entry = array.pop_dict_entry(); { EXPECT_EQ(key, std::string{entry.pop_string()}); auto variant = entry.pop_variant(); { EXPECT_EQ(counter, variant.pop_uint32()); } } counter++; } unsigned int expected_value{5}; EXPECT_EQ(expected_value, counter); } TEST(Properties, DictionaryMappingToVariantsIsEncodedCorrectlyWithMap) { namespace dbus = core::dbus; auto msg = a_method_call(); { std::map map; map["key1"] = dbus::types::Variant::encode(1); map["key2"] = dbus::types::Variant::encode(2); map["key3"] = dbus::types::Variant::encode(3); map["key4"] = dbus::types::Variant::encode(4); map["key5"] = dbus::types::Variant::encode(5); msg->writer() << map; } auto reader = msg->reader(); std::map map; reader >> map; unsigned int expected_value{5}; EXPECT_EQ(expected_value, map.size()); EXPECT_EQ(std::uint32_t(1), map.at("key1").as()); EXPECT_EQ(std::uint32_t(2), map.at("key2").as()); EXPECT_EQ(std::uint32_t(3), map.at("key3").as()); EXPECT_EQ(std::uint32_t(4), map.at("key4").as()); EXPECT_EQ(std::uint32_t(5), map.at("key5").as()); } dbus-cpp-5.0.3/tests/compiler_test.cpp000066400000000000000000000272421407013304700177610ustar00rootroot00000000000000/* * Copyright © 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Thomas Voß */ #include #include #include #include #include #include #include // local includes to access testing data #include "test_data.h" namespace dbus = core::dbus; namespace { struct ParserInspector { MOCK_METHOD1(on_node, void(const dbus::IntrospectionParser::Node&)); MOCK_METHOD0(on_node_done, void()); MOCK_METHOD1(on_interface, void(const dbus::IntrospectionParser::Interface&)); MOCK_METHOD0(on_interface_done, void()); MOCK_METHOD1(on_method, void(const dbus::IntrospectionParser::Method&)); MOCK_METHOD0(on_method_done, void()); MOCK_METHOD1(on_property, void(const dbus::IntrospectionParser::Property&)); MOCK_METHOD1(on_signal, void(const dbus::IntrospectionParser::Signal&)); MOCK_METHOD0(on_signal_done, void()); MOCK_METHOD1(on_argument, void(const dbus::IntrospectionParser::Argument&)); MOCK_METHOD0(on_argument_done, void()); MOCK_METHOD1(on_annotation, void(const dbus::IntrospectionParser::Annotation&)); MOCK_METHOD0(on_annotation_done, void()); }; struct MockGenerator : public dbus::Generator { MOCK_METHOD3(invoke_for_model_with_configuration, bool( const std::shared_ptr&, std::istream&, const dbus::GeneratorConfiguration&)); }; void ensure_test_introspection_file(const std::string& fn) { std::ofstream out(fn.c_str()); out << "" << std::endl << "" << std::endl << " " << std::endl << " " << std::endl << " " << std::endl << " " << std::endl << " " << std::endl << " " << std::endl << " " << std::endl << " " << std::endl << " " << std::endl << " " << std::endl << " " << std::endl << " " << std::endl << " " << std::endl << " " << std::endl << " " << std::endl << " " << std::endl << " " << std::endl << " " << std::endl << " " << std::endl << " " << std::endl << " " << std::endl << " " << std::endl; } } TEST(IntrospectionParser, invoking_parser_reports_elements_correctly) { using namespace ::testing; const std::string tmp_fn(__PRETTY_FUNCTION__); std::remove(tmp_fn.c_str()); ensure_test_introspection_file(tmp_fn); dbus::IntrospectionParser parser; NiceMock inspector; parser.on_node(std::bind(&ParserInspector::on_node, &inspector, std::placeholders::_1)); parser.on_node_done(std::bind(&ParserInspector::on_node_done, &inspector)); parser.on_interface(std::bind(&ParserInspector::on_interface, &inspector, std::placeholders::_1)); parser.on_interface_done(std::bind(&ParserInspector::on_interface_done, &inspector)); parser.on_method(std::bind(&ParserInspector::on_method, &inspector, std::placeholders::_1)); parser.on_method_done(std::bind(&ParserInspector::on_method_done, &inspector)); parser.on_property(std::bind(&ParserInspector::on_property, &inspector, std::placeholders::_1)); parser.on_signal(std::bind(&ParserInspector::on_signal, &inspector, std::placeholders::_1)); parser.on_signal_done(std::bind(&ParserInspector::on_signal_done, &inspector)); parser.on_argument(std::bind(&ParserInspector::on_argument, &inspector, std::placeholders::_1)); parser.on_argument_done(std::bind(&ParserInspector::on_argument_done, &inspector)); parser.on_annotation(std::bind(&ParserInspector::on_annotation, &inspector, std::placeholders::_1)); parser.on_annotation_done(std::bind(&ParserInspector::on_annotation_done, &inspector)); EXPECT_CALL(inspector, on_node(_)).Times(Exactly(3)); EXPECT_CALL(inspector, on_node_done()).Times(Exactly(3)); EXPECT_CALL(inspector, on_interface(_)).Times(Exactly(1)); EXPECT_CALL(inspector, on_interface_done()).Times(Exactly(1)); EXPECT_CALL(inspector, on_method(_)).Times(Exactly(3)); EXPECT_CALL(inspector, on_method_done()).Times(Exactly(3)); EXPECT_CALL(inspector, on_property(_)).Times(Exactly(1)); EXPECT_CALL(inspector, on_signal(_)).Times(Exactly(1)); EXPECT_CALL(inspector, on_signal_done()).Times(Exactly(1)); EXPECT_CALL(inspector, on_argument(_)).Times(Exactly(7)); EXPECT_CALL(inspector, on_annotation(_)).Times(Exactly(1)); EXPECT_TRUE(parser.invoke_for(tmp_fn)); } TEST(IntrospectionCompiler, invoking_the_compiler_triggers_the_generator) { using namespace ::testing; const std::string tmp_fn(__PRETTY_FUNCTION__); std::remove(tmp_fn.c_str()); ensure_test_introspection_file(tmp_fn); auto parser = std::make_shared(); NiceMock generator; EXPECT_CALL(generator, invoke_for_model_with_configuration(_, _, _)); dbus::Compiler compiler(parser, std::shared_ptr(&generator, [](dbus::Generator*){})); EXPECT_NO_THROW(compiler.process_introspection_file_with_generator_config( tmp_fn, dbus::Generator::default_configuration())); } namespace { struct StubGenerator : public dbus::Generator { int node_count = 0; int interface_count = 0; int method_count = 0; int signal_count = 0; int property_count = 0; int annotation_count = 0; int argument_count = 0; bool invoke_for_model_with_configuration( const std::shared_ptr& element, std::istream&, const dbus::GeneratorConfiguration&) { auto visitor = [this](const dbus::Compiler::Element& element) { switch(element.type()) { case dbus::Compiler::Element::Type::node: node_count++; break; case dbus::Compiler::Element::Type::interface: interface_count++; break; case dbus::Compiler::Element::Type::method: method_count++; break; case dbus::Compiler::Element::Type::signal: signal_count++; break; case dbus::Compiler::Element::Type::property: property_count++; break; case dbus::Compiler::Element::Type::argument: argument_count++; break; case dbus::Compiler::Element::Type::annotation: annotation_count++; break; } }; static const std::function ignored{}; element->apply(ignored, visitor, ignored); return true; } }; } TEST(IntrospectionGenerator, receives_correct_tree_from_compiler) { using namespace ::testing; const std::string tmp_fn(__PRETTY_FUNCTION__); std::remove(tmp_fn.c_str()); ensure_test_introspection_file(tmp_fn); auto parser = std::make_shared(); auto generator = std::make_shared(); dbus::Compiler compiler(parser, generator); EXPECT_NO_THROW(compiler.process_introspection_file_with_generator_config( tmp_fn, dbus::Generator::default_configuration())); EXPECT_EQ(3, generator->node_count); EXPECT_EQ(1, generator->interface_count); EXPECT_EQ(3, generator->method_count); EXPECT_EQ(1, generator->signal_count); EXPECT_EQ(1, generator->property_count); EXPECT_EQ(7, generator->argument_count); EXPECT_EQ(1, generator->annotation_count); } TEST(IntrospectionGenerator, generates_correct_protocol_definition_header_file) { using namespace ::testing; const std::string tmp_fn(__PRETTY_FUNCTION__); std::remove(tmp_fn.c_str()); ensure_test_introspection_file(tmp_fn); auto parser = std::make_shared(); auto generator = std::make_shared(); dbus::Compiler compiler(parser, generator); EXPECT_NO_THROW(compiler.process_introspection_file_with_generator_config( tmp_fn, dbus::Generator::default_configuration())); const std::string protocol_header_file_name{"SampleInterface.h"}; } TEST(CompilerMain, generates_correct_protocol_definition_header_file_for_com_canonical_user_metrics) { const char* argv[] = { "dbus-cppc", core::testing::com::canonical::user_metrics_introspection_file() }; EXPECT_EQ(EXIT_SUCCESS, dbus::Compiler::main(2, argv)); argv[1] = core::testing::com::canonical::url_dispatcher_introspection_file(); EXPECT_EQ(EXIT_SUCCESS, dbus::Compiler::main(2, argv)); argv[1] = core::testing::org::freedesktop::modem_manager::modem::cdma_introspection_file(); EXPECT_EQ(EXIT_SUCCESS, dbus::Compiler::main(2, argv)); argv[1] = core::testing::org::freedesktop::modem_manager::modem::firmware_introspection_file(); EXPECT_EQ(EXIT_SUCCESS, dbus::Compiler::main(2, argv)); argv[1] = core::testing::org::freedesktop::modem_manager::modem::gsm::card_introspection_file(); EXPECT_EQ(EXIT_SUCCESS, dbus::Compiler::main(2, argv)); argv[1] = core::testing::org::freedesktop::modem_manager::modem::gsm::contact_introspection_file(); EXPECT_EQ(EXIT_SUCCESS, dbus::Compiler::main(2, argv)); argv[1] = core::testing::org::freedesktop::modem_manager::modem::gsm::hso_introspection_file(); EXPECT_EQ(EXIT_SUCCESS, dbus::Compiler::main(2, argv)); argv[1] = core::testing::org::freedesktop::modem_manager::modem::gsm::network_introspection_file(); EXPECT_EQ(EXIT_SUCCESS, dbus::Compiler::main(2, argv)); argv[1] = core::testing::org::freedesktop::modem_manager::modem::gsm::sms_introspection_file(); EXPECT_EQ(EXIT_SUCCESS, dbus::Compiler::main(2, argv)); argv[1] = core::testing::org::freedesktop::modem_manager::modem::gsm::ussd_introspection_file(); EXPECT_EQ(EXIT_SUCCESS, dbus::Compiler::main(2, argv)); } dbus-cpp-5.0.3/tests/data/000077500000000000000000000000001407013304700153065ustar00rootroot00000000000000dbus-cpp-5.0.3/tests/data/com.canonical.URLDispatcher.xml000066400000000000000000000003141407013304700232020ustar00rootroot00000000000000 dbus-cpp-5.0.3/tests/data/com.canonical.UserMetrics.xml000066400000000000000000000027671407013304700230140ustar00rootroot00000000000000 dbus-cpp-5.0.3/tests/data/org.freedesktop.ModemManager.Modem.Cdma.xml000066400000000000000000000207041407013304700253720ustar00rootroot00000000000000 Activates the modem for use with a given carrier. In the event of immediate failure, returns an error value instead of setting a DBus error. Name of carrier. An enum from MM_MODEM_CDMA_ACTIVATION_ERROR. This is returned for immediate errors. Delayed errors are returned via an ActivationStateChanged signal Sets modem configuration data. Unlike regular Activate(), this does not contact the carrier. Some modems will reboot after this call is made. A dictionary of properties to set on the modem. Keys include 'mdn', 'min' The device activation state changed. Current activation state Carrier-specific error code Selected Modem.Simple.GetStatus keys that have changed as a result of this activation state change. Will include 'mdn' and 'min'. Get the current signal quality. Signal quality (percent). Get the Electronic Serial Number of the card. The ESN. Get the Service System details of the current network, if registered. A structure containing the Band Class (0 = unknown, 1 = 800 MHz, 2 = 1900 MHz), the Band ("A" - "F" as defined by IS707-A), and the System ID of the serving network. The signal quality changed. The new quality in percent, 0..100. Get device registration state. CDMA 1x registration state. EVDO registration state. The modem's Mobile Equipment Identifier. The device registration state changed. CDMA 1x registration state. EVDO registration state. Registration status is unknown or the device is not registered. Registered, but roaming status is unknown or cannot be provided by the device. The device may or may not be roaming. Currently registered on the home network. Currently registered on a roaming network. Device is not activated Device is activating Device is partially activated; carrier-specific steps required to continue. Device is ready for use. Device cannot activate while roaming. Device cannot activate on this network type (eg EVDO vs 1xRTT). Device could not connect to the network for activation. Device could not authenticate to the network for activation. Later stages of device provisioning failed. No signal available. An error occurred. Activation timed out. API call for initial activation failed. dbus-cpp-5.0.3/tests/data/org.freedesktop.ModemManager.Modem.Firmware.xml000066400000000000000000000112611407013304700263000ustar00rootroot00000000000000 This interface allows clients to select or install firmware images on modems. Firmware slots and firmware images are identified by arbitrary opaque strings. Firmware images are represented as dictionaries of properties. Certain properties are pre-defined, and some are required: Name (string, required): A user-readable name for the firmware image. Version (string, optional): The version of the firmware. The format is unspecified; tools attempting to upgrade firmware automatically must understand the versioning scheme used by the modem driver they are interacting with. May be displayed to the user. List installed and available firmware images. Depending on the type of modem, installed images may be stored on the host or the modem. The distinction between "installed" and "available" is not one of where the firmware is stored, but that installed images can be selected non-destructively, while available images must be installed into a slot, possibly overwriting another installed image. The identifier of the selected firmware slot, or the empty string if no slot is selected (such as if all slots are empty, or no slots exist). A dictionary of slots into which firmware is and/or can be installed. The key of each entry is the identifier of the slot, and the value is either an empty dictionary if the slot is empty, or a dictionary of properties of the firmware image installed in that slot. The slot identifiers and the mapping between slots and firmware images are guaranteed to remain stable only as long as the modem remains present. A dictionary of available firmware images. The key of each entry is the identifier of the image, and the value is a dictionary of properties of the image. The image identifiers are guaranteed to remain stable only as long as the modem remains present. Selects a different firmware image to use, and immediately resets the modem so that it begins using the new firmware image. Select will fail if the identifier does not match any of the slot identifiers returned by List, or if the slot could not be selected for some reason. The identifier of the firmware slot to select. Install an available firmware image into a slot. Install does not guarantee that the image will be installed into the specified slot, but does guarantee that, if the slot is empty, no image will be overwritten, and if the slot is not empty, no image other than the one in that slot will be overwritten. Install will fail if either of the identifiers is invalid, or if the image could not be installed into the slot for some reason. The identifier of the firmware image to install. The identifier of the slot into which the firmware should be installed. dbus-cpp-5.0.3/tests/data/org.freedesktop.ModemManager.Modem.Gsm.Card.xml000066400000000000000000000124641407013304700261300ustar00rootroot00000000000000 This interface implements functionality pertaining to the SIM card. Get the IMEI of the modem. The IMEI. Get the IMSI of the SIM card. The IMSI. Returns the ID of the network operator that issued the SIM card, formatted as a 5 or 6-digit MCC/MNC code (ex "310410"). The operator ID formatted as an MCC/MNC code. Returns the SPN (Service Provider Name) from the SIM card, The Service Provider Name. Send the PUK and a new PIN to unlock the SIM card. The PUK code. The PIN code. Send the PIN to unlock the SIM card. The PIN code. Enable or disable the PIN checking. The PIN code. True to enable PIN checking. Change the PIN code. The current PIN code. The new PIN code. An obfuscated SIM identifier based on the IMSI or the ICCID. This may be available before the PIN has been entered depending on the device itself. DEPRECATED; should not be used in new applications. Use the SupportedBands property of the Gsm.Network interface instead. DEPRECATED; should not be used in new applications. Use the AccessTechnology property, AllowedMode property, and the SetAllowedMode() method of the Gsm.Network interface instead. Facilities for which PIN locking is enabled. dbus-cpp-5.0.3/tests/data/org.freedesktop.ModemManager.Modem.Gsm.Contacts.xml000066400000000000000000000070351407013304700270330ustar00rootroot00000000000000 Add a new contact to the SIM card. The name of the contact. The phone number of the contact. The index of the new contact. Delete a contact from the SIM card. The index of the contact. Retrieve a contact from the SIM card. The index of the contact. The contact structure containing index, name, and number. List all contacts on the SIM card. The list of contacts where each contact has an index, name, and number. Find a contact from the SIM card. The pattern to search for. The list of matching contacts where a contact has an index, name, and number. Get the number of contacts stored on the SIM card. The number of contacts. dbus-cpp-5.0.3/tests/data/org.freedesktop.ModemManager.Modem.Gsm.Hso.xml000066400000000000000000000012761407013304700260070ustar00rootroot00000000000000 Authenticate using the passed user name and password. The user name. The password. dbus-cpp-5.0.3/tests/data/org.freedesktop.ModemManager.Modem.Gsm.Network.xml000066400000000000000000000333321407013304700267050ustar00rootroot00000000000000 Register the device to network. The network ID to register. An empty string can be used to register to the home network. Scan for available networks.

Found networks. It's an array of dictionaries (strings for both keys and values) with each array element describing a mobile network found in the scan. Each dict may include one or more of the following keys:

  • "status": a number representing network availability status as defined in 3GPP TS 27.007 section 7.3. e.g. "0" (unknown), "1" (available), "2" (current), or "3" (forbidden). This key will always be present.
  • "operator-long": long-format name of operator. If the name is unknown, this field should not be present.
  • "operator-short": short-format name of operator. If the name is unknown, this field should not be present.
  • "operator-num": mobile code of the operator. Returned in the format "MCCMNC", where MCC is the three-digit ITU E.212 Mobile Country Code and MNC is the two- or three-digit GSM Mobile Network Code. e.g. "31026" or "310260".
  • "access-tech": a number representing the access technology used by this mobile network as described in 3GPP TS 27.007 section 7.3. e.g. "0" (GSM), "1" (GSM Compact), "2" (UTRAN/UMTS), "3" (EDGE), etc.
Set the APN. The APN. Get the current signal quality. Signal quality (percent). Sets the bands the device is allowed to use when connecting to a mobile network. The desired bands, as a set of flags. Returns the current bands the device is using. (Note for plugin writers: returned value must not be ANY) The current bands, as a set of flags. Set the desired mode the device may use when connecting to a mobile network (DEPRECATED; see SetAllowedMode instead). The desired network mode. Only one mode may be specified, and may not be UNKNOWN. Returns the current network mode of the device (DEPRECATED; does not allow returning both the saved mode preference *and* the current access technology of the device at the same time. See the AllowedMode property instead). Returns the general network mode (ex. 2G/3G preference) of the device. Get the registration status and the current operator (if registered). The returned information is composed of the following items in the following order:
  • Mobile registration status as defined in 3GPP TS 27.007 section 10.1.19. See the MM_MODEM_GSM_NETWORK_REG_STATUS enumeration for possible values.
  • Current operator code of the operator to which the mobile is currently registered. Returned in the format "MCCMNC", where MCC is the three-digit ITU E.212 Mobile Country Code and MNC is the two- or three-digit GSM Mobile Network Code. If the MCC and MNC are not known or the mobile is not registered to a mobile network, this value should be a zero-length (blank) string. e.g. "31026" or "310260".
  • Current operator name of the operator to which the mobile is currently registered. If the operator name is not knowon or the mobile is not registered to a mobile network, this value should be a zero-length (blank) string.
Set the access technologies a device is allowed to use when connecting to a mobile network. The allowed mode. The device may not support all modes; see the org.freedesktop.ModemManager.Gsm.Card.SupportedModes property for allowed modes for each device. All devices support the "ANY" flag. The allowed access technologies (eg 2G/3G preference) the device is allowed to use when connecting to a mobile network. The current network access technology used by the device to communicate with the base station. (Note to plugin writers: if the device's access technology cannot be determined, use UNKNOWN) Bands supported by the card. (Note for plugin writers: returned value must not contain ANY) The signal quality changed. The new quality in percent, 0..100. The registration status changed. Mobile registration status as defined in 3GPP TS 27.007 section 10.1.19. Current operator code of the operator to which the mobile is currently registered. Returned in the format "MCCMNC", where MCC is the three-digit ITU E.212 Mobile Country Code and MNC is the two- or three-digit GSM Mobile Network Code. If the MCC and MNC are not known or the mobile is not registered to a mobile network, this value should be a zero-length (blank) string. e.g. "31026" or "310260". Current operator name of the operator to which the mobile is currently registered. If the operator name is not knowon or the mobile is not registered to a mobile network, this value should be a zero-length (blank) string. The network mode preference changed. (DEPRECATED; see documentation for GetNetworkMode/SetNetworkMode) The new network mode. GSM registration code as defined in 3GPP TS 27.007 section 10.1.19. Not registered, not searching for new operator to register. Registered on home network. Not registered, searching for new operator to register with. Registration denied. Unknown registration status. Registered on a roaming network. DEPRECATED; should not be used in new applications. Use AccessTechnology, AllowedMode, and SetAllowedMode() instead. Any network mode can be used GPRS EDGE UMTS (3G) HSDPA Prefer 2G (GPRS or EDGE) Prefer 3G (UMTS/HSDPA/HSUPA/HSPA) Use only 2G (GPRS or EDGE) Use only 3G (UMTS/HSDPA/HSUPA/HSPA) HSUPA HSPA (HSDPA + HSUPA)
dbus-cpp-5.0.3/tests/data/org.freedesktop.ModemManager.Modem.Gsm.SMS.xml000066400000000000000000000151501407013304700257140ustar00rootroot00000000000000 Delete an SMS message. The index of the SMS. Retrieve an SMS from the SIM card. The index of the SMS. A dictionary containing SMS properties of the SMS specified by the given index. This dictionary may contain the following key/value pairs: number : string - Phone number (mandatory) text : string - SMS text (mandatory, empty if data cannot be decoded) data : byte array - SMS user data (TP-UD) (mandatory) data-coding-scheme: uint (0..255) - SMS user data coding scheme (TP-DCS) (mandatory) smsc : string - SMS service center number (optional) class : uint (0..3) - Message importance and location (optional) completed: boolean - Whether all message parts have been received or not (optional) index : uint - Index of message (for Get and Delete) (optional) SMS properties to save with the following key values: number : string - Phone number (mandatory) text : string - SMS text (mandatory) smsc : string - SMS service center number (optional) relative-validity : uint - Minutes until the SMS expires in SMSC (optional) class : uint (0..3) - Message importance and location (optional) SMS properties to save with the following key values: number : string - Phone number (mandatory) text : string - SMS text (mandatory) smsc : string - SMS service center number (optional) relative-validity : uint - Minutes until the SMS expires in SMSC (optional) class : uint (0..3) - Message importance and location (optional) Emitted when any part of a new SMS has been received (but not for subsequent parts, if any). Not all parts may have been received and the message may not be complete; if it is, the 'complete' argument will be TRUE. Index of the new SMS. TRUE if all message parts have been received, otherwise FALSE. Emitted when the complete-ness status of an SMS message changes. An SMS may not necessarily be complete when the first part is received; this signal will be emitted when all parts have been received, even for single-part messages. The index of the SMS. TRUE if all message parts have been received, otherwise FALSE. dbus-cpp-5.0.3/tests/data/org.freedesktop.ModemManager.Modem.Gsm.Ussd.xml000066400000000000000000000070321407013304700261700ustar00rootroot00000000000000 Sends a USSD command string to the network initiating a USSD session. When the request is handled by the network, the method returns the response or an appropriate error. The network may be awaiting further response from the ME after returning from this method and no new command can be initiated until this one is cancelled or ended. The command to start the USSD session with. The network response to the command which started the USSD session. Respond to a USSD request that is either initiated by the mobile network, or that is awaiting further input after Initiate() was called. The response to network-initiated USSD command, or a response to a request for further input. The network reply to this response to the network-initiated USSD command. The reply may require further responses. Cancel an ongoing USSD session, either mobile or network initiated. Indicates the state of any ongoing USSD session. Values may be one of the following: "idle" (no active session), "active" (a session is active and the mobile is waiting for a response), "user-response" (the network is waiting for the client's response, which must be sent using Respond()). Contains any network-initiated request to which no USSD response is required. When no USSD session is active, or when there is no network- initiated request, this property will be a zero-length string. Contains any pending network-initiated request for a response. Client should call Respond() with the appropriate response to this request. When no USSD session is active, or when there is no pending network-initiated request, this property will be a zero-length string. dbus-cpp-5.0.3/tests/dbus_test.cpp000066400000000000000000000104541407013304700171010ustar00rootroot00000000000000/* * Copyright © 2013 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Thomas Voß */ #include #include #include #include #include #include "sig_term_catcher.h" #include "test_data.h" #include "test_service.h" #include #include #include namespace dbus = core::dbus; namespace { struct DBus : public core::dbus::testing::Fixture { }; auto session_bus_config_file = core::dbus::testing::Fixture::default_session_bus_config_file() = core::testing::session_bus_configuration_file(); auto system_bus_config_file = core::dbus::testing::Fixture::default_system_bus_config_file() = core::testing::system_bus_configuration_file(); } TEST_F(DBus, QueryingUnixProcessIdReturnsCorrectResult) { const std::string path{"/this/is/just/a/test/service"}; core::testing::CrossProcessSync barrier; auto client = core::posix::fork([this, path, &barrier]() { barrier.wait_for_signal_ready_for(std::chrono::milliseconds{500}); auto bus = session_bus(); auto service = dbus::Service::use_service(bus); auto object = service->object_for_path(dbus::types::ObjectPath{path}); object->invoke_method_synchronously(); return ::testing::Test::HasFailure() ? core::posix::exit::Status::failure : core::posix::exit::Status::success; }, core::posix::StandardStream::empty); uint32_t pid = client.pid(); uint32_t uid = getuid(); auto service = core::posix::fork([this, path, pid, uid, &barrier]() { core::testing::SigTermCatcher sc; auto bus = session_bus(); bus->install_executor(core::dbus::asio::make_executor(bus)); dbus::DBus daemon{bus}; auto service = dbus::Service::add_service(bus); auto object = service->add_object_for_path(dbus::types::ObjectPath{path}); uint32_t sender_pid = 0, sender_uid = 0; auto handler = [&daemon, &sender_pid, &sender_uid, bus](const dbus::Message::Ptr& msg) { auto sender = msg->sender(); sender_pid = daemon.get_connection_unix_process_id(sender); sender_uid = daemon.get_connection_unix_user(sender); auto reply = dbus::Message::make_method_return(msg); bus->send(reply); bus->stop(); }; object->install_method_handler(handler); barrier.try_signal_ready_for(std::chrono::milliseconds{500}); std::thread t1{[bus](){ bus->run(); }}; std::thread t2{[bus](){ bus->run(); }}; sc.wait_for_signal(); if (t1.joinable()) t1.join(); if (t2.joinable()) t2.join(); EXPECT_EQ(pid, sender_pid); EXPECT_EQ(uid, sender_uid); return ::testing::Test::HasFailure() ? core::posix::exit::Status::failure : core::posix::exit::Status::success; }, core::posix::StandardStream::empty); auto client_result = client.wait_for(core::posix::wait::Flags::untraced); EXPECT_EQ(core::posix::wait::Result::Status::exited, client_result.status); EXPECT_EQ(core::posix::exit::Status::success, client_result.detail.if_exited.status); service.send_signal_or_throw(core::posix::Signal::sig_term); auto service_result = service.wait_for(core::posix::wait::Flags::untraced); EXPECT_EQ(core::posix::wait::Result::Status::exited, service_result.status); EXPECT_EQ(core::posix::exit::Status::success, service_result.detail.if_exited.status); } dbus-cpp-5.0.3/tests/executor_test.cpp000066400000000000000000000370141407013304700200030ustar00rootroot00000000000000/* * Copyright © 2013 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Thomas Voß */ #include #include #include #include #include #include "sig_term_catcher.h" #include "test_data.h" #include "test_service.h" #include #include #include #include #include namespace dbus = core::dbus; namespace { // A very simple wrapper for flipping a coin whether something should go wrong. // Please note that we are considering an unfair coin here, with a probability of 0.2 // for failure. struct ChaosMonkey { constexpr static const double probability_for_failure{0.2}; bool thinks_that_something_should_go_wrong() { return coin(rng) == 1; } std::mt19937 rng{42}; std::binomial_distribution<> coin{1, 1.-probability_for_failure}; }; struct Executor : public core::dbus::testing::Fixture { protected: boost::asio::io_service io_service; }; auto session_bus_config_file = core::dbus::testing::Fixture::default_session_bus_config_file() = core::testing::session_bus_configuration_file(); auto system_bus_config_file = core::dbus::testing::Fixture::default_system_bus_config_file() = core::testing::system_bus_configuration_file(); } TEST_F(Executor, ThrowsOnConstructionFromNullBus) { EXPECT_ANY_THROW(core::dbus::asio::make_executor(core::dbus::Bus::Ptr{}, io_service)); } TEST_F(Executor, DoesNotThrowForExistingBus) { auto bus = session_bus(); EXPECT_NO_THROW(bus->install_executor(core::dbus::asio::make_executor(bus, io_service))); } TEST_F(Executor, ABusRunByAnExecutorReceivesSignals) { core::testing::CrossProcessSync cross_process_sync; const int64_t expected_value = 42; auto service = [this, expected_value, &cross_process_sync]() { core::testing::SigTermCatcher sc; auto bus = session_bus(); bus->install_executor(dbus::asio::make_executor(bus, io_service)); auto service = dbus::Service::add_service(bus); auto skeleton = service->add_object_for_path(dbus::types::ObjectPath("/this/is/unlikely/to/exist/Service")); skeleton->install_method_handler( [bus, skeleton, expected_value](const dbus::Message::Ptr& msg) { auto reply = dbus::Message::make_method_return(msg); reply->writer() << expected_value; bus->send(reply); skeleton->emit_signal(expected_value); }); cross_process_sync.try_signal_ready_for(std::chrono::milliseconds{500}); std::thread worker([bus]() { bus->run(); }); sc.wait_for_signal(); bus->stop(); if (worker.joinable()) worker.join(); return ::testing::Test::HasFailure() ? core::posix::exit::Status::failure : core::posix::exit::Status::success; }; auto client = [this, expected_value, &cross_process_sync]() -> core::posix::exit::Status { auto bus = session_bus(); bus->install_executor(dbus::asio::make_executor(bus, io_service)); std::thread t{[bus](){bus->run();}}; EXPECT_EQ(std::uint32_t(1), cross_process_sync.wait_for_signal_ready_for(std::chrono::milliseconds{500})); auto stub_service = dbus::Service::use_service(bus, dbus::traits::Service::interface_name()); auto stub = stub_service->object_for_path(dbus::types::ObjectPath("/this/is/unlikely/to/exist/Service")); auto signal = stub->get_signal(); int64_t received_signal_value = -1; signal->connect([bus, &received_signal_value](const int32_t& value) { received_signal_value = value; bus->stop(); }); auto result = stub->invoke_method_synchronously(); if (t.joinable()) t.join(); EXPECT_FALSE(result.is_error()); EXPECT_EQ(expected_value, result.value()); EXPECT_EQ(expected_value, received_signal_value); return ::testing::Test::HasFailure() ? core::posix::exit::Status::failure : core::posix::exit::Status::success; }; EXPECT_EQ(core::testing::ForkAndRunResult::empty, core::testing::fork_and_run(service, client)); } TEST_F(Executor, TimeoutsAreHandledCorrectly) { core::testing::CrossProcessSync cross_process_sync; const int64_t expected_value = 42; auto service = [this, expected_value, &cross_process_sync]() { ChaosMonkey chaos_monkey; core::testing::SigTermCatcher sc; auto bus = session_bus(); bus->install_executor(dbus::asio::make_executor(bus, io_service)); auto service = dbus::Service::add_service(bus); auto skeleton = service->add_object_for_path(dbus::types::ObjectPath("/this/is/unlikely/to/exist/Service")); skeleton->install_method_handler( [bus, skeleton, expected_value, &chaos_monkey](const dbus::Message::Ptr& msg) { // Let's add some randomness to this test and see if things are still stable. // In this case, chaos means an early return and no reply being sent. if (chaos_monkey.thinks_that_something_should_go_wrong()) return; auto reply = dbus::Message::make_method_return(msg); reply->writer() << expected_value; bus->send(reply); }); cross_process_sync.try_signal_ready_for(std::chrono::seconds{20}); std::thread w1([bus]() { bus->run(); }); std::thread w2([bus]() { bus->run(); }); sc.wait_for_signal(); bus->stop(); if (w1.joinable()) w1.join(); if (w2.joinable()) w2.join(); return ::testing::Test::HasFailure() ? core::posix::exit::Status::failure : core::posix::exit::Status::success; }; auto client = [this, expected_value, &cross_process_sync]() -> core::posix::exit::Status { auto bus = session_bus(); bus->install_executor(dbus::asio::make_executor(bus, io_service)); std::thread t{[bus](){bus->run();}}; // If you encounter failures in the client, uncomment the following two lines // and follow the instructions on the terminal. // std::cout << "Invoke gdb with: sudo gdb -p " << getpid() << std::endl; // sleep(10); EXPECT_EQ(std::uint32_t(1), cross_process_sync.wait_for_signal_ready_for(std::chrono::seconds{20})); auto stub_service = dbus::Service::use_service(bus, dbus::traits::Service::interface_name()); auto stub = stub_service->object_for_path(dbus::types::ObjectPath("/this/is/unlikely/to/exist/Service")); std::thread updater1([bus, stub]() { for (unsigned int counter = 0; counter < 1000; counter++) { try { auto result = stub->transact_method(); if (result.is_error()) std::cout << result.error().print() << std::endl; else EXPECT_EQ(42, result.value()); } catch(const std::runtime_error& e) { std::cout << e.what() << std::endl; } } }); std::thread updater2([bus, stub]() { for (unsigned int counter = 0; counter < 1000; counter++) { try { auto result = stub->transact_method(); if (result.is_error()) std::cout << result.error().print() << std::endl; else EXPECT_EQ(42, result.value()); } catch(const std::runtime_error& e) { std::cout << e.what() << std::endl; } } }); if (updater1.joinable()) updater1.join(); if (updater2.joinable()) updater2.join(); bus->stop(); if (t.joinable()) t.join(); return ::testing::Test::HasFailure() ? core::posix::exit::Status::failure : core::posix::exit::Status::success; }; EXPECT_EQ(core::testing::ForkAndRunResult::empty, core::testing::fork_and_run(service, client)); } /*TEST(Bus, TimeoutThrowsForNullDBusWatch) { boost::asio::io_service io_service; EXPECT_ANY_THROW(core::dbus::asio::Executor::Timeout<> timeout(io_service, nullptr);); } namespace { struct TimeoutHelper { TimeoutHelper(const std::chrono::milliseconds& timeout, bool enabled = true) : timeout(timeout), work(reactor), invoked(false), enabled(enabled) { } void notify_invocation() { invoked = true; reactor.stop(); } bool has_been_invoked() const { return invoked; } std::chrono::milliseconds timeout; boost::asio::io_service reactor; boost::asio::io_service::work work; bool invoked; bool enabled; }; } namespace core { namespace dbus { namespace traits { template<> struct Timeout { typedef int DurationType; static inline bool is_timeout_enabled(TimeoutHelper* helper) { return helper->enabled; } static inline DurationType get_timeout_interval(TimeoutHelper* helper) { return helper->timeout.count(); } static inline void invoke_timeout_handler(TimeoutHelper* helper) { helper->notify_invocation(); } }; } } } } TEST(Executor, TimeoutHandlerIsInvokedForEnabledDBusTimeout) { static const std::chrono::seconds test_timeout { 2 }; static const std::chrono::milliseconds expected_timeout { 100 }; ASSERT_GT(test_timeout, expected_timeout); TimeoutHelper helper {expected_timeout}; boost::asio::deadline_timer test_timer(helper.reactor); test_timer.expires_from_now(boost::posix_time::seconds(test_timeout.count())); test_timer.async_wait([&](const boost::system::error_code&) { helper.reactor.stop(); }); auto to = std::make_shared>(helper.reactor, std::addressof(helper)); to->start(); helper.reactor.run(); EXPECT_TRUE(helper.has_been_invoked()); } TEST(Bus, TimeoutHandlerIsNotInvokedForDisabledDBusTimeout) { static const std::chrono::milliseconds test_timeout { 200 }; static const std::chrono::milliseconds expected_timeout { 100 }; ASSERT_GT(test_timeout, expected_timeout); static const bool disabled { false }; TimeoutHelper helper {expected_timeout, disabled}; boost::asio::deadline_timer test_timer(helper.reactor); test_timer.expires_from_now(boost::posix_time::milliseconds(test_timeout.count())); test_timer.async_wait([&](const boost::system::error_code&) { helper.reactor.stop(); }); auto to = std::make_shared>(helper.reactor, std::addressof(helper)); to->start(); helper.reactor.run(); EXPECT_FALSE(helper.has_been_invoked()); } TEST(Bus, TimeoutHandlerIsNotInvokedForEnabledButCancelledDBusTimeout) { static const std::chrono::milliseconds test_timeout { 200 }; static const std::chrono::milliseconds expected_timeout { 100 }; ASSERT_GT(test_timeout, expected_timeout); TimeoutHelper helper {expected_timeout}; boost::asio::deadline_timer test_timer(helper.reactor); test_timer.expires_from_now(boost::posix_time::milliseconds(test_timeout.count())); test_timer.async_wait([&](const boost::system::error_code&) { helper.reactor.stop(); }); auto to = std::make_shared>(helper.reactor, std::addressof(helper)); to->start(); helper.reactor.post([&]() { to->cancel(); }); helper.reactor.run(); EXPECT_FALSE(helper.has_been_invoked()); } #include namespace { struct WatchHelper { inline static int readable_event() { return 0; }; inline static int writeable_event() { return 1; }; inline static int error_event() { return 2; }; inline static int hangup_event() { return 3; }; static const unsigned int initial_value = 0; static const int flags = 0; WatchHelper(std::function handler) : fd(eventfd(initial_value, flags)), invocation_handler(handler), invocation_cache(4, false), work(reactor) { } ~WatchHelper() { close(fd); } bool invoke_for_event(int event) { invocation_cache[event] = true; if (has_been_invoked_for(readable_event()) && has_been_invoked_for(writeable_event())) reactor.stop(); invocation_handler(event, *this); return true; } bool has_been_invoked_for(int event) { return invocation_cache[event]; } int fd; std::function invocation_handler; std::vector invocation_cache; boost::asio::io_service reactor; boost::asio::io_service::work work; }; } namespace org { namespace freedesktop { namespace dbus { namespace traits { template<> struct Watch { inline static int readable_event() { return WatchHelper::readable_event(); }; inline static int writeable_event() { return WatchHelper::writeable_event(); }; inline static int error_event() { return WatchHelper::error_event(); }; inline static int hangup_event() { return WatchHelper::hangup_event(); }; static int get_watch_unix_fd(WatchHelper* watch) { return watch->fd; } static bool is_watch_monitoring_fd_for_readable(WatchHelper*) { return true; } static bool is_watch_monitoring_fd_for_writable(WatchHelper*) { return true; } static bool invoke_watch_handler_for_event(WatchHelper* watch, int event) { return watch->invoke_for_event(event); } }; } } } } TEST(Executor, WatchHandlerIsInvokedForReadableAndWritableEvents) { WatchHelper helper([&](int, WatchHelper& wh) { static const int64_t make_readable = std::numeric_limits::max(); write(wh.fd, std::addressof(make_readable), sizeof(make_readable)); }); auto watch = std::make_shared>(helper.reactor, std::addressof(helper)); helper.reactor.post([&]() { int64_t value = 0; read(helper.fd, std::addressof(value), sizeof(value)); }); watch->start(); helper.reactor.run(); EXPECT_TRUE(helper.has_been_invoked_for(WatchHelper::readable_event())); EXPECT_TRUE(helper.has_been_invoked_for(WatchHelper::writeable_event())); } */ dbus-cpp-5.0.3/tests/match_rule_test.cpp000066400000000000000000000024611407013304700202660ustar00rootroot00000000000000/* * Copyright © 2013 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Thomas Voß */ #include #include TEST(MatchRule, ConstructingAMatchRuleYieldsCorrectResult) { core::dbus::MatchRule rule; rule .type(core::dbus::Message::Type::signal) .sender("org.freedesktop.DBus") .interface("org.freedesktop.DBus") .member("ListNames") .path(core::dbus::types::ObjectPath("/core/DBus")); const std::string expected_rule {"type='signal',sender='org.freedesktop.DBus',interface='org.freedesktop.DBus',member='ListNames',path='/core/DBus'" }; EXPECT_EQ(expected_rule, rule.as_string()); } dbus-cpp-5.0.3/tests/message_router_test.cpp000066400000000000000000000045221407013304700211670ustar00rootroot00000000000000/* * Copyright © 2013 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Thomas Voß */ #include #include #include namespace dbus = core::dbus; namespace { dbus::Message::Ptr a_signal_message(const std::string& path, const std::string& interface, const std::string& name) { return dbus::Message::make_signal( path, interface, name); } } TEST(MessageRouterForType, ARegisteredRouteIsInvokedForMessageOfMatchingType) { bool invoked {false}; dbus::MessageRouter router([](const dbus::Message::Ptr& msg) { return msg->type(); }); router.install_route(dbus::Message::Type::signal, [&](const dbus::Message::Ptr& msg) { if (msg->type() == dbus::Message::Type::signal) invoked = true; }); auto signal = a_signal_message("/core/DBus", "org.freedesktop.DBus", "LaLeLu"); router(signal); EXPECT_TRUE(invoked); } TEST(MessageRouterForType, HandlerDoesNotDeadlock) { bool invoked {false}; dbus::MessageRouter router([](const dbus::Message::Ptr& msg) { return msg->type(); }); router.install_route(dbus::Message::Type::signal, [&](const dbus::Message::Ptr& msg) { if (msg->type() == dbus::Message::Type::signal) { /* This will deadlock if the router has not released it's * internal lock before calling this handler. */ router.uninstall_route(dbus::Message::Type::signal); invoked = true; } }); auto signal = a_signal_message("/core/DBus", "org.freedesktop.DBus", "LaLeLu"); router(signal); EXPECT_TRUE(invoked); } dbus-cpp-5.0.3/tests/message_test.cpp000066400000000000000000000143721407013304700175730ustar00rootroot00000000000000/* * Copyright © 2013 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Thomas Voß */ #include #include #include #include #include namespace dbus = core::dbus; TEST(Message, BuildingAMethodCallMessageSucceedsForValidArguments) { const std::string destination = core::dbus::DBus::name(); const std::string path = core::dbus::DBus::path().as_string(); const std::string interface = core::dbus::DBus::name(); const std::string member = "ListNames"; std::shared_ptr msg; EXPECT_NO_THROW(msg = core::dbus::Message::make_method_call(destination, path, interface, member);); EXPECT_NE(nullptr, msg.get()); } TEST(Message, BuildingAMethodCallMessageThrowsForInvalidArguments) { const std::string destination = core::dbus::DBus::name(); const std::string path = "an:invalid:path"; const std::string interface = core::dbus::DBus::name(); const std::string member = "ListNames"; std::shared_ptr msg; EXPECT_ANY_THROW(msg = core::dbus::Message::make_method_call(destination, path, interface, member);); EXPECT_EQ(nullptr, msg.get()); } TEST(Message, AccessingAReaderOnAnEmptyMessageThrows) { const std::string destination = core::dbus::DBus::name(); const std::string path = core::dbus::DBus::path().as_string(); const std::string interface = core::dbus::DBus::name(); const std::string member = "ListNames"; auto msg = core::dbus::Message::make_method_call(destination, path, interface, member); EXPECT_ANY_THROW(msg->reader()); } TEST(Message, AccessingAWriterOnAnyMessageSucceeds) { const std::string destination = core::dbus::DBus::name(); const std::string path = core::dbus::DBus::path().as_string(); const std::string interface = core::dbus::DBus::name(); const std::string member = "ListNames"; auto msg = core::dbus::Message::make_method_call( destination, path, interface, member); EXPECT_NO_THROW(auto writer = msg->writer()); { msg->writer().push_int16(43); msg->writer().push_int16(42); } EXPECT_NO_THROW(auto writer = msg->writer();); } TEST(Message, WriteAndSuccessiveReadAreIdempotent) { const std::string destination = core::dbus::DBus::name(); const std::string path = core::dbus::DBus::path().as_string(); const std::string interface = core::dbus::DBus::name(); const std::string member = "ListNames"; auto msg = core::dbus::Message::make_method_call( destination, path, interface, member); const int32_t expected_integer_value { 43 }; const double expected_floating_point_value { 42. }; { auto writer = msg->writer(); writer.push_int32(expected_integer_value); writer.push_floating_point(expected_floating_point_value); } auto reader = msg->reader(); auto i = reader.pop_int32(); auto d = reader.pop_floating_point(); EXPECT_EQ(expected_integer_value, i); EXPECT_EQ(expected_floating_point_value, d); } TEST(Message, WriteAndSuccessiveIterationAreIdempotent) { const std::string destination = core::dbus::DBus::name(); const std::string path = core::dbus::DBus::path().as_string(); const std::string interface = core::dbus::DBus::name(); const std::string member = "ListNames"; auto msg = core::dbus::Message::make_method_call( destination, path, interface, member); const std::int32_t expected_integer_value { 43 }; const double expected_floating_point_value { 42. }; { auto writer = msg->writer(); writer.push_int32(expected_integer_value); writer.push_floating_point(expected_floating_point_value); auto vw = writer.open_variant(dbus::types::Signature("(id)")); { auto sw = vw.open_structure(); { sw.push_int32(expected_integer_value); sw.push_floating_point(expected_floating_point_value); } vw.close_structure(std::move(sw)); } writer.close_variant(std::move(vw)); } auto reader = msg->reader(); EXPECT_EQ(dbus::ArgumentType::int32, reader.type()); EXPECT_NO_THROW(reader.pop()); EXPECT_EQ(dbus::ArgumentType::floating_point, reader.type()); EXPECT_NO_THROW(reader.pop()); auto vr = reader.pop_variant(); { auto sr = vr.pop_structure(); { EXPECT_EQ(dbus::ArgumentType::int32, sr.type()); EXPECT_EQ(expected_integer_value, sr.pop_int32()); EXPECT_EQ(dbus::ArgumentType::floating_point, sr.type()); EXPECT_EQ(expected_floating_point_value, sr.pop_floating_point()); } } } namespace { class MessageType : public testing::TestWithParam> { }; } TEST_P(MessageType, IsPrintedCorrectly) { std::stringstream ss; ss << GetParam().first; EXPECT_EQ(GetParam().second, ss.str()); } INSTANTIATE_TEST_CASE_P(MessageType, MessageType, ::testing::Values( std::make_pair(core::dbus::Message::Type::error, "error"), std::make_pair(core::dbus::Message::Type::invalid, "invalid"), std::make_pair(core::dbus::Message::Type::method_call, "method_call"), std::make_pair(core::dbus::Message::Type::method_return, "method_return"), std::make_pair(core::dbus::Message::Type::signal, "signal"))); dbus-cpp-5.0.3/tests/service_test.cpp000066400000000000000000000317311407013304700176050ustar00rootroot00000000000000/* * Copyright © 2013 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Thomas Voß */ #include #include #include #include #include #include #include #include #include #include "sig_term_catcher.h" #include "test_data.h" #include "test_service.h" #include #include #include #include #include namespace dbus = core::dbus; namespace { struct Service : public core::dbus::testing::Fixture { }; auto session_bus_config_file = core::dbus::testing::Fixture::default_session_bus_config_file() = core::testing::session_bus_configuration_file(); auto system_bus_config_file = core::dbus::testing::Fixture::default_system_bus_config_file() = core::testing::system_bus_configuration_file(); } TEST_F(Service, AccessingAnExistingServiceAndItsObjectsOnTheBusWorks) { auto bus = session_bus(); auto names = dbus::DBus(bus).list_names(); ASSERT_GT(names.size(), std::size_t{0}); } TEST_F(Service, AddingServiceAndObjectAndCallingIntoItSucceeds) { core::testing::CrossProcessSync cps1; const int64_t expected_value = 42; auto service = [this, expected_value, &cps1]() { core::testing::SigTermCatcher sc; auto bus = session_bus(); bus->install_executor(core::dbus::asio::make_executor(bus)); auto service = dbus::Service::add_service(bus); auto skeleton = service->add_object_for_path(dbus::types::ObjectPath("/this/is/unlikely/to/exist/Service")); auto signal = skeleton->get_signal(); auto writable_property = skeleton->get_property(); writable_property->set(expected_value); auto readonly_property = skeleton->get_property(); readonly_property->set(7); skeleton->install_method_handler([bus, skeleton, &readonly_property, expected_value](const dbus::Message::Ptr& msg) { auto reply = dbus::Message::make_method_return(msg); reply->writer() << expected_value; bus->send(reply); readonly_property->set(expected_value); auto changed_signal = skeleton->get_signal(); core::dbus::interfaces::Properties::Signals::PropertiesChanged::ArgumentType args("this.is.unlikely.to.exist.Service", {{test::Service::Properties::ReadOnly::name(), core::dbus::types::TypedVariant(expected_value)}}, {}); skeleton->emit_signal(args); changed_signal->emit(args); skeleton->emit_signal(expected_value); }); std::thread t{[bus](){ bus->run(); }}; cps1.try_signal_ready_for(std::chrono::milliseconds{500}); EXPECT_TRUE(sc.wait_for_signal()); bus->stop(); if (t.joinable()) t.join(); return ::testing::Test::HasFailure() ? core::posix::exit::Status::failure : core::posix::exit::Status::success; }; auto client = [this, expected_value, &cps1]() { auto bus = session_bus(); bus->install_executor(core::dbus::asio::make_executor(bus)); std::thread t{[bus](){ bus->run(); }}; EXPECT_EQ(std::uint32_t(1), cps1.wait_for_signal_ready_for(std::chrono::milliseconds{500})); auto stub_service = dbus::Service::use_service(bus); auto stub = stub_service->object_for_path(dbus::types::ObjectPath("/this/is/unlikely/to/exist/Service")); EXPECT_EQ(stub->path().as_string(), "/this/is/unlikely/to/exist/Service"); auto writable_property = stub->get_property(); writable_property->changed().connect([](double d) { std::cout << "Dummy property changed: " << d << std::endl; }); auto readonly_property = stub->get_property(); EXPECT_EQ(readonly_property->get(), (std::uint32_t)7); std::uint32_t changed_value = 0; readonly_property->changed().connect([&changed_value](std::uint32_t value){ changed_value = value; }); auto signal = stub->get_signal(); int64_t received_signal_value = -1; signal->connect([bus, &received_signal_value](const int32_t& value) { received_signal_value = value; bus->stop(); }); try { auto result = stub->invoke_method_synchronously(); EXPECT_FALSE(result.is_error()); EXPECT_EQ(expected_value, result.value()); } catch(const std::exception& e) { std::cout << e.what() << std::endl; } EXPECT_EQ(expected_value, writable_property->get()); EXPECT_NO_THROW(writable_property->set(4242)); EXPECT_EQ(4242, writable_property->get()); if (t.joinable()) t.join(); EXPECT_EQ(expected_value, received_signal_value); EXPECT_EQ(expected_value, readonly_property->get()); EXPECT_EQ(changed_value, expected_value); return ::testing::Test::HasFailure() ? core::posix::exit::Status::failure : core::posix::exit::Status::success; }; EXPECT_EQ(core::testing::ForkAndRunResult::empty, core::testing::fork_and_run(service, client)); } TEST_F(Service, AddingANonExistingServiceDoesNotThrow) { ASSERT_NO_THROW(auto service = dbus::Service::add_service(session_bus());); } namespace { struct Dummy { static const std::string& name() { static std::string s{"A.Dummy.Service"}; return s; } }; } // We cache service allocations in-process. For that, we rely on two child processes for testing purposes and // to check that trying to own a service name for the second name actually throws. TEST_F(Service, AddingAServiceTwiceThrows) { // p1 --| Done accessing the service |--> p2 core::testing::CrossProcessSync first_process_acquired_name; // p2 --| Done trying to access the service |--> p1 core::testing::CrossProcessSync second_process_acquired_name; // This is the child process that owns the dummy service. It waits for the second process to // come up and trying to own the same service on the same bus. Otherwise, the service object // would go out of scope in P1 and clean up the owned name. auto p1 = core::posix::fork([this, &first_process_acquired_name, &second_process_acquired_name] { core::dbus::Service::Ptr service; EXPECT_NO_THROW(service = dbus::Service::add_service(session_bus())); first_process_acquired_name.try_signal_ready_for(std::chrono::seconds{2}); second_process_acquired_name.wait_for_signal_ready_for(std::chrono::seconds{2}); return ::testing::Test::HasFailure() ? core::posix::exit::Status::failure : core::posix::exit::Status::success; }, core::posix::StandardStream::empty); auto p2 = core::posix::fork([this, &first_process_acquired_name, &second_process_acquired_name] { first_process_acquired_name.wait_for_signal_ready_for(std::chrono::seconds{2}); core::dbus::Service::Ptr service; EXPECT_ANY_THROW(service = dbus::Service::add_service(session_bus());); second_process_acquired_name.try_signal_ready_for(std::chrono::seconds{2}); return ::testing::Test::HasFailure() ? core::posix::exit::Status::failure : core::posix::exit::Status::success; }, core::posix::StandardStream::empty); core::posix::wait::Result r1 = p1.wait_for(core::posix::wait::Flags::untraced); core::posix::wait::Result r2 = p2.wait_for(core::posix::wait::Flags::untraced); EXPECT_EQ(core::posix::wait::Result::Status::exited, r1.status); EXPECT_EQ(core::posix::exit::Status::success, r1.detail.if_exited.status); EXPECT_EQ(core::posix::wait::Result::Status::exited, r2.status); EXPECT_EQ(core::posix::exit::Status::success, r2.detail.if_exited.status); } TEST_F(Service, AddingAnExistingServiceThrowsForSpecificFlags) { const std::string service_name { "org.freedesktop.DBus" }; dbus::Bus::RequestNameFlag flags{dbus::Bus::RequestNameFlag::not_set}; ASSERT_ANY_THROW(auto service = dbus::Service::add_service(session_bus(), flags);); } TEST(VoidResult, DefaultConstructionYieldsANonErrorResult) { dbus::Result result; EXPECT_FALSE(result.is_error()); } TEST(VoidResult, FromMethodCallYieldsException) { auto msg = dbus::Message::make_method_call( dbus::DBus::name(), dbus::DBus::path(), dbus::DBus::interface(), "ListNames"); dbus::Result result; EXPECT_ANY_THROW(result.from_message(msg)); } TEST(VoidResult, FromErrorYieldsError) { const std::string error_name = "does.not.exist.MyError"; const std::string error_description = "MyErrorDescription"; auto msg = dbus::Message::make_method_call( dbus::DBus::name(), dbus::DBus::path(), dbus::DBus::interface(), "ListNames"); msg->ensure_serial_larger_than_zero_for_testing(); auto error_reply = dbus::Message::make_error(msg, error_name, error_description); dbus::Result result = dbus::Result::from_message(error_reply); EXPECT_TRUE(result.is_error()); EXPECT_EQ(error_name + ": " + error_description, result.error().print()); } TEST(VoidResult, FromNonEmptyMethodReturnYieldsException) { auto msg = dbus::Message::make_method_call( dbus::DBus::name(), dbus::DBus::path(), dbus::DBus::interface(), "ListNames"); msg->ensure_serial_larger_than_zero_for_testing(); auto reply = dbus::Message::make_method_return(msg); reply->writer() << 42; dbus::Result result; EXPECT_NO_THROW(result.from_message(reply)); } TEST(NonVoidResult, DefaultConstructionYieldsANonErrorResult) { dbus::Result> result; EXPECT_FALSE(result.is_error()); } TEST(NonVoidResult, FromMethodCallYieldsException) { auto msg = dbus::Message::make_method_call( dbus::DBus::name(), dbus::DBus::path(), dbus::DBus::interface(), "ListNames"); dbus::Result result; EXPECT_ANY_THROW(result.from_message(msg)); } TEST(NonVoidResult, FromErrorYieldsError) { const std::string error_name = "does.not.exist.MyError"; const std::string error_description = "MyErrorDescription"; auto msg = dbus::Message::make_method_call( dbus::DBus::name(), dbus::DBus::path(), dbus::DBus::interface(), "ListNames"); msg->ensure_serial_larger_than_zero_for_testing(); auto error_reply = dbus::Message::make_error(msg, error_name, error_description); auto result = dbus::Result::from_message(error_reply); EXPECT_TRUE(result.is_error()); EXPECT_EQ(error_name + ": " + error_description, result.error().print()); } TEST(NonVoidResult, FromEmptyMethodReturnYieldsException) { auto msg = dbus::Message::make_method_call( dbus::DBus::name(), dbus::DBus::path(), dbus::DBus::interface(), "ListNames"); msg->ensure_serial_larger_than_zero_for_testing(); auto reply = dbus::Message::make_method_return(msg); dbus::Result result; EXPECT_ANY_THROW(result.from_message(reply)); } dbus-cpp-5.0.3/tests/service_watcher_test.cpp000066400000000000000000000165441407013304700213270ustar00rootroot00000000000000/* * Copyright © 2014 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Pete Woods */ #include #include #include #include #include #include #include #include #include #include "sig_term_catcher.h" #include "test_data.h" #include "test_service.h" #include "test_service_tiny.h" #include #include #include #include #include namespace dbus = core::dbus; namespace { struct ServiceWatcher : public core::dbus::testing::Fixture { }; auto session_bus_config_file = core::dbus::testing::Fixture::default_session_bus_config_file() = core::testing::session_bus_configuration_file(); auto system_bus_config_file = core::dbus::testing::Fixture::default_system_bus_config_file() = core::testing::system_bus_configuration_file(); } TEST_F(ServiceWatcher, Registration) { core::testing::CrossProcessSync client_is_listening_for_service_registration; auto service = [this, &client_is_listening_for_service_registration]() { core::testing::SigTermCatcher sc; EXPECT_EQ(std::uint32_t(1), client_is_listening_for_service_registration.wait_for_signal_ready_for( std::chrono::milliseconds{500})); auto bus = session_bus(); bus->install_executor(core::dbus::asio::make_executor(bus)); auto service_tiny = dbus::Service::add_service(bus); auto service = dbus::Service::add_service(bus); std::thread t{[bus](){ bus->run(); }}; sc.wait_for_signal(); bus->stop(); if (t.joinable()) t.join(); return ::testing::Test::HasFailure() ? core::posix::exit::Status::failure : core::posix::exit::Status::success; }; auto client = [this, &client_is_listening_for_service_registration]() { auto bus = session_bus(); auto executor = core::dbus::asio::make_executor(bus); bus->install_executor(executor); std::thread t{[bus](){ bus->run(); }}; dbus::DBus daemon(bus); dbus::ServiceWatcher::Ptr service_watcher( daemon.make_service_watcher(dbus::traits::Service::interface_name(), dbus::DBus::WatchMode::registration)); std::vector> owner_changed; unsigned int service_registered = 0; unsigned int service_unregistered = 0; service_watcher->owner_changed().connect( [&owner_changed](const std::string& old_owner, const std::string& new_owner) { owner_changed.push_back({ new_owner, old_owner }); }); service_watcher->service_registered().connect([bus, &service_registered]() { ++service_registered; bus->stop(); }); service_watcher->service_unregistered().connect([&service_unregistered]() { ++service_unregistered; }); client_is_listening_for_service_registration.try_signal_ready_for(std::chrono::milliseconds{500}); if (t.joinable()) t.join(); EXPECT_EQ(std::uint32_t(1), owner_changed.size()); EXPECT_FALSE(owner_changed.at(0).first.empty()); EXPECT_TRUE(owner_changed.at(0).second.empty()); EXPECT_EQ(std::uint32_t(1), service_registered); EXPECT_EQ(std::uint32_t(0), service_unregistered); return ::testing::Test::HasFailure() ? core::posix::exit::Status::failure : core::posix::exit::Status::success; }; EXPECT_EQ(core::testing::ForkAndRunResult::empty, core::testing::fork_and_run(service, client)); } TEST_F(ServiceWatcher, Unregistration) { core::testing::CrossProcessSync client_is_listening_for_service_unregistration; auto service = [this, &client_is_listening_for_service_unregistration]() { auto bus = session_bus(); bus->install_executor(core::dbus::asio::make_executor(bus)); // Ensure that the client is listening for unregistration before we even // start the service. EXPECT_EQ(std::uint32_t(1), client_is_listening_for_service_unregistration.wait_for_signal_ready_for( std::chrono::milliseconds{500})); // We just let this be destroyed immediately dbus::Service::add_service(bus); std::thread t{[bus](){ bus->run(); }}; bus->stop(); if (t.joinable()) t.join(); return ::testing::Test::HasFailure() ? core::posix::exit::Status::failure : core::posix::exit::Status::success; }; auto client = [this, &client_is_listening_for_service_unregistration]() { auto bus = session_bus(); auto executor = core::dbus::asio::make_executor(bus); bus->install_executor(executor); std::thread t{[bus](){ bus->run(); }}; dbus::DBus daemon(bus); dbus::ServiceWatcher::Ptr service_watcher( daemon.make_service_watcher(dbus::traits::Service::interface_name(), dbus::DBus::WatchMode::unregistration)); std::vector> owner_changed; unsigned int service_registered = 0; unsigned int service_unregistered = 0; service_watcher->owner_changed().connect( [&owner_changed](const std::string& old_owner, const std::string& new_owner) { owner_changed.push_back({ new_owner, old_owner }); }); service_watcher->service_registered().connect([&service_registered]() { ++service_registered; }); service_watcher->service_unregistered().connect([bus, &service_unregistered]() { ++service_unregistered; bus->stop(); }); client_is_listening_for_service_unregistration.try_signal_ready_for(std::chrono::milliseconds{500}); if (t.joinable()) t.join(); EXPECT_EQ(std::uint32_t(1), owner_changed.size()); EXPECT_TRUE(owner_changed.at(0).first.empty()); EXPECT_FALSE(owner_changed.at(0).second.empty()); EXPECT_EQ(std::uint32_t(0), service_registered); EXPECT_EQ(std::uint32_t(1), service_unregistered); return ::testing::Test::HasFailure() ? core::posix::exit::Status::failure : core::posix::exit::Status::success; }; EXPECT_EQ(core::testing::ForkAndRunResult::empty, core::testing::fork_and_run(service, client)); } dbus-cpp-5.0.3/tests/sig_term_catcher.h000066400000000000000000000027631407013304700200600ustar00rootroot00000000000000/* * Copyright © 2013 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Thomas Voß */ #ifndef CORE_TESTING_SIG_TERM_CATCHER_H_ #define CORE_TESTING_SIG_TERM_CATCHER_H_ #include #include namespace core { namespace testing { struct SigTermCatcher { inline SigTermCatcher() { sigemptyset(&signal_mask); if (-1 == sigaddset(&signal_mask, SIGTERM)) throw std::system_error(errno, std::system_category()); if (-1 == sigprocmask(SIG_BLOCK, &signal_mask, nullptr)) throw std::system_error(errno, std::system_category()); } inline ~SigTermCatcher() { } inline bool wait_for_signal() { int rc = -1; int signal = -1; rc = sigwait(&signal_mask, &signal); return rc != -1 && signal == SIGTERM; } sigset_t signal_mask; }; } } #endif // CORE_TESTING_SIG_TERM_CATCHER_H_ dbus-cpp-5.0.3/tests/signal_delivery_test.cpp000066400000000000000000000303041407013304700213200ustar00rootroot00000000000000/* * Copyright © 2013 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Thomas Voß */ #include #include #include #include #include #include #include #include #include #include "sig_term_catcher.h" #include "test_data.h" #include "test_service.h" #include #include #include #include #include namespace dbus = core::dbus; namespace { struct Service : public core::dbus::testing::Fixture { }; auto session_bus_config_file = core::dbus::testing::Fixture::default_session_bus_config_file() = core::testing::session_bus_configuration_file(); auto system_bus_config_file = core::dbus::testing::Fixture::default_system_bus_config_file() = core::testing::system_bus_configuration_file(); } TEST_F(Service, SignalDeliveryMultipleObjectsSameInterface) { core::testing::CrossProcessSync server_is_running; core::testing::CrossProcessSync client_has_setup_signals_and_connections; const int64_t expected_value = 42; auto service = [this, expected_value, &server_is_running, &client_has_setup_signals_and_connections]() { core::testing::SigTermCatcher sc; auto bus = session_bus(); bus->install_executor(core::dbus::asio::make_executor(bus)); auto service = dbus::Service::add_service(bus); auto foo1 = service->add_object_for_path(dbus::types::ObjectPath("/this/is/unlikely/to/exist/Service/Foo1")); auto foo2 = service->add_object_for_path(dbus::types::ObjectPath("/this/is/unlikely/to/exist/Service/Foo2")); std::thread t{[bus](){ bus->run(); }}; server_is_running.try_signal_ready_for(std::chrono::milliseconds{1000}); EXPECT_EQ(std::uint32_t(1), client_has_setup_signals_and_connections.wait_for_signal_ready_for( std::chrono::milliseconds{500})); foo1->emit_signal< test::Service::Interfaces::Foo::Signals::Dummy, test::Service::Interfaces::Foo::Signals::Dummy::ArgumentType > (1); foo2->emit_signal< test::Service::Interfaces::Foo::Signals::Dummy, test::Service::Interfaces::Foo::Signals::Dummy::ArgumentType > (2); sc.wait_for_signal(); bus->stop(); if (t.joinable()) t.join(); return ::testing::Test::HasFailure() ? core::posix::exit::Status::failure : core::posix::exit::Status::success; }; auto client = [this, expected_value, &server_is_running, &client_has_setup_signals_and_connections]() { auto bus = session_bus(); auto executor = core::dbus::asio::make_executor(bus); bus->install_executor(executor); std::thread t{[bus](){ bus->run(); }}; test::Service::Interfaces::Foo::Signals::Dummy::ArgumentType received1 = -1; test::Service::Interfaces::Foo::Signals::Dummy::ArgumentType received2 = -1; // server ready EXPECT_EQ(std::uint32_t(1), server_is_running.wait_for_signal_ready_for(std::chrono::milliseconds{500})); auto stub_service = dbus::Service::use_service(bus, dbus::traits::Service::interface_name()); auto foo1 = stub_service->object_for_path(dbus::types::ObjectPath("/this/is/unlikely/to/exist/Service/Foo1")); auto foo2 = stub_service->object_for_path(dbus::types::ObjectPath("/this/is/unlikely/to/exist/Service/Foo2")); auto foo1signal = foo1->get_signal(); auto foo2signal = foo2->get_signal(); foo1signal->connect([&received1](test::Service::Interfaces::Foo::Signals::Dummy::ArgumentType value) { received1 = value; }); foo2signal->connect([bus, &received2](test::Service::Interfaces::Foo::Signals::Dummy::ArgumentType value) { received2 = value; bus->stop(); }); // signals connected client_has_setup_signals_and_connections.try_signal_ready_for(std::chrono::milliseconds{500}); if (t.joinable()) t.join(); EXPECT_EQ(std::uint32_t(1), received1); EXPECT_EQ(std::uint32_t(2), received2); return ::testing::Test::HasFailure() ? core::posix::exit::Status::failure : core::posix::exit::Status::success; }; EXPECT_EQ(core::testing::ForkAndRunResult::empty, core::testing::fork_and_run(service, client)); } TEST_F(Service, SignalDeliverySameObjectSameInterfaceDifferentSignal) { core::testing::CrossProcessSync server_is_running; core::testing::CrossProcessSync client_has_setup_signals_and_connections; const int64_t expected_value = 42; auto service = [this, expected_value, &server_is_running, &client_has_setup_signals_and_connections]() { core::testing::SigTermCatcher sc; auto bus = session_bus(); bus->install_executor(core::dbus::asio::make_executor(bus)); auto service = dbus::Service::add_service(bus); auto foo1 = service->add_object_for_path(dbus::types::ObjectPath("/this/is/unlikely/to/exist/Service/Foo1")); std::thread t{[bus](){ bus->run(); }}; server_is_running.try_signal_ready_for(std::chrono::milliseconds{1000}); EXPECT_EQ(std::uint32_t(1), client_has_setup_signals_and_connections.wait_for_signal_ready_for( std::chrono::milliseconds{500})); foo1->emit_signal< test::Service::Interfaces::Foo::Signals::Dummy, test::Service::Interfaces::Foo::Signals::Dummy::ArgumentType > (1); // test emitting through Signal object auto bar = foo1->get_signal(); bar->emit(2); sc.wait_for_signal(); bus->stop(); if (t.joinable()) t.join(); return ::testing::Test::HasFailure() ? core::posix::exit::Status::failure : core::posix::exit::Status::success; }; auto client = [this, expected_value, &server_is_running, &client_has_setup_signals_and_connections]() { auto bus = session_bus(); auto executor = core::dbus::asio::make_executor(bus); bus->install_executor(executor); std::thread t{[bus](){ bus->run(); }}; test::Service::Interfaces::Foo::Signals::Dummy::ArgumentType received1 = -1; test::Service::Interfaces::Foo::Signals::Bar::ArgumentType received2 = -1; // server ready EXPECT_EQ(std::uint32_t(1), server_is_running.wait_for_signal_ready_for(std::chrono::milliseconds{500})); auto stub_service = dbus::Service::use_service(bus, dbus::traits::Service::interface_name()); auto foo1 = stub_service->object_for_path(dbus::types::ObjectPath("/this/is/unlikely/to/exist/Service/Foo1")); auto foo1signal = foo1->get_signal(); auto foo2signal = foo1->get_signal(); foo1signal->connect([&received1](test::Service::Interfaces::Foo::Signals::Dummy::ArgumentType value) { received1 = value; }); foo2signal->connect([bus, &received2](test::Service::Interfaces::Foo::Signals::Bar::ArgumentType value) { received2 = value; bus->stop(); }); // signals connected client_has_setup_signals_and_connections.try_signal_ready_for(std::chrono::milliseconds{500}); if (t.joinable()) t.join(); EXPECT_EQ(std::uint32_t(1), received1); EXPECT_EQ(std::uint32_t(2), received2); return ::testing::Test::HasFailure() ? core::posix::exit::Status::failure : core::posix::exit::Status::success; }; EXPECT_EQ(core::testing::ForkAndRunResult::empty, core::testing::fork_and_run(service, client)); } TEST_F(Service, SignalDeliverySameObjectSameInterfaceSameSignal) { core::testing::CrossProcessSync server_is_running; core::testing::CrossProcessSync client_has_setup_signals_and_connections; const int64_t expected_value = 42; auto service = [this, expected_value, &server_is_running, &client_has_setup_signals_and_connections]() { core::testing::SigTermCatcher sc; auto bus = session_bus(); bus->install_executor(core::dbus::asio::make_executor(bus)); auto service = dbus::Service::add_service(bus); auto foo1 = service->add_object_for_path(dbus::types::ObjectPath("/this/is/unlikely/to/exist/Service/Foo1")); std::thread t{[bus](){ bus->run(); }}; server_is_running.try_signal_ready_for(std::chrono::milliseconds{1000}); EXPECT_EQ(std::uint32_t(1), client_has_setup_signals_and_connections.wait_for_signal_ready_for( std::chrono::milliseconds{500})); foo1->emit_signal< test::Service::Interfaces::Foo::Signals::Dummy, test::Service::Interfaces::Foo::Signals::Dummy::ArgumentType > (1); foo1->emit_signal< test::Service::Interfaces::Foo::Signals::Dummy, test::Service::Interfaces::Foo::Signals::Dummy::ArgumentType > (2); sc.wait_for_signal(); bus->stop(); if (t.joinable()) t.join(); return ::testing::Test::HasFailure() ? core::posix::exit::Status::failure : core::posix::exit::Status::success; }; auto client = [this, expected_value, &server_is_running, &client_has_setup_signals_and_connections]() { auto bus = session_bus(); auto executor = core::dbus::asio::make_executor(bus); bus->install_executor(executor); std::thread t{[bus](){ bus->run(); }}; test::Service::Interfaces::Foo::Signals::Dummy::ArgumentType received1 = -1; test::Service::Interfaces::Foo::Signals::Dummy::ArgumentType received2 = -1; // server ready EXPECT_EQ(std::uint32_t(1), server_is_running.wait_for_signal_ready_for(std::chrono::milliseconds{500})); auto stub_service = dbus::Service::use_service(bus, dbus::traits::Service::interface_name()); auto foo1 = stub_service->object_for_path(dbus::types::ObjectPath("/this/is/unlikely/to/exist/Service/Foo1")); auto foo1signal = foo1->get_signal(); auto foo2signal = foo1->get_signal(); foo1signal->connect([&received1](test::Service::Interfaces::Foo::Signals::Dummy::ArgumentType value) { received1 = value; }); foo2signal->connect([bus, &received2](test::Service::Interfaces::Foo::Signals::Dummy::ArgumentType value) { received2 = value; if (received2 == 2) bus->stop(); }); // signals connected client_has_setup_signals_and_connections.try_signal_ready_for(std::chrono::milliseconds{500}); if (t.joinable()) t.join(); EXPECT_EQ(2u, received1); EXPECT_EQ(2u, received2); return ::testing::Test::HasFailure() ? core::posix::exit::Status::failure : core::posix::exit::Status::success; }; EXPECT_EQ(core::testing::ForkAndRunResult::empty, core::testing::fork_and_run(service, client)); } dbus-cpp-5.0.3/tests/stl_codec_test.cpp000066400000000000000000000057551407013304700201130ustar00rootroot00000000000000/* * Copyright © 2013 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Thomas Voß */ #include #include #include #include #include #include #include #include namespace dbus = core::dbus; namespace { std::shared_ptr a_method_call() { return dbus::Message::make_method_call( dbus::DBus::name(), dbus::DBus::path(), dbus::DBus::interface(), "ListNames"); } } TEST(CodecForTuple, encoding_of_tuples_works) { typedef std::tuple TupleType; auto msg = a_method_call(); auto writer = msg->writer(); TupleType t1(42, 42); core::dbus::Codec::encode_argument(writer, t1); EXPECT_EQ(msg->signature(), core::dbus::helper::TypeMapper::signature()); TupleType t2; auto reader = msg->reader(); core::dbus::Codec::decode_argument(reader, t2); EXPECT_EQ(std::get<0>(t1), std::get<0>(t2)); EXPECT_EQ(std::get<1>(t1), std::get<1>(t2)); } TEST(CodecForMaps, DictionaryMappingToVariantsIsEncodedAndDecodedCorrectly) { namespace dbus = core::dbus; auto msg = a_method_call(); { auto writer = msg->writer(); auto array = writer.open_array(dbus::types::Signature{"{sv}"}); for(unsigned int i = 0; i < 5; i++) { auto entry = array.open_dict_entry(); { auto key = std::to_string(i); entry.push_stringn(key.c_str(), key.size()); auto variant = entry.open_variant(dbus::types::Signature{dbus::helper::TypeMapper::signature()}); { variant.push_uint32(i); } entry.close_variant(std::move(variant)); } array.close_dict_entry(std::move(entry)); } writer.close_array(std::move(array)); } unsigned int counter = 0; std::map result; msg->reader() >> result; EXPECT_EQ(std::uint32_t(5), result.size()); for (const auto& element : result) { EXPECT_EQ(std::to_string(counter), element.first); EXPECT_EQ(counter, element.second.as()); counter++; } } dbus-cpp-5.0.3/tests/test_data.h.in000066400000000000000000000050631407013304700171270ustar00rootroot00000000000000/* * Copyright © 2013 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Thomas Voß */ #ifndef TEST_DATA_H_ #define TEST_DATA_H_ namespace core { namespace testing { const char* session_bus_configuration_file() { return "@CMAKE_SOURCE_DIR@/data/session.conf"; } const char* system_bus_configuration_file() { return "@CMAKE_SOURCE_DIR@/data/system.conf"; } namespace com { namespace canonical { const char* user_metrics_introspection_file() { return "@CMAKE_CURRENT_SOURCE_DIR@/data/com.canonical.UserMetrics.xml"; } const char* url_dispatcher_introspection_file() { return "@CMAKE_CURRENT_SOURCE_DIR@/data/com.canonical.URLDispatcher.xml"; } } } namespace org { namespace freedesktop { namespace modem_manager { namespace modem { constexpr const char* cdma_introspection_file() { return "@CMAKE_CURRENT_SOURCE_DIR@/data/org.freedesktop.ModemManager.Modem.Cdma.xml"; } constexpr const char* firmware_introspection_file() { return "@CMAKE_CURRENT_SOURCE_DIR@/data/org.freedesktop.ModemManager.Modem.Firmware.xml"; } namespace gsm { constexpr const char* card_introspection_file() { return "@CMAKE_CURRENT_SOURCE_DIR@/data/org.freedesktop.ModemManager.Modem.Gsm.Card.xml"; } constexpr const char* contact_introspection_file() { return "@CMAKE_CURRENT_SOURCE_DIR@/data/org.freedesktop.ModemManager.Modem.Gsm.Contacts.xml"; } constexpr const char* hso_introspection_file() { return "@CMAKE_CURRENT_SOURCE_DIR@/data/org.freedesktop.ModemManager.Modem.Gsm.Hso.xml"; } constexpr const char* network_introspection_file() { return "@CMAKE_CURRENT_SOURCE_DIR@/data/org.freedesktop.ModemManager.Modem.Gsm.Network.xml"; } constexpr const char* sms_introspection_file() { return "@CMAKE_CURRENT_SOURCE_DIR@/data/org.freedesktop.ModemManager.Modem.Gsm.SMS.xml"; } constexpr const char* ussd_introspection_file() { return "@CMAKE_CURRENT_SOURCE_DIR@/data/org.freedesktop.ModemManager.Modem.Gsm.Ussd.xml"; } } } } } } } } #endif // TEST_DATA_H_ dbus-cpp-5.0.3/tests/test_main.cpp000066400000000000000000000015161407013304700170670ustar00rootroot00000000000000/* * Copyright © 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Thomas Voß */ #include "SampleInterface.h> int main(int, char**) { std::cout << core::SampleInterface::introspect() << std::endl; return 0; } dbus-cpp-5.0.3/tests/test_service.h000066400000000000000000000065441407013304700172560ustar00rootroot00000000000000/* * Copyright © 2013 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Thomas Voß */ #ifndef TEST_SERVICE_H_ #define TEST_SERVICE_H_ namespace test { struct Service { struct Method { typedef Service Interface; inline static const std::string& name() { static const std::string s { "Method" }; return s; } inline static const std::chrono::milliseconds default_timeout() { return std::chrono::milliseconds{10}; } }; struct Signals { struct Dummy { inline static std::string name() { return "Dummy"; }; typedef Service Interface; typedef int64_t ArgumentType; }; }; struct Properties { struct Dummy { inline static std::string name() { return "Dummy"; }; typedef Service Interface; typedef double ValueType; static const bool readable = true; static const bool writable = true; }; struct ReadOnly { inline static std::string name() { return "ReadOnly"; }; typedef Service Interface; typedef std::uint32_t ValueType; static const bool readable = true; static const bool writable = false; }; }; struct Interfaces { struct Foo { static const std::string& name() { static const std::string s{"this.is.unlikely.to.exist.Service.Foo"}; return s; } struct Signals { struct Dummy { inline static std::string name() { return "Dummy"; } typedef Foo Interface; typedef int64_t ArgumentType; }; struct Bar { inline static std::string name() { return "Bar"; } typedef Foo Interface; typedef int64_t ArgumentType; }; }; }; }; }; } #include #include namespace core { namespace dbus { namespace traits { template<> struct Service { inline static const std::string& interface_name() { static const std::string s { "this.is.unlikely.to.exist.Service" }; return s; } }; } } } #endif // TEST_SERVICE_H_ dbus-cpp-5.0.3/tests/test_service_tiny.h000066400000000000000000000026471407013304700203210ustar00rootroot00000000000000/* * Copyright © 2013 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Thomas Voß */ #ifndef TEST_SERVICE_TINY_H_ #define TEST_SERVICE_TINY_H_ namespace test { struct ServiceTiny { struct Interfaces { struct Foo { static const std::string& name() { static const std::string s{"this.is.unlikely.to.exist.ServiceTiny.Foo"}; return s; } }; }; }; } #include namespace core { namespace dbus { namespace traits { template<> struct Service { inline static const std::string& interface_name() { static const std::string s { "this.is.unlikely.to.exist.ServiceTiny" }; return s; } }; } } } #endif // TEST_SERVICE_TINY_H_ dbus-cpp-5.0.3/tests/types_test.cpp000066400000000000000000000022341407013304700173050ustar00rootroot00000000000000/* * Copyright © 2013 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Thomas Voß */ #include #include TEST(ObjectPath, comparison_for_equality_yields_correct_result) { core::dbus::types::ObjectPath op1{"/does/not/exist"}; auto op2 = op1; EXPECT_TRUE(op2 == op1); } TEST(ObjectPath, comparison_for_inequality_yields_correct_result) { core::dbus::types::ObjectPath op1{"/does/not/exist"}; core::dbus::types::ObjectPath op2{"/does/not/exist/different"}; EXPECT_TRUE(op2 != op1); }