From: Johannes Schanda Date: Fri, 11 Jan 2013 09:41:12 +0000 (+0100) Subject: Initial import to Git X-Git-Tag: genivi_release_1~8 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=eee535b093d65dac23dd45f8d63f489027e742e9;p=profile%2Fivi%2Fcommon-api-dbus-runtime.git Initial import to Git --- eee535b093d65dac23dd45f8d63f489027e742e9 diff --git a/CommonAPI-DBus/AUTHORS b/CommonAPI-DBus/AUTHORS new file mode 100644 index 0000000..a0d3b96 --- /dev/null +++ b/CommonAPI-DBus/AUTHORS @@ -0,0 +1,4 @@ +BMW AG +Aleksandar Kanchev +Philip Rauwolf +Johannes Schanda diff --git a/CommonAPI-DBus/CommonAPI-DBus-uninstalled.pc.in b/CommonAPI-DBus/CommonAPI-DBus-uninstalled.pc.in new file mode 100644 index 0000000..4d522e6 --- /dev/null +++ b/CommonAPI-DBus/CommonAPI-DBus-uninstalled.pc.in @@ -0,0 +1,11 @@ +abs_top_builddir=@abs_top_builddir@ +abs_top_srcdir=@abs_top_srcdir@ +prefix= +exec_prefix= + +Name: Common API C++ D-Bus Middleware +Description: GENIVI Common API C++ D-Bus Middleware (uninstalled copy) +Version: @PACKAGE_VERSION@ +Requires: CommonAPI dbus-1 +Libs: ${abs_top_builddir}/libCommonAPI-DBus.la +Cflags: -I${abs_top_srcdir}/src \ No newline at end of file diff --git a/CommonAPI-DBus/CommonAPI-DBus.pc.in b/CommonAPI-DBus/CommonAPI-DBus.pc.in new file mode 100644 index 0000000..d59dfd4 --- /dev/null +++ b/CommonAPI-DBus/CommonAPI-DBus.pc.in @@ -0,0 +1,11 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: Common API C++ D-Bus Middleware +Description: GENIVI Common API C++ D-Bus Middleware +Version: @PACKAGE_VERSION@ +Requires: CommonAPI dbus-1 +Libs: -L${libdir} -lCommonAPI-DBus +Cflags: -I${includedir}/CommonAPI-@PACKAGE_VERSION@ \ No newline at end of file diff --git a/CommonAPI-DBus/LICENSE b/CommonAPI-DBus/LICENSE new file mode 100644 index 0000000..14e2f77 --- /dev/null +++ b/CommonAPI-DBus/LICENSE @@ -0,0 +1,373 @@ +Mozilla Public License Version 2.0 +================================== + +1. Definitions +-------------- + +1.1. "Contributor" + means each individual or legal entity that creates, contributes to + the creation of, or owns Covered Software. + +1.2. "Contributor Version" + means the combination of the Contributions of others (if any) used + by a Contributor and that particular Contributor's Contribution. + +1.3. "Contribution" + means Covered Software of a particular Contributor. + +1.4. "Covered Software" + means Source Code Form to which the initial Contributor has attached + the notice in Exhibit A, the Executable Form of such Source Code + Form, and Modifications of such Source Code Form, in each case + including portions thereof. + +1.5. "Incompatible With Secondary Licenses" + means + + (a) that the initial Contributor has attached the notice described + in Exhibit B to the Covered Software; or + + (b) that the Covered Software was made available under the terms of + version 1.1 or earlier of the License, but not also under the + terms of a Secondary License. + +1.6. "Executable Form" + means any form of the work other than Source Code Form. + +1.7. "Larger Work" + means a work that combines Covered Software with other material, in + a separate file or files, that is not Covered Software. + +1.8. "License" + means this document. + +1.9. "Licensable" + means having the right to grant, to the maximum extent possible, + whether at the time of the initial grant or subsequently, any and + all of the rights conveyed by this License. + +1.10. "Modifications" + means any of the following: + + (a) any file in Source Code Form that results from an addition to, + deletion from, or modification of the contents of Covered + Software; or + + (b) any new file in Source Code Form that contains any Covered + Software. + +1.11. "Patent Claims" of a Contributor + means any patent claim(s), including without limitation, method, + process, and apparatus claims, in any patent Licensable by such + Contributor that would be infringed, but for the grant of the + License, by the making, using, selling, offering for sale, having + made, import, or transfer of either its Contributions or its + Contributor Version. + +1.12. "Secondary License" + means either the GNU General Public License, Version 2.0, the GNU + Lesser General Public License, Version 2.1, the GNU Affero General + Public License, Version 3.0, or any later versions of those + licenses. + +1.13. "Source Code Form" + means the form of the work preferred for making modifications. + +1.14. "You" (or "Your") + means an individual or a legal entity exercising rights under this + License. For legal entities, "You" includes any entity that + controls, is controlled by, or is under common control with You. For + purposes of this definition, "control" means (a) the power, direct + or indirect, to cause the direction or management of such entity, + whether by contract or otherwise, or (b) ownership of more than + fifty percent (50%) of the outstanding shares or beneficial + ownership of such entity. + +2. License Grants and Conditions +-------------------------------- + +2.1. Grants + +Each Contributor hereby grants You a world-wide, royalty-free, +non-exclusive license: + +(a) under intellectual property rights (other than patent or trademark) + Licensable by such Contributor to use, reproduce, make available, + modify, display, perform, distribute, and otherwise exploit its + Contributions, either on an unmodified basis, with Modifications, or + as part of a Larger Work; and + +(b) under Patent Claims of such Contributor to make, use, sell, offer + for sale, have made, import, and otherwise transfer either its + Contributions or its Contributor Version. + +2.2. Effective Date + +The licenses granted in Section 2.1 with respect to any Contribution +become effective for each Contribution on the date the Contributor first +distributes such Contribution. + +2.3. Limitations on Grant Scope + +The licenses granted in this Section 2 are the only rights granted under +this License. No additional rights or licenses will be implied from the +distribution or licensing of Covered Software under this License. +Notwithstanding Section 2.1(b) above, no patent license is granted by a +Contributor: + +(a) for any code that a Contributor has removed from Covered Software; + or + +(b) for infringements caused by: (i) Your and any other third party's + modifications of Covered Software, or (ii) the combination of its + Contributions with other software (except as part of its Contributor + Version); or + +(c) under Patent Claims infringed by Covered Software in the absence of + its Contributions. + +This License does not grant any rights in the trademarks, service marks, +or logos of any Contributor (except as may be necessary to comply with +the notice requirements in Section 3.4). + +2.4. Subsequent Licenses + +No Contributor makes additional grants as a result of Your choice to +distribute the Covered Software under a subsequent version of this +License (see Section 10.2) or under the terms of a Secondary License (if +permitted under the terms of Section 3.3). + +2.5. Representation + +Each Contributor represents that the Contributor believes its +Contributions are its original creation(s) or it has sufficient rights +to grant the rights to its Contributions conveyed by this License. + +2.6. Fair Use + +This License is not intended to limit any rights You have under +applicable copyright doctrines of fair use, fair dealing, or other +equivalents. + +2.7. Conditions + +Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted +in Section 2.1. + +3. Responsibilities +------------------- + +3.1. Distribution of Source Form + +All distribution of Covered Software in Source Code Form, including any +Modifications that You create or to which You contribute, must be under +the terms of this License. You must inform recipients that the Source +Code Form of the Covered Software is governed by the terms of this +License, and how they can obtain a copy of this License. You may not +attempt to alter or restrict the recipients' rights in the Source Code +Form. + +3.2. Distribution of Executable Form + +If You distribute Covered Software in Executable Form then: + +(a) such Covered Software must also be made available in Source Code + Form, as described in Section 3.1, and You must inform recipients of + the Executable Form how they can obtain a copy of such Source Code + Form by reasonable means in a timely manner, at a charge no more + than the cost of distribution to the recipient; and + +(b) You may distribute such Executable Form under the terms of this + License, or sublicense it under different terms, provided that the + license for the Executable Form does not attempt to limit or alter + the recipients' rights in the Source Code Form under this License. + +3.3. Distribution of a Larger Work + +You may create and distribute a Larger Work under terms of Your choice, +provided that You also comply with the requirements of this License for +the Covered Software. If the Larger Work is a combination of Covered +Software with a work governed by one or more Secondary Licenses, and the +Covered Software is not Incompatible With Secondary Licenses, this +License permits You to additionally distribute such Covered Software +under the terms of such Secondary License(s), so that the recipient of +the Larger Work may, at their option, further distribute the Covered +Software under the terms of either this License or such Secondary +License(s). + +3.4. Notices + +You may not remove or alter the substance of any license notices +(including copyright notices, patent notices, disclaimers of warranty, +or limitations of liability) contained within the Source Code Form of +the Covered Software, except that You may alter any license notices to +the extent required to remedy known factual inaccuracies. + +3.5. Application of Additional Terms + +You may choose to offer, and to charge a fee for, warranty, support, +indemnity or liability obligations to one or more recipients of Covered +Software. However, You may do so only on Your own behalf, and not on +behalf of any Contributor. You must make it absolutely clear that any +such warranty, support, indemnity, or liability obligation is offered by +You alone, and You hereby agree to indemnify every Contributor for any +liability incurred by such Contributor as a result of warranty, support, +indemnity or liability terms You offer. You may include additional +disclaimers of warranty and limitations of liability specific to any +jurisdiction. + +4. Inability to Comply Due to Statute or Regulation +--------------------------------------------------- + +If it is impossible for You to comply with any of the terms of this +License with respect to some or all of the Covered Software due to +statute, judicial order, or regulation then You must: (a) comply with +the terms of this License to the maximum extent possible; and (b) +describe the limitations and the code they affect. Such description must +be placed in a text file included with all distributions of the Covered +Software under this License. Except to the extent prohibited by statute +or regulation, such description must be sufficiently detailed for a +recipient of ordinary skill to be able to understand it. + +5. Termination +-------------- + +5.1. The rights granted under this License will terminate automatically +if You fail to comply with any of its terms. However, if You become +compliant, then the rights granted under this License from a particular +Contributor are reinstated (a) provisionally, unless and until such +Contributor explicitly and finally terminates Your grants, and (b) on an +ongoing basis, if such Contributor fails to notify You of the +non-compliance by some reasonable means prior to 60 days after You have +come back into compliance. Moreover, Your grants from a particular +Contributor are reinstated on an ongoing basis if such Contributor +notifies You of the non-compliance by some reasonable means, this is the +first time You have received notice of non-compliance with this License +from such Contributor, and You become compliant prior to 30 days after +Your receipt of the notice. + +5.2. If You initiate litigation against any entity by asserting a patent +infringement claim (excluding declaratory judgment actions, +counter-claims, and cross-claims) alleging that a Contributor Version +directly or indirectly infringes any patent, then the rights granted to +You by any and all Contributors for the Covered Software under Section +2.1 of this License shall terminate. + +5.3. In the event of termination under Sections 5.1 or 5.2 above, all +end user license agreements (excluding distributors and resellers) which +have been validly granted by You or Your distributors under this License +prior to termination shall survive termination. + +************************************************************************ +* * +* 6. Disclaimer of Warranty * +* ------------------------- * +* * +* Covered Software is provided under this License on an "as is" * +* basis, without warranty of any kind, either expressed, implied, or * +* statutory, including, without limitation, warranties that the * +* Covered Software is free of defects, merchantable, fit for a * +* particular purpose or non-infringing. The entire risk as to the * +* quality and performance of the Covered Software is with You. * +* Should any Covered Software prove defective in any respect, You * +* (not any Contributor) assume the cost of any necessary servicing, * +* repair, or correction. This disclaimer of warranty constitutes an * +* essential part of this License. No use of any Covered Software is * +* authorized under this License except under this disclaimer. * +* * +************************************************************************ + +************************************************************************ +* * +* 7. Limitation of Liability * +* -------------------------- * +* * +* Under no circumstances and under no legal theory, whether tort * +* (including negligence), contract, or otherwise, shall any * +* Contributor, or anyone who distributes Covered Software as * +* permitted above, be liable to You for any direct, indirect, * +* special, incidental, or consequential damages of any character * +* including, without limitation, damages for lost profits, loss of * +* goodwill, work stoppage, computer failure or malfunction, or any * +* and all other commercial damages or losses, even if such party * +* shall have been informed of the possibility of such damages. This * +* limitation of liability shall not apply to liability for death or * +* personal injury resulting from such party's negligence to the * +* extent applicable law prohibits such limitation. Some * +* jurisdictions do not allow the exclusion or limitation of * +* incidental or consequential damages, so this exclusion and * +* limitation may not apply to You. * +* * +************************************************************************ + +8. Litigation +------------- + +Any litigation relating to this License may be brought only in the +courts of a jurisdiction where the defendant maintains its principal +place of business and such litigation shall be governed by laws of that +jurisdiction, without reference to its conflict-of-law provisions. +Nothing in this Section shall prevent a party's ability to bring +cross-claims or counter-claims. + +9. Miscellaneous +---------------- + +This License represents the complete agreement concerning the subject +matter hereof. If any provision of this License is held to be +unenforceable, such provision shall be reformed only to the extent +necessary to make it enforceable. Any law or regulation which provides +that the language of a contract shall be construed against the drafter +shall not be used to construe this License against a Contributor. + +10. Versions of the License +--------------------------- + +10.1. New Versions + +Mozilla Foundation is the license steward. Except as provided in Section +10.3, no one other than the license steward has the right to modify or +publish new versions of this License. Each version will be given a +distinguishing version number. + +10.2. Effect of New Versions + +You may distribute the Covered Software under the terms of the version +of the License under which You originally received the Covered Software, +or under the terms of any subsequent version published by the license +steward. + +10.3. Modified Versions + +If you create software not governed by this License, and you want to +create a new license for such software, you may create and use a +modified version of this License if you rename the license and remove +any references to the name of the license steward (except to note that +such modified license differs from this License). + +10.4. Distributing Source Code Form that is Incompatible With Secondary +Licenses + +If You choose to distribute Source Code Form that is Incompatible With +Secondary Licenses under the terms of this version of the License, the +notice described in Exhibit B of this License must be attached. + +Exhibit A - Source Code Form License Notice +------------------------------------------- + + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at http://mozilla.org/MPL/2.0/. + +If it is not possible or desirable to put the notice in a particular +file, then You may include the notice in a location (such as a LICENSE +file in a relevant directory) where a recipient would be likely to look +for such a notice. + +You may add additional accurate notices of copyright ownership. + +Exhibit B - "Incompatible With Secondary Licenses" Notice +--------------------------------------------------------- + + This Source Code Form is "Incompatible With Secondary Licenses", as + defined by the Mozilla Public License, v. 2.0. diff --git a/CommonAPI-DBus/Makefile.am b/CommonAPI-DBus/Makefile.am new file mode 100644 index 0000000..4fa9c6b --- /dev/null +++ b/CommonAPI-DBus/Makefile.am @@ -0,0 +1,183 @@ +ACLOCAL_AMFLAGS = -I m4 + +EXTRA_DIST = +MOSTLYCLEANFILES = + +AM_CPPFLAGS = \ + ${COMMONAPI_CFLAGS} \ + ${DBUS_CFLAGS} \ + -I$(top_srcdir)/src + +LDADD = \ + ${COMMONAPI_LIBS} \ + ${DBUS_LIBS} + +lib_LTLIBRARIES = +lib_LIBRARIES = + +# ------------------------------------------------------------------------------ +lib_LTLIBRARIES += libmurmurhash-internal.la + +libmurmurhash_internal_la_SOURCES = \ + src/murmurhash/MurmurHash3.h \ + src/murmurhash/MurmurHash3.cpp + +# ------------------------------------------------------------------------------ +lib_LTLIBRARIES += libCommonAPI-DBus.la + +libCommonAPI_DBus_la_SOURCES = \ + src/CommonAPI/DBus/DBusConnection.cpp \ + src/CommonAPI/DBus/DBusDaemonProxy.cpp \ + src/CommonAPI/DBus/DBusError.cpp \ + src/CommonAPI/DBus/DBusFunctionalHash.cpp \ + src/CommonAPI/DBus/DBusInputStream.cpp \ + src/CommonAPI/DBus/DBusMessage.cpp \ + src/CommonAPI/DBus/DBusObjectManager.cpp \ + src/CommonAPI/DBus/DBusOutputStream.cpp \ + src/CommonAPI/DBus/DBusProxy.cpp \ + src/CommonAPI/DBus/DBusFactory.cpp \ + src/CommonAPI/DBus/DBusRuntime.cpp \ + src/CommonAPI/DBus/DBusServiceRegistry.cpp \ + src/CommonAPI/DBus/DBusServiceStatusEvent.cpp \ + src/CommonAPI/DBus/DBusStubAdapter.cpp + +libCommonAPI_DBus_la_LIBADD = \ + libmurmurhash-internal.la \ + ${COMMONAPI_LIBS} + +CommonAPI_DBus_includedir=$(includedir)/CommonAPI-${VERSION}/CommonAPI/DBus +CommonAPI_DBus_include_HEADERS = \ + src/CommonAPI/DBus/DBusAttribute.h \ + src/CommonAPI/DBus/DBusConnection.h \ + src/CommonAPI/DBus/DBusDaemonProxy.h \ + src/CommonAPI/DBus/DBusError.h \ + src/CommonAPI/DBus/DBusEvent.h \ + src/CommonAPI/DBus/DBusFunctionalHash.h \ + src/CommonAPI/DBus/DBusHelper.h \ + src/CommonAPI/DBus/DBusInputStream.h \ + src/CommonAPI/DBus/DBusMessage.h \ + src/CommonAPI/DBus/DBusMultiEvent.h \ + src/CommonAPI/DBus/DBusObjectManager.h \ + src/CommonAPI/DBus/DBusOutputStream.h \ + src/CommonAPI/DBus/DBusProxy.h \ + src/CommonAPI/DBus/DBusProxyAsyncCallbackHandler.h \ + src/CommonAPI/DBus/DBusProxyConnection.h \ + src/CommonAPI/DBus/DBusFactory.h \ + src/CommonAPI/DBus/DBusProxyHelper.h \ + src/CommonAPI/DBus/DBusRuntime.h \ + src/CommonAPI/DBus/DBusSerializableArguments.h \ + src/CommonAPI/DBus/DBusServiceRegistry.h \ + src/CommonAPI/DBus/DBusServiceStatusEvent.h \ + src/CommonAPI/DBus/DBusStubAdapter.h \ + src/CommonAPI/DBus/DBusStubAdapterHelper.h \ + src/CommonAPI/DBus/DBusUtils.h + +pkgconfigdir = ${libdir}/pkgconfig +pkgconfig_DATA = CommonAPI-DBus.pc + +# ------------------------------------------------------------------------------ +if ENABLE_TESTS + +TestInterfaceSources = \ + src/test/commonapi/tests/DerivedTypeCollection.cpp \ + src/test/commonapi/tests/TestInterfaceDBusProxy.cpp \ + src/test/commonapi/tests/TestInterfaceDBusStubAdapter.cpp \ + src/test/commonapi/tests/TestInterfaceStubDefault.cpp + +check_PROGRAMS = \ + DBusCommunicationTest \ + DBusMultipleConnectionTest \ + DBusDaemonProxyTest \ + DBusInputStreamTest \ + DBusOutputStreamTest \ + DBusRuntimeTest \ + DBusFactoryTest \ + DBusProxyTest \ + DBusVariantTest \ + DBusBenchmarkingTest + +TESTS = ${check_PROGRAMS} + +DBusBenchmarkingTest_SOURCES = src/test/DBusBenchmarkingTest.cpp +DBusBenchmarkingTest_CPPFLAGS = ${AM_CPPFLAGS} ${GTEST_CPPFLAGS} +DBusBenchmarkingTest_CXXFLAGS = ${GTEST_CXXFLAGS} +DBusBenchmarkingTest_LDADD = ${LDADD} ${GTEST_LIBS} libCommonAPI-DBus.la + +DBusCommunicationTest_SOURCES = \ + src/test/DBusCommunicationTest.cpp \ + ${TestInterfaceSources} +DBusCommunicationTest_CPPFLAGS = ${AM_CPPFLAGS} ${GTEST_CPPFLAGS} +DBusCommunicationTest_CXXFLAGS = ${GTEST_CXXFLAGS} +DBusCommunicationTest_LDADD = ${LDADD} ${GTEST_LIBS} libCommonAPI-DBus.la + +DBusDaemonProxyTest_SOURCES = src/test/DBusDaemonProxyTest.cpp +DBusDaemonProxyTest_CPPFLAGS = ${AM_CPPFLAGS} ${GTEST_CPPFLAGS} +DBusDaemonProxyTest_CXXFLAGS = ${GTEST_CXXFLAGS} +DBusDaemonProxyTest_LDADD = ${LDADD} ${GTEST_LIBS} libCommonAPI-DBus.la + +DBusInputStreamTest_SOURCES = src/test/DBusInputStreamTest.cpp +DBusInputStreamTest_CPPFLAGS = ${AM_CPPFLAGS} ${GTEST_CPPFLAGS} +DBusInputStreamTest_CXXFLAGS = ${GTEST_CXXFLAGS} +DBusInputStreamTest_LDADD = ${LDADD} ${GTEST_LIBS} libCommonAPI-DBus.la + +DBusOutputStreamTest_SOURCES = src/test/DBusOutputStreamTest.cpp +DBusOutputStreamTest_CPPFLAGS = ${AM_CPPFLAGS} ${GTEST_CPPFLAGS} +DBusOutputStreamTest_CXXFLAGS = ${GTEST_CXXFLAGS} +DBusOutputStreamTest_LDADD = ${LDADD} ${GTEST_LIBS} libCommonAPI-DBus.la + +DBusFactoryTest_SOURCES = \ + src/test/DBusFactoryTest.cpp \ + ${TestInterfaceSources} +DBusFactoryTest_CPPFLAGS = ${AM_CPPFLAGS} ${GTEST_CPPFLAGS} +DBusFactoryTest_CXXFLAGS = ${GTEST_CXXFLAGS} +DBusFactoryTest_LDADD = ${LDADD} ${GTEST_LIBS} libCommonAPI-DBus.la + +DBusRuntimeTest_SOURCES = src/test/DBusRuntimeTest.cpp +DBusRuntimeTest_CPPFLAGS = ${AM_CPPFLAGS} ${GTEST_CPPFLAGS} +DBusRuntimeTest_CXXFLAGS = ${GTEST_CXXFLAGS} +DBusRuntimeTest_LDADD = ${LDADD} ${GTEST_LIBS} libCommonAPI-DBus.la + +#DBusStubAdapterTest_SOURCES = src/test/DBusStubAdapterTest.cpp +#DBusStubAdapterTest_CPPFLAGS = ${AM_CPPFLAGS} ${GTEST_CPPFLAGS} +#DBusStubAdapterTest_CXXFLAGS = ${GTEST_CXXFLAGS} +#DBusStubAdapterTest_LDADD = ${LDADD} ${GTEST_LIBS} libCommonAPI-DBus.la + +DBusMultipleConnectionTest_SOURCES = src/test/DBusMultipleConnectionTest.cpp \ + ${TestInterfaceSources} +DBusMultipleConnectionTest_CPPFLAGS = ${AM_CPPFLAGS} ${GTEST_CPPFLAGS} +DBusMultipleConnectionTest_CXXFLAGS = ${GTEST_CXXFLAGS} +DBusMultipleConnectionTest_LDADD = ${LDADD} ${GTEST_LIBS} libCommonAPI-DBus.la + +DBusProxyTest_SOURCES = src/test/DBusProxyTest.cpp +DBusProxyTest_CPPFLAGS = ${AM_CPPFLAGS} ${GTEST_CPPFLAGS} +DBusProxyTest_CXXFLAGS = ${GTEST_CXXFLAGS} +DBusProxyTest_LDADD = ${LDADD} ${GTEST_LIBS} libCommonAPI-DBus.la + +DBusVariantTest_SOURCES = src/test/DBusVariantTest.cpp +DBusVariantTest_CPPFLAGS = ${AM_CPPFLAGS} ${GTEST_CPPFLAGS} +DBusVariantTest_CXXFLAGS = ${GTEST_CXXFLAGS} +DBusVariantTest_LDADD = ${LDADD} ${GTEST_LIBS} libCommonAPI-DBus.la + +endif + + +# ------------------------------------------------------------------------------ +# Doxygen +include $(top_srcdir)/aminclude.am +EXTRA_DIST += doxygen.cfg +MOSTLYCLEANFILES += ${DX_CLEANFILES} + +# ------------------------------------------------------------------------------ +MAINTAINERCLEANFILES = \ + Makefile.in \ + aclocal.m4 \ + configure + +clean-local: + -rm -rf src-gen + +maintainer-clean-local: + -rm -rf build-aux + -rm -f config.h.in* + -rm -f m4/libtool*.m4 + -rm -f m4/lt*.m4 diff --git a/CommonAPI-DBus/TODO b/CommonAPI-DBus/TODO new file mode 100644 index 0000000..d1331ca --- /dev/null +++ b/CommonAPI-DBus/TODO @@ -0,0 +1,84 @@ +* Move Version checking to the ServiceRegistry: + Currently, ensuring the interface-version based compatibility of the local proxy and + a given remote service would be done asynchronously within the proxy right after its creation. + The check should be moved to the service registry, so that a proxy only needs to ask + for the locally cached version information of the remote service. + According to the current CommonAPI Spec, it is required that a proxy remains "unavailable" when + it's counterpart has an incompatible interface version. + Feasibility of and alternatives to this approach remain to be determined. + +* Performance: + Check especially message dispatching! Is it possible to do the dispatching without copying + the interface name and object path strings? + Check (de)serialization, improve where possible. + +* Implementation of Variants. + +* Dedicated Test of multiple connect/disconnect cycles + +* Life Cycle of connections: Disconnect/Destroy with ProxyFactory, how to do this otherwise? + +* DBusProxyHelper.h: + // TODO: Must implement available checks on method calls, and wait for valid avalable status in sync case + /* + * XXX DBusProxy declares a private DBusReadonlyAttribute variable, which + * cuases a circular dependency. As a workaround the DBusProxy must be + * forward declared and set as default parameter to the template attribute + * classes. + * + * Since DBus*Attribute use the DBusProxyHelper, we have to use the + * DBusProxy class as a template typename. + */ + +* DBusMultiEvent.h: + /* + * XXX DBusProxy declares a private DBusReadonlyAttribute variable, which + * cuases a circular dependency. As a workaround the DBusProxy must be + * forward declared and set as default parameter to the template attribute + * classes. + * + * Since DBus*Attribute use the DBusProxyHelper, we have to use the + * DBusProxy class as a template typename. + */ + //TODO: if rehashing occurs, then all iterators are invalidated. + //TODO: rework with pointers, since this is D-Bus only + typedef typename ListenersMap::iterator Subscription; + +* DBusAttribute.h: + /* + * XXX DBusProxy declares a private DBusReadonlyAttribute variable, which + * causes a circular dependency. As a workaround the DBusProxy must be + * forward declared and set as default parameter to the template attribute + * classes. + */ + +* DBusServiceRegistry.h: + isServiceInstanceAlive: //TODO Fallback for services not in dbus object manager + +* DBus Generator: implizite Array-Deklaration via "[]" (z.B. UInt32[] in Methoden-Aufruf) unterstützen! + + + + +Future development (2.1): + +* Request Name for DBusStubAdapter: + The D-Bus specification states that a single D-Bus connection might own multiple names. + We have to make sure that when a register request comes from the CommonAPI StubAdapter + Factory that we make sure that the name is already owned by our DBusConnection. + Probably we'll have to keep a list of all owned names and request a new one on registration + if required. + +* Check static/dynamic loading of libraries, make it work. + +* Doxygen in CommonAPI source code. + +* Main Loop Integration + - Per Factory or on Runtime level? + - Which functions are needed? + - Example with Glib on CommonAPI base (not D-Bus specific) + - Christian Linke has some ideas + +- Handling of D-Bus properties!! Sollte auf Franca attributes gemapped sein (Grund: Interoperabilität) + +* getValue on attributes is inconsisten with other methods, CallStatus should be in signature not return \ No newline at end of file diff --git a/CommonAPI-DBus/aminclude.am b/CommonAPI-DBus/aminclude.am new file mode 100644 index 0000000..7dfed8d --- /dev/null +++ b/CommonAPI-DBus/aminclude.am @@ -0,0 +1,168 @@ +# Copyright (c) 2009 Oren Ben-Kiki +# +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice +# and this notice are preserved. This file is offered as-is, without any +# warranty. +# +# =========================================================================== +# http://www.gnu.org/software/autoconf-archive/ax_prog_doxygen.html +# =========================================================================== +# + +## --------------------------------- ## +## Format-independent Doxygen rules. ## +## --------------------------------- ## + +if DX_COND_doc + +## ------------------------------- ## +## Rules specific for HTML output. ## +## ------------------------------- ## + +if DX_COND_html + +DX_CLEAN_HTML = @DX_DOCDIR@/html + +endif # DX_COND_html + +## ------------------------------ ## +## Rules specific for CHM output. ## +## ------------------------------ ## + +if DX_COND_chm + +DX_CLEAN_CHM = @DX_DOCDIR@/chm + +if DX_COND_chi + +DX_CLEAN_CHI = @DX_DOCDIR@/@PACKAGE@.chi + +endif # DX_COND_chi + +endif # DX_COND_chm + +## ------------------------------ ## +## Rules specific for MAN output. ## +## ------------------------------ ## + +if DX_COND_man + +DX_CLEAN_MAN = @DX_DOCDIR@/man + +endif # DX_COND_man + +## ------------------------------ ## +## Rules specific for RTF output. ## +## ------------------------------ ## + +if DX_COND_rtf + +DX_CLEAN_RTF = @DX_DOCDIR@/rtf + +endif # DX_COND_rtf + +## ------------------------------ ## +## Rules specific for XML output. ## +## ------------------------------ ## + +if DX_COND_xml + +DX_CLEAN_XML = @DX_DOCDIR@/xml + +endif # DX_COND_xml + +## ----------------------------- ## +## Rules specific for PS output. ## +## ----------------------------- ## + +if DX_COND_ps + +DX_CLEAN_PS = @DX_DOCDIR@/@PACKAGE@.ps + +DX_PS_GOAL = doxygen-ps + +doxygen-ps: @DX_DOCDIR@/@PACKAGE@.ps + +@DX_DOCDIR@/@PACKAGE@.ps: @DX_DOCDIR@/@PACKAGE@.tag + cd @DX_DOCDIR@/latex; \ + rm -f *.aux *.toc *.idx *.ind *.ilg *.log *.out; \ + $(DX_LATEX) refman.tex; \ + $(MAKEINDEX_PATH) refman.idx; \ + $(DX_LATEX) refman.tex; \ + countdown=5; \ + while $(DX_EGREP) 'Rerun (LaTeX|to get cross-references right)' \ + refman.log > /dev/null 2>&1 \ + && test $$countdown -gt 0; do \ + $(DX_LATEX) refman.tex; \ + countdown=`expr $$countdown - 1`; \ + done; \ + $(DX_DVIPS) -o ../@PACKAGE@.ps refman.dvi + +endif # DX_COND_ps + +## ------------------------------ ## +## Rules specific for PDF output. ## +## ------------------------------ ## + +if DX_COND_pdf + +DX_CLEAN_PDF = @DX_DOCDIR@/@PACKAGE@.pdf + +DX_PDF_GOAL = doxygen-pdf + +doxygen-pdf: @DX_DOCDIR@/@PACKAGE@.pdf + +@DX_DOCDIR@/@PACKAGE@.pdf: @DX_DOCDIR@/@PACKAGE@.tag + cd @DX_DOCDIR@/latex; \ + rm -f *.aux *.toc *.idx *.ind *.ilg *.log *.out; \ + $(DX_PDFLATEX) refman.tex; \ + $(DX_MAKEINDEX) refman.idx; \ + $(DX_PDFLATEX) refman.tex; \ + countdown=5; \ + while $(DX_EGREP) 'Rerun (LaTeX|to get cross-references right)' \ + refman.log > /dev/null 2>&1 \ + && test $$countdown -gt 0; do \ + $(DX_PDFLATEX) refman.tex; \ + countdown=`expr $$countdown - 1`; \ + done; \ + mv refman.pdf ../@PACKAGE@.pdf + +endif # DX_COND_pdf + +## ------------------------------------------------- ## +## Rules specific for LaTeX (shared for PS and PDF). ## +## ------------------------------------------------- ## + +if DX_COND_latex + +DX_CLEAN_LATEX = @DX_DOCDIR@/latex + +endif # DX_COND_latex + +.PHONY: doxygen-run doxygen-doc $(DX_PS_GOAL) $(DX_PDF_GOAL) + +.INTERMEDIATE: doxygen-run $(DX_PS_GOAL) $(DX_PDF_GOAL) + +doxygen-run: @DX_DOCDIR@/@PACKAGE@.tag + +doxygen-doc: doxygen-run $(DX_PS_GOAL) $(DX_PDF_GOAL) + +@DX_DOCDIR@/@PACKAGE@.tag: $(DX_CONFIG) $(pkginclude_HEADERS) + rm -rf @DX_DOCDIR@ + $(DX_ENV) $(DX_DOXYGEN) $(srcdir)/$(DX_CONFIG) + +DX_CLEANFILES = \ + @DX_DOCDIR@/@PACKAGE@.tag \ + -r \ + $(DX_CLEAN_HTML) \ + $(DX_CLEAN_CHM) \ + $(DX_CLEAN_CHI) \ + $(DX_CLEAN_MAN) \ + $(DX_CLEAN_RTF) \ + $(DX_CLEAN_XML) \ + $(DX_CLEAN_PS) \ + $(DX_CLEAN_PDF) \ + $(DX_CLEAN_LATEX) + +endif # DX_COND_doc \ No newline at end of file diff --git a/CommonAPI-DBus/configure.ac b/CommonAPI-DBus/configure.ac new file mode 100644 index 0000000..e09f244 --- /dev/null +++ b/CommonAPI-DBus/configure.ac @@ -0,0 +1,97 @@ +AC_PREREQ(2.61) +AC_INIT([GENIVI Common API DBus C++ Library], + [0.7], + [], + [CommonAPI-DBus]) + +AC_CONFIG_MACRO_DIR([m4]) +AC_CONFIG_AUX_DIR([build-aux]) +AC_CONFIG_HEADERS([build-aux/config.h]) +AC_CONFIG_FILES([ + Makefile + CommonAPI-DBus.pc + CommonAPI-DBus-uninstalled.pc]) + +AC_CANONICAL_SYSTEM + +AM_INIT_AUTOMAKE([foreign 1.11 silent-rules subdir-objects color-tests -Wall -Werror]) +AM_SILENT_RULES +AM_MAINTAINER_MODE + +AC_PROG_CXX +AC_LANG([C++]) +AX_CXX_COMPILE_STDCXX_11([noext]) + +AC_ARG_VAR([GTEST_CONFIG], [The exact path of Google Test's 'gtest-config' script.]) + +LT_PREREQ(2.2) +LT_INIT + +PKG_PROG_PKG_CONFIG +PKG_CHECK_MODULES(COMMONAPI, [CommonAPI >= 0.7]) +PKG_CHECK_MODULES(DBUS, [dbus-1 >= 1.4.6]) + +GTEST_MIN_VERSION="1.6.0" +GTEST_URL="http://code.google.com/p/googletest" + + +AC_ARG_VAR([GTEST_CONFIG], [The exact path of Google Test's 'gtest-config' script.]) +AC_ARG_VAR([GTEST_CPPFLAGS], [C-like preprocessor flags for Google Test.]) +AC_ARG_VAR([GTEST_CXXFLAGS], [C++ compile flags for Google Test.]) +AC_ARG_VAR([GTEST_LDFLAGS], [Linker path and option flags for Google Test.]) +AC_ARG_VAR([GTEST_LIBS], [Library linking flags for Google Test.]) +AC_ARG_VAR([GTEST_VERSION], [The available version of Google Test.]) + +AS_IF([test -f "${GTEST_CONFIG}"], + [AS_IF([${GTEST_CONFIG} --min-version=${GTEST_MIN_VERSION}], + [], + [AC_MSG_ERROR([dnl + Found Google Test Version ${GTEST_VERSION}. However ${GTEST_MIN_VERSION} is + required. Please refer to ${GTEST_URL} for a more recent version.])]) + [GTEST_CPPFLAGS=`${GTEST_CONFIG} --cppflags`] + [GTEST_CXXFLAGS=`${GTEST_CONFIG} --cxxflags`] + [GTEST_LDFLAGS=`${GTEST_CONFIG} --ldflags`] + [GTEST_LIBS=`${GTEST_CONFIG} --libs`] + [GTEST_VERSION=`${GTEST_CONFIG} --version`] + ] + [] +) + +AM_CONDITIONAL(ENABLE_TESTS, [test -f "${GTEST_CONFIG}"]) + + +# Doxygen support +DX_HTML_FEATURE(ON) +DX_CHM_FEATURE(OFF) +DX_CHI_FEATURE(OFF) +DX_MAN_FEATURE(OFF) +DX_RTF_FEATURE(OFF) +DX_XML_FEATURE(OFF) +DX_PDF_FEATURE(OFF) +DX_PS_FEATURE(OFF) +DX_INIT_DOXYGEN(${PACKAGE_NAME}, doxygen.cfg, doc) + +AC_MSG_RESULT([ + $PACKAGE_NAME v$VERSION + + enable docs: ${ENABLE_DOCS} + + COMMONAPI_CFLAGS: ${COMMONAPI_CFLAGS} + COMMONAPI_LIBS: ${COMMONAPI_LIBS} + + DBUS_CFLAGS: ${DBUS_CFLAGS} + DBUS_LIBS: ${DBUS_LIBS} + + GTEST_CONFIG: ${GTEST_CONFIG} + GTEST_CPPFLAGS: ${GTEST_CPPFLAGS} + GTEST_CXXFLAGS: ${GTEST_CXXFLAGS} + GTEST_LDFLAGS: ${GTEST_LDFLAGS} + GTEST_LIBS: ${GTEST_LIBS} + GTEST_VERSION: ${GTEST_VERSION} + + prefix: ${prefix} + CXXFLAGS: ${CXXFLAGS} + LDFLAGS: ${LDFLAGS} +]) + +AC_OUTPUT \ No newline at end of file diff --git a/CommonAPI-DBus/dbus-DBusMessage-add-support-for-custom-marshaling.patch b/CommonAPI-DBus/dbus-DBusMessage-add-support-for-custom-marshaling.patch new file mode 100644 index 0000000..5f225f3 --- /dev/null +++ b/CommonAPI-DBus/dbus-DBusMessage-add-support-for-custom-marshaling.patch @@ -0,0 +1,267 @@ +From 467a2e307462b02865b35397c572b6048c2934e2 Mon Sep 17 00:00:00 2001 +From: Aleksandar Kanchev +Date: Mon, 9 Jul 2012 18:09:04 +0200 +Subject: [PATCH] DBusMessage: add support for custom marshaling + +Add functions to support querying and manipulating the message body and +signature. This is useful for code generators, which can generate custom +marshaling functions based on a given IDL. Those functions tend to be +optimized and faster than the generic iterator based marshaling. +--- + dbus/dbus-message.c | 143 +++++++++++++++++++++++++++++++++++---------------- + dbus/dbus-message.h | 13 +++++ + dbus/dbus-string.c | 16 ++++++ + dbus/dbus-string.h | 4 ++ + 4 files changed, 132 insertions(+), 44 deletions(-) + +diff --git a/dbus/dbus-message.c b/dbus/dbus-message.c +index 24ef5ac..fbacfba 100644 +--- a/dbus/dbus-message.c ++++ b/dbus/dbus-message.c +@@ -356,50 +356,6 @@ set_or_delete_string_field (DBusMessage *message, + &value); + } + +-#if 0 +-/* Probably we don't need to use this */ +-/** +- * Sets the signature of the message, i.e. the arguments in the +- * message payload. The signature includes only "in" arguments for +- * #DBUS_MESSAGE_TYPE_METHOD_CALL and only "out" arguments for +- * #DBUS_MESSAGE_TYPE_METHOD_RETURN, so is slightly different from +- * what you might expect (it does not include the signature of the +- * entire C++-style method). +- * +- * The signature is a string made up of type codes such as +- * #DBUS_TYPE_INT32. The string is terminated with nul (nul is also +- * the value of #DBUS_TYPE_INVALID). The macros such as +- * #DBUS_TYPE_INT32 evaluate to integers; to assemble a signature you +- * may find it useful to use the string forms, such as +- * #DBUS_TYPE_INT32_AS_STRING. +- * +- * An "unset" or #NULL signature is considered the same as an empty +- * signature. In fact dbus_message_get_signature() will never return +- * #NULL. +- * +- * @param message the message +- * @param signature the type signature or #NULL to unset +- * @returns #FALSE if no memory +- */ +-static dbus_bool_t +-_dbus_message_set_signature (DBusMessage *message, +- const char *signature) +-{ +- _dbus_return_val_if_fail (message != NULL, FALSE); +- _dbus_return_val_if_fail (!message->locked, FALSE); +- _dbus_return_val_if_fail (signature == NULL || +- _dbus_check_is_valid_signature (signature)); +- /* can't delete the signature if you have a message body */ +- _dbus_return_val_if_fail (_dbus_string_get_length (&message->body) == 0 || +- signature != NULL); +- +- return set_or_delete_string_field (message, +- DBUS_HEADER_FIELD_SIGNATURE, +- DBUS_TYPE_SIGNATURE, +- signature); +-} +-#endif +- + /* Message Cache + * + * We cache some DBusMessage to reduce the overhead of allocating +@@ -3370,6 +3326,47 @@ dbus_message_get_sender (DBusMessage *message) + } + + /** ++ * Sets the signature of the message, i.e. the arguments in the ++ * message payload. The signature includes only "in" arguments for ++ * #DBUS_MESSAGE_TYPE_METHOD_CALL and only "out" arguments for ++ * #DBUS_MESSAGE_TYPE_METHOD_RETURN, so is slightly different from ++ * what you might expect (it does not include the signature of the ++ * entire C++-style method). ++ * ++ * The signature is a string made up of type codes such as ++ * #DBUS_TYPE_INT32. The string is terminated with nul (nul is also ++ * the value of #DBUS_TYPE_INVALID). The macros such as ++ * #DBUS_TYPE_INT32 evaluate to integers; to assemble a signature you ++ * may find it useful to use the string forms, such as ++ * #DBUS_TYPE_INT32_AS_STRING. ++ * ++ * An "unset" or #NULL signature is considered the same as an empty ++ * signature. In fact dbus_message_get_signature() will never return ++ * #NULL. ++ * ++ * @param message the message ++ * @param signature the type signature or #NULL to unset ++ * @returns #FALSE if no memory ++ */ ++dbus_bool_t ++dbus_message_set_signature (DBusMessage *message, ++ const char *signature) ++{ ++ _dbus_return_val_if_fail (message != NULL, FALSE); ++ _dbus_return_val_if_fail (!message->locked, FALSE); ++ _dbus_return_val_if_fail (signature == NULL || ++ _dbus_check_is_valid_signature (signature), FALSE); ++ /* can't delete the signature if you have a message body */ ++ _dbus_return_val_if_fail (_dbus_string_get_length (&message->body) == 0 || ++ signature != NULL, FALSE); ++ ++ return set_or_delete_string_field (message, ++ DBUS_HEADER_FIELD_SIGNATURE, ++ DBUS_TYPE_SIGNATURE, ++ signature); ++} ++ ++/** + * Gets the type signature of the message, i.e. the arguments in the + * message payload. The signature includes only "in" arguments for + * #DBUS_MESSAGE_TYPE_METHOD_CALL and only "out" arguments for +@@ -4519,6 +4516,64 @@ dbus_message_type_to_string (int type) + } + + /** ++ * Returns pointer to the buffer used to store the message body. ++ * ++ * @param message the message ++ * @return pointer to the message body memory ++ */ ++char* ++dbus_message_get_body (DBusMessage *message) { ++ _dbus_return_val_if_fail (message != NULL, NULL); ++ ++ return _dbus_string_get_data(&(message->body)); ++} ++ ++/** ++ * Adjust the length of the message body buffer. The memory will be reallocated ++ * if the new length is bigger than the already allocated size. ++ * ++ * @see dbus_message_get_body_allocated ++ * @param message the message ++ * @param length the new length of the body ++ * @return #TRUE if successful ++ */ ++dbus_bool_t ++dbus_message_set_body_length (DBusMessage *message, ++ int length) { ++ _dbus_return_val_if_fail (message != NULL, FALSE); ++ _dbus_return_val_if_fail (length >= 0, FALSE); ++ ++ return _dbus_string_set_length(&(message->body), length); ++} ++ ++/** ++ * Gets the length of the message body buffer. ++ * ++ * @param message the message ++ * @param length the new length of the body ++ * @return the length of the body buffer ++ */ ++int ++dbus_message_get_body_length (DBusMessage *message) { ++ _dbus_return_val_if_fail (message != NULL, 0); ++ ++ return _dbus_string_get_length(&(message->body)); ++} ++ ++/** ++ * Gets the allocated memory size used to hold the message body. ++ * ++ * @param message the message ++ * @return size of the allocated message body memory ++ */ ++int ++dbus_message_get_body_allocated (DBusMessage *message) { ++ _dbus_return_val_if_fail (message != NULL, 0); ++ ++ return _dbus_string_get_allocated(&(message->body)); ++} ++ ++/** + * Turn a DBusMessage into the marshalled form as described in the D-Bus + * specification. + * +diff --git a/dbus/dbus-message.h b/dbus/dbus-message.h +index 5500492..55388ac 100644 +--- a/dbus/dbus-message.h ++++ b/dbus/dbus-message.h +@@ -138,6 +138,9 @@ dbus_bool_t dbus_message_set_sender (DBusMessage *message, + DBUS_EXPORT + const char* dbus_message_get_sender (DBusMessage *message); + DBUS_EXPORT ++dbus_bool_t dbus_message_set_signature (DBusMessage *message, ++ const char *signature); ++DBUS_EXPORT + const char* dbus_message_get_signature (DBusMessage *message); + DBUS_EXPORT + void dbus_message_set_no_reply (DBusMessage *message, +@@ -264,6 +267,16 @@ void dbus_message_iter_abandon_container (DBusMessageIter *iter, + DBusMessageIter *sub); + + DBUS_EXPORT ++char* dbus_message_get_body (DBusMessage *message); ++DBUS_EXPORT ++dbus_bool_t dbus_message_set_body_length (DBusMessage *message, ++ int length); ++DBUS_EXPORT ++int dbus_message_get_body_length (DBusMessage *message); ++DBUS_EXPORT ++int dbus_message_get_body_allocated (DBusMessage *message); ++ ++DBUS_EXPORT + void dbus_message_lock (DBusMessage *message); + + DBUS_EXPORT +diff --git a/dbus/dbus-string.c b/dbus/dbus-string.c +index e2eb93b..d8628ba 100644 +--- a/dbus/dbus-string.c ++++ b/dbus/dbus-string.c +@@ -848,6 +848,22 @@ _dbus_string_get_length (const DBusString *str) + } + #endif /* !_dbus_string_get_length */ + ++/* Only have the function if we don't have the macro */ ++#ifndef _dbus_string_get_allocated ++/** ++ * Gets the allocated length of a string (not including nul termination). ++ * ++ * @returns the allocated length. ++ */ ++int ++_dbus_string_get_allocated(const DBusString *str) ++{ ++ DBUS_CONST_STRING_PREAMBLE (str); ++ ++ return real->allocated; ++} ++#endif /* !_dbus_string_get_allocated */ ++ + /** + * Makes a string longer by the given number of bytes. Checks whether + * adding additional_length to the current length would overflow an +diff --git a/dbus/dbus-string.h b/dbus/dbus-string.h +index 2f1ed31..490aea6 100644 +--- a/dbus/dbus-string.h ++++ b/dbus/dbus-string.h +@@ -62,6 +62,7 @@ struct DBusString + */ + #define _dbus_string_get_data(s) ((char*)(((DBusString*)(s))->dummy1)) + #define _dbus_string_get_length(s) (((DBusString*)(s))->dummy2) ++#define _dbus_string_get_allocated(s) (((DBusString*)(s))->dummy3 - _DBUS_STRING_ALLOCATION_PADDING) + #define _dbus_string_set_byte(s, i, b) ((((unsigned char*)(((DBusString*)(s))->dummy1))[(i)]) = (unsigned char) (b)) + #define _dbus_string_get_byte(s, i) (((const unsigned char*)(((DBusString*)(s))->dummy1))[(i)]) + #define _dbus_string_get_const_data(s) ((const char*)(((DBusString*)(s))->dummy1)) +@@ -131,6 +132,9 @@ void _dbus_string_copy_to_buffer_with_nul (const DBusString *str, + #ifndef _dbus_string_get_length + int _dbus_string_get_length (const DBusString *str); + #endif /* !_dbus_string_get_length */ ++#ifndef _dbus_string_get_allocated ++int _dbus_string_get_allocated (const DBusString *str); ++#endif /* !_dbus_string_get_allocated */ + + dbus_bool_t _dbus_string_lengthen (DBusString *str, + int additional_length); +-- +1.7.10.2 + diff --git a/CommonAPI-DBus/dbus-DBusMessage-disable-data-validation.patch b/CommonAPI-DBus/dbus-DBusMessage-disable-data-validation.patch new file mode 100644 index 0000000..4983900 --- /dev/null +++ b/CommonAPI-DBus/dbus-DBusMessage-disable-data-validation.patch @@ -0,0 +1,25 @@ +From 762a0ceb1ff6b4c69eced23902fbc404870f21ca Mon Sep 17 00:00:00 2001 +From: Philip Rauwolf +Date: Fri, 3 Aug 2012 16:34:59 +0200 +Subject: [PATCH] Disabled all data checks in DBUS + +--- + dbus/dbus-message.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/dbus/dbus-message.c b/dbus/dbus-message.c +index 5e570bd..9883e70 100644 +--- a/dbus/dbus-message.c ++++ b/dbus/dbus-message.c +@@ -3960,7 +3960,7 @@ load_message (DBusMessageLoader *loader, + DBusValidationMode mode; + dbus_uint32_t n_unix_fds = 0; + +- mode = DBUS_VALIDATION_MODE_DATA_IS_UNTRUSTED; ++ mode = DBUS_VALIDATION_MODE_WE_TRUST_THIS_DATA_ABSOLUTELY; + + oom = FALSE; + +-- +1.7.10.4 + diff --git a/CommonAPI-DBus/doxygen.cfg b/CommonAPI-DBus/doxygen.cfg new file mode 100644 index 0000000..ec60bb2 --- /dev/null +++ b/CommonAPI-DBus/doxygen.cfg @@ -0,0 +1,1794 @@ +# Doxyfile 1.8.1.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 = $(PROJECT)-$(VERSION) + +# 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 = + +# 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 = + +# 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 = $(DOCDIR) + +# 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 = YES + +# 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. + +STRIP_FROM_PATH = $(SRCDIR) + +# 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 = YES + +# 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 = YES + +# 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 + +# 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 = NO + +# 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 = YES + +# 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 = YES + +# 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 sectionname ... \endif. + +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 = 0 + +# 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. + +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 = YES + +# 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 = $(SRCDIR) + +# 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 = + +# 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 = NO + +# 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 = + +#--------------------------------------------------------------------------- +# 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 = $(GENERATE_HTML) + +# 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 the tag is left blank doxygen +# will generate a default style sheet. Note that doxygen will try to copy +# the style sheet file to the HTML output directory, so don't put your own +# style sheet in the HTML output directory as well, or it will be erased! + +HTML_STYLESHEET = + +# 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 = NO + +# 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 = NO + +# 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 = $(GENERATE_HTMLHELP) + +# 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 = ../$(PROJECT).chm + +# 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 = $(HHC_PATH) + +# 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 = $(GENERATE_CHI) + +# 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 = YES + +# 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 = NO + +# 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 = 4 + +# 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 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 PHP enabled web server instead of at the web client +# using Javascript. Doxygen will generate the search PHP script and index +# file to put on the web server. The advantage of the server +# based approach is that it scales better to large projects and allows +# full text search. The disadvantages are that it is more difficult to setup +# and does not have live searching capabilities. + +SERVER_BASED_SEARCH = NO + +#--------------------------------------------------------------------------- +# 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 = $(GENERATE_LATEX) + +# 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 = + +# 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 = + +# 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 = YES + +# 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 = $(PAPER_SIZE) + +# 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 = NO + +# 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 = $(GENERATE_PDF) + +# 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 = YES + +# 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 = $(GENERATE_RTF) + +# 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 = YES + +# 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 = $(GENERATE_MAN) + +# 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 = $(GENERATE_XML) + +# 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 = YES + +# 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 = YES + +# 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 = _DOXYGEN + +# 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 = EASY_TYPE \ + EASY_DESTRUCTOR \ + EASY_METHOD + +# 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 = $(DOCDIR)/$(PROJECT).tag + +# 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/false + +#--------------------------------------------------------------------------- +# 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 = YES + +# 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 = $(HAVE_DOT) + +# 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 = NO + +# 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 = YES + +# 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 = NO + +# 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 = NO + +# 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 = $(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 = NO + +# 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 = NO + +# 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 diff --git a/CommonAPI-DBus/eclipse-code-style-formatter.xml b/CommonAPI-DBus/eclipse-code-style-formatter.xml new file mode 100644 index 0000000..8be3b29 --- /dev/null +++ b/CommonAPI-DBus/eclipse-code-style-formatter.xml @@ -0,0 +1,166 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/CommonAPI-DBus/m4/ax_cxx_compile_stdcxx_11.m4 b/CommonAPI-DBus/m4/ax_cxx_compile_stdcxx_11.m4 new file mode 100644 index 0000000..0d96c07 --- /dev/null +++ b/CommonAPI-DBus/m4/ax_cxx_compile_stdcxx_11.m4 @@ -0,0 +1,107 @@ +# ============================================================================ +# http://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx_11.html +# ============================================================================ +# +# SYNOPSIS +# +# AX_CXX_COMPILE_STDCXX_11([ext|noext]) +# +# DESCRIPTION +# +# Check for baseline language coverage in the compiler for the C++11 +# standard; if necessary, add switches to CXXFLAGS to enable support. +# Errors out if no mode that supports C++11 baseline syntax can be found. +# The argument, if specified, indicates whether you insist on an extended +# mode (e.g. -std=gnu++11) or a strict conformance mode (e.g. -std=c++11). +# If neither is specified, you get whatever works, with preference for an +# extended mode. +# +# LICENSE +# +# Copyright (c) 2008 Benjamin Kosnik +# Copyright (c) 2012 Zack Weinberg +# +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice +# and this notice are preserved. This file is offered as-is, without any +# warranty. + +#serial 1 + +m4_define([_AX_CXX_COMPILE_STDCXX_11_testbody], [ + template + struct check + { + static_assert(sizeof(int) <= sizeof(T), "not big enough"); + }; + + typedef check> right_angle_brackets; + + int a; + decltype(a) b; + + typedef check check_type; + check_type c; + check_type&& cr = static_cast(c); +]) + +AC_DEFUN([AX_CXX_COMPILE_STDCXX_11], [dnl + m4_if([$1], [], [], + [$1], [ext], [], + [$1], [noext], [], + [m4_fatal([invalid argument `$1' to AX_CXX_COMPILE_STDCXX_11])])dnl + AC_LANG_ASSERT([C++])dnl + ac_success=no + AC_CACHE_CHECK(whether $CXX supports C++11 features by default, + ax_cv_cxx_compile_cxx11, + [AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_11_testbody])], + [ax_cv_cxx_compile_cxx11=yes], + [ax_cv_cxx_compile_cxx11=no])]) + if test x$ax_cv_cxx_compile_cxx11 = xyes; then + ac_success=yes + fi + + m4_if([$1], [noext], [], [dnl + if test x$ac_success = xno; then + for switch in -std=gnu++11 -std=gnu++0x; do + cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx11_$switch]) + AC_CACHE_CHECK(whether $CXX supports C++11 features with $switch, + $cachevar, + [ac_save_CXXFLAGS="$CXXFLAGS" + CXXFLAGS="$CXXFLAGS $switch" + AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_11_testbody])], + [eval $cachevar=yes], + [eval $cachevar=no]) + CXXFLAGS="$ac_save_CXXFLAGS"]) + if eval test x\$$cachevar = xyes; then + CXXFLAGS="$CXXFLAGS $switch" + ac_success=yes + break + fi + done + fi]) + + m4_if([$1], [ext], [], [dnl + if test x$ac_success = xno; then + for switch in -std=c++11 -std=c++0x; do + cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx11_$switch]) + AC_CACHE_CHECK(whether $CXX supports C++11 features with $switch, + $cachevar, + [ac_save_CXXFLAGS="$CXXFLAGS" + CXXFLAGS="$CXXFLAGS $switch" + AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_11_testbody])], + [eval $cachevar=yes], + [eval $cachevar=no]) + CXXFLAGS="$ac_save_CXXFLAGS"]) + if eval test x\$$cachevar = xyes; then + CXXFLAGS="$CXXFLAGS $switch" + ac_success=yes + break + fi + done + fi]) + + if test x$ac_success = xno; then + AC_MSG_ERROR([*** A compiler with support for C++11 language features is required.]) + fi +]) diff --git a/CommonAPI-DBus/m4/ax_prog_doxygen.m4 b/CommonAPI-DBus/m4/ax_prog_doxygen.m4 new file mode 100644 index 0000000..44b22b0 --- /dev/null +++ b/CommonAPI-DBus/m4/ax_prog_doxygen.m4 @@ -0,0 +1,532 @@ +# =========================================================================== +# http://www.gnu.org/software/autoconf-archive/ax_prog_doxygen.html +# =========================================================================== +# +# SYNOPSIS +# +# DX_INIT_DOXYGEN(PROJECT-NAME, DOXYFILE-PATH, [OUTPUT-DIR]) +# DX_DOXYGEN_FEATURE(ON|OFF) +# DX_DOT_FEATURE(ON|OFF) +# DX_HTML_FEATURE(ON|OFF) +# DX_CHM_FEATURE(ON|OFF) +# DX_CHI_FEATURE(ON|OFF) +# DX_MAN_FEATURE(ON|OFF) +# DX_RTF_FEATURE(ON|OFF) +# DX_XML_FEATURE(ON|OFF) +# DX_PDF_FEATURE(ON|OFF) +# DX_PS_FEATURE(ON|OFF) +# +# DESCRIPTION +# +# The DX_*_FEATURE macros control the default setting for the given +# Doxygen feature. Supported features are 'DOXYGEN' itself, 'DOT' for +# generating graphics, 'HTML' for plain HTML, 'CHM' for compressed HTML +# help (for MS users), 'CHI' for generating a seperate .chi file by the +# .chm file, and 'MAN', 'RTF', 'XML', 'PDF' and 'PS' for the appropriate +# output formats. The environment variable DOXYGEN_PAPER_SIZE may be +# specified to override the default 'a4wide' paper size. +# +# By default, HTML, PDF and PS documentation is generated as this seems to +# be the most popular and portable combination. MAN pages created by +# Doxygen are usually problematic, though by picking an appropriate subset +# and doing some massaging they might be better than nothing. CHM and RTF +# are specific for MS (note that you can't generate both HTML and CHM at +# the same time). The XML is rather useless unless you apply specialized +# post-processing to it. +# +# The macros mainly control the default state of the feature. The use can +# override the default by specifying --enable or --disable. The macros +# ensure that contradictory flags are not given (e.g., +# --enable-doxygen-html and --enable-doxygen-chm, +# --enable-doxygen-anything with --disable-doxygen, etc.) Finally, each +# feature will be automatically disabled (with a warning) if the required +# programs are missing. +# +# Once all the feature defaults have been specified, call DX_INIT_DOXYGEN +# with the following parameters: a one-word name for the project for use +# as a filename base etc., an optional configuration file name (the +# default is 'Doxyfile', the same as Doxygen's default), and an optional +# output directory name (the default is 'doxygen-doc'). +# +# Automake Support +# +# The following is a template aminclude.am file for use with Automake. +# Make targets and variables values are controlled by the various +# DX_COND_* conditionals set by autoconf. +# +# The provided targets are: +# +# doxygen-doc: Generate all doxygen documentation. +# +# doxygen-run: Run doxygen, which will generate some of the +# documentation (HTML, CHM, CHI, MAN, RTF, XML) +# but will not do the post processing required +# for the rest of it (PS, PDF, and some MAN). +# +# doxygen-man: Rename some doxygen generated man pages. +# +# doxygen-ps: Generate doxygen PostScript documentation. +# +# doxygen-pdf: Generate doxygen PDF documentation. +# +# Note that by default these are not integrated into the automake targets. +# If doxygen is used to generate man pages, you can achieve this +# integration by setting man3_MANS to the list of man pages generated and +# then adding the dependency: +# +# $(man3_MANS): doxygen-doc +# +# This will cause make to run doxygen and generate all the documentation. +# +# The following variable is intended for use in Makefile.am: +# +# DX_CLEANFILES = everything to clean. +# +# Then add this variable to MOSTLYCLEANFILES. +# +# ----- begin aminclude.am ------------------------------------- +# +# ## --------------------------------- ## +# ## Format-independent Doxygen rules. ## +# ## --------------------------------- ## +# +# if DX_COND_doc +# +# ## ------------------------------- ## +# ## Rules specific for HTML output. ## +# ## ------------------------------- ## +# +# if DX_COND_html +# +# DX_CLEAN_HTML = @DX_DOCDIR@/html +# +# endif DX_COND_html +# +# ## ------------------------------ ## +# ## Rules specific for CHM output. ## +# ## ------------------------------ ## +# +# if DX_COND_chm +# +# DX_CLEAN_CHM = @DX_DOCDIR@/chm +# +# if DX_COND_chi +# +# DX_CLEAN_CHI = @DX_DOCDIR@/@PACKAGE@.chi +# +# endif DX_COND_chi +# +# endif DX_COND_chm +# +# ## ------------------------------ ## +# ## Rules specific for MAN output. ## +# ## ------------------------------ ## +# +# if DX_COND_man +# +# DX_CLEAN_MAN = @DX_DOCDIR@/man +# +# endif DX_COND_man +# +# ## ------------------------------ ## +# ## Rules specific for RTF output. ## +# ## ------------------------------ ## +# +# if DX_COND_rtf +# +# DX_CLEAN_RTF = @DX_DOCDIR@/rtf +# +# endif DX_COND_rtf +# +# ## ------------------------------ ## +# ## Rules specific for XML output. ## +# ## ------------------------------ ## +# +# if DX_COND_xml +# +# DX_CLEAN_XML = @DX_DOCDIR@/xml +# +# endif DX_COND_xml +# +# ## ----------------------------- ## +# ## Rules specific for PS output. ## +# ## ----------------------------- ## +# +# if DX_COND_ps +# +# DX_CLEAN_PS = @DX_DOCDIR@/@PACKAGE@.ps +# +# DX_PS_GOAL = doxygen-ps +# +# doxygen-ps: @DX_DOCDIR@/@PACKAGE@.ps +# +# @DX_DOCDIR@/@PACKAGE@.ps: @DX_DOCDIR@/@PACKAGE@.tag +# cd @DX_DOCDIR@/latex; \ +# rm -f *.aux *.toc *.idx *.ind *.ilg *.log *.out; \ +# $(DX_LATEX) refman.tex; \ +# $(MAKEINDEX_PATH) refman.idx; \ +# $(DX_LATEX) refman.tex; \ +# countdown=5; \ +# while $(DX_EGREP) 'Rerun (LaTeX|to get cross-references right)' \ +# refman.log > /dev/null 2>&1 \ +# && test $$countdown -gt 0; do \ +# $(DX_LATEX) refman.tex; \ +# countdown=`expr $$countdown - 1`; \ +# done; \ +# $(DX_DVIPS) -o ../@PACKAGE@.ps refman.dvi +# +# endif DX_COND_ps +# +# ## ------------------------------ ## +# ## Rules specific for PDF output. ## +# ## ------------------------------ ## +# +# if DX_COND_pdf +# +# DX_CLEAN_PDF = @DX_DOCDIR@/@PACKAGE@.pdf +# +# DX_PDF_GOAL = doxygen-pdf +# +# doxygen-pdf: @DX_DOCDIR@/@PACKAGE@.pdf +# +# @DX_DOCDIR@/@PACKAGE@.pdf: @DX_DOCDIR@/@PACKAGE@.tag +# cd @DX_DOCDIR@/latex; \ +# rm -f *.aux *.toc *.idx *.ind *.ilg *.log *.out; \ +# $(DX_PDFLATEX) refman.tex; \ +# $(DX_MAKEINDEX) refman.idx; \ +# $(DX_PDFLATEX) refman.tex; \ +# countdown=5; \ +# while $(DX_EGREP) 'Rerun (LaTeX|to get cross-references right)' \ +# refman.log > /dev/null 2>&1 \ +# && test $$countdown -gt 0; do \ +# $(DX_PDFLATEX) refman.tex; \ +# countdown=`expr $$countdown - 1`; \ +# done; \ +# mv refman.pdf ../@PACKAGE@.pdf +# +# endif DX_COND_pdf +# +# ## ------------------------------------------------- ## +# ## Rules specific for LaTeX (shared for PS and PDF). ## +# ## ------------------------------------------------- ## +# +# if DX_COND_latex +# +# DX_CLEAN_LATEX = @DX_DOCDIR@/latex +# +# endif DX_COND_latex +# +# .PHONY: doxygen-run doxygen-doc $(DX_PS_GOAL) $(DX_PDF_GOAL) +# +# .INTERMEDIATE: doxygen-run $(DX_PS_GOAL) $(DX_PDF_GOAL) +# +# doxygen-run: @DX_DOCDIR@/@PACKAGE@.tag +# +# doxygen-doc: doxygen-run $(DX_PS_GOAL) $(DX_PDF_GOAL) +# +# @DX_DOCDIR@/@PACKAGE@.tag: $(DX_CONFIG) $(pkginclude_HEADERS) +# rm -rf @DX_DOCDIR@ +# $(DX_ENV) $(DX_DOXYGEN) $(srcdir)/$(DX_CONFIG) +# +# DX_CLEANFILES = \ +# @DX_DOCDIR@/@PACKAGE@.tag \ +# -r \ +# $(DX_CLEAN_HTML) \ +# $(DX_CLEAN_CHM) \ +# $(DX_CLEAN_CHI) \ +# $(DX_CLEAN_MAN) \ +# $(DX_CLEAN_RTF) \ +# $(DX_CLEAN_XML) \ +# $(DX_CLEAN_PS) \ +# $(DX_CLEAN_PDF) \ +# $(DX_CLEAN_LATEX) +# +# endif DX_COND_doc +# +# ----- end aminclude.am --------------------------------------- +# +# LICENSE +# +# Copyright (c) 2009 Oren Ben-Kiki +# +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice +# and this notice are preserved. This file is offered as-is, without any +# warranty. + +#serial 12 + +## ----------## +## Defaults. ## +## ----------## + +DX_ENV="" +AC_DEFUN([DX_FEATURE_doc], ON) +AC_DEFUN([DX_FEATURE_dot], OFF) +AC_DEFUN([DX_FEATURE_man], OFF) +AC_DEFUN([DX_FEATURE_html], ON) +AC_DEFUN([DX_FEATURE_chm], OFF) +AC_DEFUN([DX_FEATURE_chi], OFF) +AC_DEFUN([DX_FEATURE_rtf], OFF) +AC_DEFUN([DX_FEATURE_xml], OFF) +AC_DEFUN([DX_FEATURE_pdf], ON) +AC_DEFUN([DX_FEATURE_ps], ON) + +## --------------- ## +## Private macros. ## +## --------------- ## + +# DX_ENV_APPEND(VARIABLE, VALUE) +# ------------------------------ +# Append VARIABLE="VALUE" to DX_ENV for invoking doxygen. +AC_DEFUN([DX_ENV_APPEND], [AC_SUBST([DX_ENV], ["$DX_ENV $1='$2'"])]) + +# DX_DIRNAME_EXPR +# --------------- +# Expand into a shell expression prints the directory part of a path. +AC_DEFUN([DX_DIRNAME_EXPR], + [[expr ".$1" : '\(\.\)[^/]*$' \| "x$1" : 'x\(.*\)/[^/]*$']]) + +# DX_IF_FEATURE(FEATURE, IF-ON, IF-OFF) +# ------------------------------------- +# Expands according to the M4 (static) status of the feature. +AC_DEFUN([DX_IF_FEATURE], [ifelse(DX_FEATURE_$1, ON, [$2], [$3])]) + +# DX_REQUIRE_PROG(VARIABLE, PROGRAM) +# ---------------------------------- +# Require the specified program to be found for the DX_CURRENT_FEATURE to work. +AC_DEFUN([DX_REQUIRE_PROG], [ +AC_PATH_TOOL([$1], [$2]) +if test "$DX_FLAG_[]DX_CURRENT_FEATURE$$1" = 1; then + AC_MSG_WARN([$2 not found - will not DX_CURRENT_DESCRIPTION]) + AC_SUBST(DX_FLAG_[]DX_CURRENT_FEATURE, 0) +fi +]) + +# DX_TEST_FEATURE(FEATURE) +# ------------------------ +# Expand to a shell expression testing whether the feature is active. +AC_DEFUN([DX_TEST_FEATURE], [test "$DX_FLAG_$1" = 1]) + +# DX_CHECK_DEPEND(REQUIRED_FEATURE, REQUIRED_STATE) +# ------------------------------------------------- +# Verify that a required features has the right state before trying to turn on +# the DX_CURRENT_FEATURE. +AC_DEFUN([DX_CHECK_DEPEND], [ +test "$DX_FLAG_$1" = "$2" \ +|| AC_MSG_ERROR([doxygen-DX_CURRENT_FEATURE ifelse([$2], 1, + requires, contradicts) doxygen-DX_CURRENT_FEATURE]) +]) + +# DX_CLEAR_DEPEND(FEATURE, REQUIRED_FEATURE, REQUIRED_STATE) +# ---------------------------------------------------------- +# Turn off the DX_CURRENT_FEATURE if the required feature is off. +AC_DEFUN([DX_CLEAR_DEPEND], [ +test "$DX_FLAG_$1" = "$2" || AC_SUBST(DX_FLAG_[]DX_CURRENT_FEATURE, 0) +]) + +# DX_FEATURE_ARG(FEATURE, DESCRIPTION, +# CHECK_DEPEND, CLEAR_DEPEND, +# REQUIRE, DO-IF-ON, DO-IF-OFF) +# -------------------------------------------- +# Parse the command-line option controlling a feature. CHECK_DEPEND is called +# if the user explicitly turns the feature on (and invokes DX_CHECK_DEPEND), +# otherwise CLEAR_DEPEND is called to turn off the default state if a required +# feature is disabled (using DX_CLEAR_DEPEND). REQUIRE performs additional +# requirement tests (DX_REQUIRE_PROG). Finally, an automake flag is set and +# DO-IF-ON or DO-IF-OFF are called according to the final state of the feature. +AC_DEFUN([DX_ARG_ABLE], [ + AC_DEFUN([DX_CURRENT_FEATURE], [$1]) + AC_DEFUN([DX_CURRENT_DESCRIPTION], [$2]) + AC_ARG_ENABLE(doxygen-$1, + [AS_HELP_STRING(DX_IF_FEATURE([$1], [--disable-doxygen-$1], + [--enable-doxygen-$1]), + DX_IF_FEATURE([$1], [don't $2], [$2]))], + [ +case "$enableval" in +#( +y|Y|yes|Yes|YES) + AC_SUBST([DX_FLAG_$1], 1) + $3 +;; #( +n|N|no|No|NO) + AC_SUBST([DX_FLAG_$1], 0) +;; #( +*) + AC_MSG_ERROR([invalid value '$enableval' given to doxygen-$1]) +;; +esac +], [ +AC_SUBST([DX_FLAG_$1], [DX_IF_FEATURE([$1], 1, 0)]) +$4 +]) +if DX_TEST_FEATURE([$1]); then + $5 + : +fi +AM_CONDITIONAL(DX_COND_$1, DX_TEST_FEATURE([$1])) +if DX_TEST_FEATURE([$1]); then + $6 + : +else + $7 + : +fi +]) + +## -------------- ## +## Public macros. ## +## -------------- ## + +# DX_XXX_FEATURE(DEFAULT_STATE) +# ----------------------------- +AC_DEFUN([DX_DOXYGEN_FEATURE], [AC_DEFUN([DX_FEATURE_doc], [$1])]) +AC_DEFUN([DX_DOT_FEATURE], [AC_DEFUN([DX_FEATURE_dot], [$1])]) +AC_DEFUN([DX_MAN_FEATURE], [AC_DEFUN([DX_FEATURE_man], [$1])]) +AC_DEFUN([DX_HTML_FEATURE], [AC_DEFUN([DX_FEATURE_html], [$1])]) +AC_DEFUN([DX_CHM_FEATURE], [AC_DEFUN([DX_FEATURE_chm], [$1])]) +AC_DEFUN([DX_CHI_FEATURE], [AC_DEFUN([DX_FEATURE_chi], [$1])]) +AC_DEFUN([DX_RTF_FEATURE], [AC_DEFUN([DX_FEATURE_rtf], [$1])]) +AC_DEFUN([DX_XML_FEATURE], [AC_DEFUN([DX_FEATURE_xml], [$1])]) +AC_DEFUN([DX_XML_FEATURE], [AC_DEFUN([DX_FEATURE_xml], [$1])]) +AC_DEFUN([DX_PDF_FEATURE], [AC_DEFUN([DX_FEATURE_pdf], [$1])]) +AC_DEFUN([DX_PS_FEATURE], [AC_DEFUN([DX_FEATURE_ps], [$1])]) + +# DX_INIT_DOXYGEN(PROJECT, [CONFIG-FILE], [OUTPUT-DOC-DIR]) +# --------------------------------------------------------- +# PROJECT also serves as the base name for the documentation files. +# The default CONFIG-FILE is "Doxyfile" and OUTPUT-DOC-DIR is "doxygen-doc". +AC_DEFUN([DX_INIT_DOXYGEN], [ + +# Files: +AC_SUBST([DX_PROJECT], [$1]) +AC_SUBST([DX_CONFIG], [ifelse([$2], [], Doxyfile, [$2])]) +AC_SUBST([DX_DOCDIR], [ifelse([$3], [], doxygen-doc, [$3])]) + +# Environment variables used inside doxygen.cfg: +DX_ENV_APPEND(SRCDIR, $srcdir) +DX_ENV_APPEND(PROJECT, $DX_PROJECT) +DX_ENV_APPEND(DOCDIR, $DX_DOCDIR) +DX_ENV_APPEND(VERSION, $PACKAGE_VERSION) + +# Doxygen itself: +DX_ARG_ABLE(doc, [generate any doxygen documentation], + [], + [], + [DX_REQUIRE_PROG([DX_DOXYGEN], doxygen) + DX_REQUIRE_PROG([DX_PERL], perl)], + [DX_ENV_APPEND(PERL_PATH, $DX_PERL)]) + +# Dot for graphics: +DX_ARG_ABLE(dot, [generate graphics for doxygen documentation], + [DX_CHECK_DEPEND(doc, 1)], + [DX_CLEAR_DEPEND(doc, 1)], + [DX_REQUIRE_PROG([DX_DOT], dot)], + [DX_ENV_APPEND(HAVE_DOT, YES) + DX_ENV_APPEND(DOT_PATH, [`DX_DIRNAME_EXPR($DX_DOT)`])], + [DX_ENV_APPEND(HAVE_DOT, NO)]) + +# Man pages generation: +DX_ARG_ABLE(man, [generate doxygen manual pages], + [DX_CHECK_DEPEND(doc, 1)], + [DX_CLEAR_DEPEND(doc, 1)], + [], + [DX_ENV_APPEND(GENERATE_MAN, YES)], + [DX_ENV_APPEND(GENERATE_MAN, NO)]) + +# RTF file generation: +DX_ARG_ABLE(rtf, [generate doxygen RTF documentation], + [DX_CHECK_DEPEND(doc, 1)], + [DX_CLEAR_DEPEND(doc, 1)], + [], + [DX_ENV_APPEND(GENERATE_RTF, YES)], + [DX_ENV_APPEND(GENERATE_RTF, NO)]) + +# XML file generation: +DX_ARG_ABLE(xml, [generate doxygen XML documentation], + [DX_CHECK_DEPEND(doc, 1)], + [DX_CLEAR_DEPEND(doc, 1)], + [], + [DX_ENV_APPEND(GENERATE_XML, YES)], + [DX_ENV_APPEND(GENERATE_XML, NO)]) + +# (Compressed) HTML help generation: +DX_ARG_ABLE(chm, [generate doxygen compressed HTML help documentation], + [DX_CHECK_DEPEND(doc, 1)], + [DX_CLEAR_DEPEND(doc, 1)], + [DX_REQUIRE_PROG([DX_HHC], hhc)], + [DX_ENV_APPEND(HHC_PATH, $DX_HHC) + DX_ENV_APPEND(GENERATE_HTML, YES) + DX_ENV_APPEND(GENERATE_HTMLHELP, YES)], + [DX_ENV_APPEND(GENERATE_HTMLHELP, NO)]) + +# Seperate CHI file generation. +DX_ARG_ABLE(chi, [generate doxygen seperate compressed HTML help index file], + [DX_CHECK_DEPEND(chm, 1)], + [DX_CLEAR_DEPEND(chm, 1)], + [], + [DX_ENV_APPEND(GENERATE_CHI, YES)], + [DX_ENV_APPEND(GENERATE_CHI, NO)]) + +# Plain HTML pages generation: +DX_ARG_ABLE(html, [generate doxygen plain HTML documentation], + [DX_CHECK_DEPEND(doc, 1) DX_CHECK_DEPEND(chm, 0)], + [DX_CLEAR_DEPEND(doc, 1) DX_CLEAR_DEPEND(chm, 0)], + [], + [DX_ENV_APPEND(GENERATE_HTML, YES)], + [DX_TEST_FEATURE(chm) || DX_ENV_APPEND(GENERATE_HTML, NO)]) + +# PostScript file generation: +DX_ARG_ABLE(ps, [generate doxygen PostScript documentation], + [DX_CHECK_DEPEND(doc, 1)], + [DX_CLEAR_DEPEND(doc, 1)], + [DX_REQUIRE_PROG([DX_LATEX], latex) + DX_REQUIRE_PROG([DX_MAKEINDEX], makeindex) + DX_REQUIRE_PROG([DX_DVIPS], dvips) + DX_REQUIRE_PROG([DX_EGREP], egrep)]) + +# PDF file generation: +DX_ARG_ABLE(pdf, [generate doxygen PDF documentation], + [DX_CHECK_DEPEND(doc, 1)], + [DX_CLEAR_DEPEND(doc, 1)], + [DX_REQUIRE_PROG([DX_PDFLATEX], pdflatex) + DX_REQUIRE_PROG([DX_MAKEINDEX], makeindex) + DX_REQUIRE_PROG([DX_EGREP], egrep)]) + +# LaTeX generation for PS and/or PDF: +AM_CONDITIONAL(DX_COND_latex, DX_TEST_FEATURE(ps) || DX_TEST_FEATURE(pdf)) +if DX_TEST_FEATURE(ps) || DX_TEST_FEATURE(pdf); then + DX_ENV_APPEND(GENERATE_LATEX, YES) +else + DX_ENV_APPEND(GENERATE_LATEX, NO) +fi + +# Paper size for PS and/or PDF: +AC_ARG_VAR(DOXYGEN_PAPER_SIZE, + [a4wide (default), a4, letter, legal or executive]) +case "$DOXYGEN_PAPER_SIZE" in +#( +"") + AC_SUBST(DOXYGEN_PAPER_SIZE, "") +;; #( +a4wide|a4|letter|legal|executive) + DX_ENV_APPEND(PAPER_SIZE, $DOXYGEN_PAPER_SIZE) +;; #( +*) + AC_MSG_ERROR([unknown DOXYGEN_PAPER_SIZE='$DOXYGEN_PAPER_SIZE']) +;; +esac + +#For debugging: +#echo DX_FLAG_doc=$DX_FLAG_doc +#echo DX_FLAG_dot=$DX_FLAG_dot +#echo DX_FLAG_man=$DX_FLAG_man +#echo DX_FLAG_html=$DX_FLAG_html +#echo DX_FLAG_chm=$DX_FLAG_chm +#echo DX_FLAG_chi=$DX_FLAG_chi +#echo DX_FLAG_rtf=$DX_FLAG_rtf +#echo DX_FLAG_xml=$DX_FLAG_xml +#echo DX_FLAG_pdf=$DX_FLAG_pdf +#echo DX_FLAG_ps=$DX_FLAG_ps +#echo DX_ENV=$DX_ENV +]) diff --git a/CommonAPI-DBus/src/CommonAPI/DBus/DBusAttribute.h b/CommonAPI-DBus/src/CommonAPI/DBus/DBusAttribute.h new file mode 100644 index 0000000..9ffa400 --- /dev/null +++ b/CommonAPI-DBus/src/CommonAPI/DBus/DBusAttribute.h @@ -0,0 +1,114 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#ifndef COMMONAPI_DBUS_DBUS_ATTRIBUTE_H_ +#define COMMONAPI_DBUS_DBUS_ATTRIBUTE_H_ + +#include "DBusProxyHelper.h" +#include "DBusEvent.h" + +#include + +namespace CommonAPI { +namespace DBus { + + +class DBusProxy; + + +template +class DBusReadonlyAttribute: public _AttributeType { + public: + typedef typename _AttributeType::ValueType ValueType; + typedef typename _AttributeType::AttributeAsyncCallback AttributeAsyncCallback; + + DBusReadonlyAttribute(_DBusProxyType& dbusProxy, const char* getMethodName): + dbusProxy_(dbusProxy), + getMethodName_(getMethodName) { + assert(getMethodName); + } + + CallStatus getValue(ValueType& value) const { + CallStatus callStatus; + DBusProxyHelper, + DBusSerializableArguments >::callMethodWithReply(dbusProxy_, getMethodName_, "", callStatus, value); + return callStatus; + } + + std::future getValueAsync(AttributeAsyncCallback attributeAsyncCallback) { + return DBusProxyHelper, + DBusSerializableArguments >::callMethodAsync(dbusProxy_, getMethodName_, "", std::move(attributeAsyncCallback)); + } + + protected: + _DBusProxyType& dbusProxy_; + const char* getMethodName_; +}; + + +template +class DBusAttribute: public DBusReadonlyAttribute<_AttributeType> { + public: + typedef typename _AttributeType::ValueType ValueType; + typedef typename _AttributeType::AttributeAsyncCallback AttributeAsyncCallback; + + DBusAttribute(_DBusProxyType& dbusProxy, const char* setMethodName, const char* setMethodSignature, const char* getMethodName): + DBusReadonlyAttribute<_AttributeType>(dbusProxy, getMethodName), + setMethodName_(setMethodName), + setMethodSignature_(setMethodSignature) { + assert(setMethodName); + assert(setMethodSignature); + } + + void setValue(const ValueType& requestValue, CallStatus& callStatus, ValueType& responseValue) { + DBusProxyHelper, + DBusSerializableArguments >::callMethodWithReply( + this->dbusProxy_, + setMethodName_, + setMethodSignature_, + requestValue, + callStatus, + responseValue); + } + + std::future setValueAsync(const ValueType& requestValue, AttributeAsyncCallback attributeAsyncCallback) { + return DBusProxyHelper, + DBusSerializableArguments >::callMethodAsync( + this->dbusProxy_, + setMethodName_, + setMethodSignature_, + requestValue, + attributeAsyncCallback); + } + + protected: + const char* setMethodName_; + const char* setMethodSignature_; +}; + + +template +class DBusObservableAttribute: public _AttributeType { + public: + typedef typename _AttributeType::ValueType ValueType; + typedef typename _AttributeType::AttributeAsyncCallback AttributeAsyncCallback; + typedef typename _AttributeType::ChangedEvent ChangedEvent; + + template + DBusObservableAttribute(_DBusProxyType& dbusProxy, const char* changedEventName, _AttributeTypeArguments... arguments): + _AttributeType(dbusProxy, arguments...), + changedEvent_(dbusProxy, changedEventName, this->setMethodSignature_) { + } + + ChangedEvent& getChangedEvent() { + return changedEvent_; + } + + protected: + DBusEvent changedEvent_; +}; + +} // namespace DBus +} // namespace CommonAPI + +#endif // COMMONAPI_DBUS_DBUS_ATTRIBUTE_H_ diff --git a/CommonAPI-DBus/src/CommonAPI/DBus/DBusConnection.cpp b/CommonAPI-DBus/src/CommonAPI/DBus/DBusConnection.cpp new file mode 100644 index 0000000..f94df52 --- /dev/null +++ b/CommonAPI-DBus/src/CommonAPI/DBus/DBusConnection.cpp @@ -0,0 +1,553 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include "DBusConnection.h" +#include "DBusInputStream.h" + +#include +#include +#include + +#include + +namespace CommonAPI { +namespace DBus { + + +DBusObjectPathVTable DBusConnection::libdbusObjectPathVTable_ = { + NULL, // no need to handle unregister callbacks + &DBusConnection::onLibdbusObjectPathMessageThunk +}; + +void DBusConnection::dispatch() { + while (!stopDispatching_ && readWriteDispatch(10)) { + } +} + +DBusConnection::DBusConnection(BusType busType) : + busType_(busType), + libdbusConnection_(NULL), + isLibdbusSignalFilterAdded_(false), + stopDispatching_(false) { + dbus_threads_init_default(); +} + +DBusConnection::DBusConnection(::DBusConnection* libDbusConnection) : + busType_(WRAPPED), + libdbusConnection_(libDbusConnection), + isLibdbusSignalFilterAdded_(false), + stopDispatching_(false) { + dbus_threads_init_default(); +} + +DBusConnection::~DBusConnection() { + if (isConnected()) { + disconnect(); + } + dispatchThread_.join(); +} + +bool DBusConnection::connect() { + DBusError dbusError; + return connect(dbusError); +} + +bool DBusConnection::connect(DBusError& dbusError) { + assert(!dbusError); + + if (isConnected()) + return true; + + const ::DBusBusType libdbusType = static_cast(busType_); + + libdbusConnection_ = dbus_bus_get_private(libdbusType, &dbusError.libdbusError_); + if (dbusError) + return false; + + assert(libdbusConnection_); + dbus_connection_set_exit_on_disconnect(libdbusConnection_, false); + + dbusConnectionStatusEvent_.notifyListeners(AvailabilityStatus::AVAILABLE); + + initLibdbusObjectPathHandlerAfterConnect(); + + initLibdbusSignalFilterAfterConnect(); + + dispatchThread_ = std::thread(std::bind(&DBusConnection::dispatch, this)); + + return true; +} + +void DBusConnection::disconnect() { + if (isConnected()) { + stopDispatching_ = true; + if (!dbusSignalMatchRulesMap_.empty()) { + dbus_connection_remove_filter(libdbusConnection_, &onLibdbusSignalFilterThunk, this); + } + + dbus_connection_close(libdbusConnection_); + dbus_connection_unref(libdbusConnection_); + libdbusConnection_ = NULL; + + dbusConnectionStatusEvent_.notifyListeners(AvailabilityStatus::NOT_AVAILABLE); + } +} + +bool DBusConnection::isConnected() const { + return (libdbusConnection_ != NULL); +} + +DBusConnectionStatusEvent& DBusConnection::getConnectionStatusEvent() { + return dbusConnectionStatusEvent_; +} + +const std::shared_ptr& DBusConnection::getDBusServiceRegistry() { + if (!dbusServiceRegistry_) { + dbusServiceRegistry_ = std::make_shared(this->shared_from_this()); + } + + return dbusServiceRegistry_; +} + +const std::shared_ptr& DBusConnection::getDBusDaemonProxy() { + if (!dbusDaemonProxy_) { + dbusDaemonProxy_ = std::make_shared(this->shared_from_this()); + } + + return dbusDaemonProxy_; +} + +const std::shared_ptr& DBusConnection::getDBusObjectManager() { + if (!dbusObjectManager_) { + dbusObjectManager_ = std::make_shared(this->shared_from_this()); + } + + return dbusObjectManager_; +} + +bool DBusConnection::requestServiceNameAndBlock(const std::string& serviceName) const { + DBusError dbusError; + const int libdbusStatus = dbus_bus_request_name(libdbusConnection_, + serviceName.c_str(), + DBUS_NAME_FLAG_DO_NOT_QUEUE, + &dbusError.libdbusError_); + const bool isServiceNameAcquired = (libdbusStatus == DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER); + + return isServiceNameAcquired; +} + +bool DBusConnection::releaseServiceName(const std::string& serviceName) const { + DBusError dbusError; + const int libdbusStatus = dbus_bus_release_name(libdbusConnection_, + serviceName.c_str(), + &dbusError.libdbusError_); + const bool isServiceNameReleased = (libdbusStatus == DBUS_RELEASE_NAME_REPLY_RELEASED); + + return isServiceNameReleased; +} + +bool DBusConnection::sendDBusMessage(const DBusMessage& dbusMessage, uint32_t* allocatedSerial) const { + assert(dbusMessage); + assert(isConnected()); + + dbus_uint32_t* libdbusSerial = static_cast(allocatedSerial); + const bool result = dbus_connection_send(libdbusConnection_, dbusMessage.libdbusMessage_, libdbusSerial); + + return result; +} + +void DBusConnection::onLibdbusPendingCallNotifyThunk(::DBusPendingCall* libdbusPendingCall, void *userData) { + assert(userData); + assert(libdbusPendingCall); + + auto dbusMessageReplyAsyncHandler = reinterpret_cast(userData); + + ::DBusMessage* libdbusMessage = dbus_pending_call_steal_reply( + libdbusPendingCall); + const bool increaseLibdbusMessageReferenceCount = false; + DBusMessage dbusMessage(libdbusMessage, increaseLibdbusMessageReferenceCount); + + dbusMessageReplyAsyncHandler->onDBusMessageReply(CallStatus::SUCCESS, dbusMessage); + + // libdbus calls the Cleanup method below + dbus_pending_call_unref(libdbusPendingCall); +} + +void DBusConnection::onLibdbusDataCleanup(void* userData) { + auto dbusMessageReplyAsyncHandler = reinterpret_cast(userData); + delete dbusMessageReplyAsyncHandler; +} + +std::future DBusConnection::sendDBusMessageWithReplyAsync( + const DBusMessage& dbusMessage, + std::unique_ptr dbusMessageReplyAsyncHandler, + int timeoutMilliseconds) const { + + assert(dbusMessage); + assert(isConnected()); + + DBusPendingCall* libdbusPendingCall; + dbus_bool_t libdbusSuccess; + + libdbusSuccess = dbus_connection_send_with_reply( + libdbusConnection_, + dbusMessage.libdbusMessage_, + &libdbusPendingCall, + timeoutMilliseconds); + + if (!libdbusSuccess || !libdbusPendingCall) { + dbusMessageReplyAsyncHandler->onDBusMessageReply(CallStatus::CONNECTION_FAILED, dbusMessage); + return dbusMessageReplyAsyncHandler->getFuture(); + } + + libdbusSuccess = dbus_pending_call_set_notify( + libdbusPendingCall, + onLibdbusPendingCallNotifyThunk, + dbusMessageReplyAsyncHandler.get(), + onLibdbusDataCleanup); + + if (!libdbusSuccess) { + dbusMessageReplyAsyncHandler->onDBusMessageReply(CallStatus::OUT_OF_MEMORY, dbusMessage); + dbus_pending_call_unref(libdbusPendingCall); + return dbusMessageReplyAsyncHandler->getFuture(); + } + + return dbusMessageReplyAsyncHandler.release()->getFuture(); +} + + +DBusMessage DBusConnection::sendDBusMessageWithReplyAndBlock(const DBusMessage& dbusMessage, + DBusError& dbusError, + int timeoutMilliseconds) const { + assert(dbusMessage); + assert(!dbusError); + assert(isConnected()); + + ::DBusMessage* libdbusMessageReply = dbus_connection_send_with_reply_and_block(libdbusConnection_, + dbusMessage.libdbusMessage_, + timeoutMilliseconds, + &dbusError.libdbusError_); + if (dbusError) + return DBusMessage(); + + const bool increaseLibdbusMessageReferenceCount = false; + return DBusMessage(libdbusMessageReply, increaseLibdbusMessageReferenceCount); +} + + +bool DBusConnection::readWriteDispatch(int timeoutMilliseconds) { + if(isConnected()) { + const dbus_bool_t libdbusSuccess = dbus_connection_read_write_dispatch(libdbusConnection_, + timeoutMilliseconds); + return libdbusSuccess; + } + return false; +} + +DBusProxyConnection::DBusSignalHandlerToken DBusConnection::addSignalMemberHandler(const std::string& objectPath, + const std::string& interfaceName, + const std::string& interfaceMemberName, + const std::string& interfaceMemberSignature, + DBusSignalHandler* dbusSignalHandler) { + DBusSignalHandlerPath dbusSignalHandlerPath( + objectPath, + interfaceName, + interfaceMemberName, + interfaceMemberSignature); + const bool isFirstSignalMemberHandler = dbusSignalHandlerTable_.find(dbusSignalHandlerPath) == dbusSignalHandlerTable_.end(); + + dbusSignalHandlerTable_.insert(DBusSignalHandlerTable::value_type(dbusSignalHandlerPath, dbusSignalHandler)); + + if (isFirstSignalMemberHandler) + addLibdbusSignalMatchRule(objectPath, interfaceName, interfaceMemberName); + + return dbusSignalHandlerPath; +} + +void DBusConnection::removeSignalMemberHandler(const DBusSignalHandlerToken& dbusSignalHandlerToken) { + auto equalRangeIteratorPair = dbusSignalHandlerTable_.equal_range(dbusSignalHandlerToken); + + // the range can't be empty! + assert(equalRangeIteratorPair.first != equalRangeIteratorPair.second); + + // advance to the next element + equalRangeIteratorPair.first++; + + // check if the first element was the only element + const bool isLastSignalMemberHandler = equalRangeIteratorPair.first == equalRangeIteratorPair.second; + + if (isLastSignalMemberHandler) { + const std::string& objectPath = std::get<0>(dbusSignalHandlerToken); + const std::string& interfaceName = std::get<1>(dbusSignalHandlerToken); + const std::string& interfaceMemberName = std::get<2>(dbusSignalHandlerToken); + + removeLibdbusSignalMatchRule(objectPath, interfaceName, interfaceMemberName); + } + + dbusSignalHandlerTable_.erase(dbusSignalHandlerToken); +} + +void DBusConnection::registerObjectPath(const std::string& objectPath) { + assert(!objectPath.empty()); + assert(objectPath[0] == '/'); + + auto handlerIterator = libdbusRegisteredObjectPaths_.find(objectPath); + const bool foundRegisteredObjectPathHandler = handlerIterator != libdbusRegisteredObjectPaths_.end(); + + if (foundRegisteredObjectPathHandler) { + uint32_t& referenceCount = handlerIterator->second; + + referenceCount++; + + return; + } + + libdbusRegisteredObjectPaths_.insert(LibdbusRegisteredObjectPathHandlersTable::value_type(objectPath, 1)); + + if (isConnected()) { + DBusError dbusError; + const dbus_bool_t libdbusSuccess = dbus_connection_try_register_object_path(libdbusConnection_, + objectPath.c_str(), + &libdbusObjectPathVTable_, + this, + &dbusError.libdbusError_); + assert(libdbusSuccess); + assert(!dbusError); + } +} + +void DBusConnection::unregisterObjectPath(const std::string& objectPath) { + assert(!objectPath.empty()); + assert(objectPath[0] == '/'); + + auto handlerIterator = libdbusRegisteredObjectPaths_.find(objectPath); + const bool foundRegisteredObjectPathHandler = handlerIterator != libdbusRegisteredObjectPaths_.end(); + + assert(foundRegisteredObjectPathHandler); + + uint32_t& referenceCount = handlerIterator->second; + if (referenceCount > 1) { + referenceCount--; + return; + } + + libdbusRegisteredObjectPaths_.erase(handlerIterator); + + if (isConnected()) { + dbus_bool_t libdbusSuccess = dbus_connection_unregister_object_path(libdbusConnection_, + objectPath.c_str()); + assert(libdbusSuccess); + } +} + +void DBusConnection::addLibdbusSignalMatchRule(const std::string& objectPath, + const std::string& interfaceName, + const std::string& interfaceMemberName) { + DBusSignalMatchRuleTuple dbusSignalMatchRuleTuple(objectPath, interfaceName, interfaceMemberName); + auto matchRuleIterator = dbusSignalMatchRulesMap_.find(dbusSignalMatchRuleTuple); + const bool matchRuleFound = matchRuleIterator != dbusSignalMatchRulesMap_.end(); + + if (matchRuleFound) { + uint32_t& matchRuleReferenceCount = matchRuleIterator->second.first; + matchRuleReferenceCount++; + return; + } + + const bool isFirstMatchRule = dbusSignalMatchRulesMap_.empty(); + + // generate D-Bus match rule string + std::ostringstream matchRuleStringStream; + + matchRuleStringStream << "type='signal'"; + matchRuleStringStream << ",path='" << objectPath << "'"; + matchRuleStringStream << ",interface='" << interfaceName << "'"; + matchRuleStringStream << ",member='" << interfaceMemberName << "'"; + + // add the match rule string to the map with reference count set to 1 + std::string matchRuleString = matchRuleStringStream.str(); + auto success = dbusSignalMatchRulesMap_.insert( + DBusSignalMatchRulesMap::value_type(dbusSignalMatchRuleTuple, + DBusSignalMatchRuleMapping(1, matchRuleString))); + assert(success.second); + + // if not connected the filter and the rules will be added as soon as the connection is established + if (isConnected()) { + // add the libdbus message signal filter + if (isFirstMatchRule) { + const dbus_bool_t libdbusSuccess = dbus_connection_add_filter(libdbusConnection_, + &onLibdbusSignalFilterThunk, + this, + NULL); + assert(libdbusSuccess); + } + + // finally add the match rule + DBusError dbusError; + dbus_bus_add_match(libdbusConnection_, matchRuleString.c_str(), &dbusError.libdbusError_); + assert(!dbusError); + } +} + +void DBusConnection::removeLibdbusSignalMatchRule(const std::string& objectPath, + const std::string& interfaceName, + const std::string& interfaceMemberName) { + DBusSignalMatchRuleTuple dbusSignalMatchRuleTuple(objectPath, interfaceName, interfaceMemberName); + auto matchRuleIterator = dbusSignalMatchRulesMap_.find(dbusSignalMatchRuleTuple); + const bool matchRuleFound = matchRuleIterator != dbusSignalMatchRulesMap_.end(); + + assert(matchRuleFound); + + uint32_t& matchRuleReferenceCount = matchRuleIterator->second.first; + if (matchRuleReferenceCount > 1) { + matchRuleReferenceCount--; + return; + } + + const std::string& matchRuleString = matchRuleIterator->second.second; + DBusError dbusError; + dbus_bus_remove_match(libdbusConnection_, matchRuleString.c_str(), &dbusError.libdbusError_); + assert(!dbusError); + + dbusSignalMatchRulesMap_.erase(matchRuleIterator); + + const bool isLastMatchRule = dbusSignalMatchRulesMap_.empty(); + if (isLastMatchRule) + dbus_connection_remove_filter(libdbusConnection_, &onLibdbusSignalFilterThunk, this); +} + +void DBusConnection::initLibdbusObjectPathHandlerAfterConnect() { + assert(isConnected()); + + // nothing to do if there aren't any registered object path handlers + if (libdbusRegisteredObjectPaths_.empty()) + return; + + DBusError dbusError; + dbus_bool_t libdbusSuccess; + + for ( auto handlerIterator = libdbusRegisteredObjectPaths_.begin(); + handlerIterator != libdbusRegisteredObjectPaths_.end(); + handlerIterator++) { + const std::string& objectPath = handlerIterator->first; + + dbusError.clear(); + + libdbusSuccess = dbus_connection_try_register_object_path(libdbusConnection_, + objectPath.c_str(), + &libdbusObjectPathVTable_, + this, + &dbusError.libdbusError_); + assert(libdbusSuccess); + assert(!dbusError); + } +} + +void DBusConnection::initLibdbusSignalFilterAfterConnect() { + assert(isConnected()); + + // nothing to do if there aren't any signal match rules + if (dbusSignalMatchRulesMap_.empty()) + return; + + // first we add the libdbus message signal filter + const dbus_bool_t libdbusSuccess = dbus_connection_add_filter(libdbusConnection_, + &onLibdbusSignalFilterThunk, + this, + NULL); + assert(libdbusSuccess); + + // then we upload all match rules to the dbus-daemon + DBusError dbusError; + for (auto iterator = dbusSignalMatchRulesMap_.begin(); iterator != dbusSignalMatchRulesMap_.end(); iterator++) { + const std::string& matchRuleString = iterator->second.second; + + dbusError.clear(); + dbus_bus_add_match(libdbusConnection_, matchRuleString.c_str(), &dbusError.libdbusError_); + assert(!dbusError); + } +} + +::DBusHandlerResult DBusConnection::onLibdbusObjectPathMessage(::DBusMessage* libdbusMessage) const { + assert(libdbusMessage); + + // handle only method call messages + if (dbus_message_get_type(libdbusMessage) != DBUS_MESSAGE_TYPE_METHOD_CALL) { + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + } + + bool isDBusMessageHandled = dbusObjectManager_->handleMessage(DBusMessage(libdbusMessage)); + return isDBusMessageHandled ? DBUS_HANDLER_RESULT_HANDLED : DBUS_HANDLER_RESULT_NOT_YET_HANDLED; +} + +::DBusHandlerResult DBusConnection::onLibdbusSignalFilter(::DBusMessage* libdbusMessage) { + assert(libdbusMessage); + + // handle only signal messages + if (dbus_message_get_type(libdbusMessage) != DBUS_MESSAGE_TYPE_SIGNAL) + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + + const char* objectPath = dbus_message_get_path(libdbusMessage); + const char* interfaceName = dbus_message_get_interface(libdbusMessage); + const char* interfaceMemberName = dbus_message_get_member(libdbusMessage); + const char* interfaceMemberSignature = dbus_message_get_signature(libdbusMessage); + + assert(objectPath); + assert(interfaceName); + assert(interfaceMemberName); + assert(interfaceMemberSignature); + + DBusSignalHandlerPath dbusSignalHandlerPath(objectPath, interfaceName, interfaceMemberName, interfaceMemberSignature); + auto equalRangeIteratorPair = dbusSignalHandlerTable_.equal_range(dbusSignalHandlerPath); + + if (equalRangeIteratorPair.first != equalRangeIteratorPair.second) { + DBusMessage dbusMessage(libdbusMessage); + + while (equalRangeIteratorPair.first != equalRangeIteratorPair.second) { + DBusSignalHandler* dbusSignalHandler = equalRangeIteratorPair.first->second; + const SubscriptionStatus dbusSignalHandlerSubscriptionStatus = dbusSignalHandler->onSignalDBusMessage(dbusMessage); + + if (dbusSignalHandlerSubscriptionStatus == SubscriptionStatus::CANCEL) { + auto dbusSignalHandlerSubscription = equalRangeIteratorPair.first; + equalRangeIteratorPair.first++; + dbusSignalHandlerTable_.erase(dbusSignalHandlerSubscription); + } else + equalRangeIteratorPair.first++; + } + + return DBUS_HANDLER_RESULT_HANDLED; + } + + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; +} + +::DBusHandlerResult DBusConnection::onLibdbusSignalFilterThunk(::DBusConnection* libdbusConnection, + ::DBusMessage* libdbusMessage, + void* userData) { + assert(libdbusConnection); + assert(libdbusMessage); + assert(userData); + + DBusConnection* dbusConnection = reinterpret_cast(userData); + + assert(dbusConnection->libdbusConnection_ == libdbusConnection); + + return dbusConnection->onLibdbusSignalFilter(libdbusMessage); +} + +::DBusHandlerResult DBusConnection::onLibdbusObjectPathMessageThunk(::DBusConnection* libdbusConnection, + ::DBusMessage* libdbusMessage, + void* userData) { + assert(libdbusConnection); + assert(libdbusMessage); + assert(userData); + + const DBusConnection* dbusConnection = reinterpret_cast(userData); + + assert(dbusConnection->libdbusConnection_ == libdbusConnection); + + return dbusConnection->onLibdbusObjectPathMessage(libdbusMessage); +} + +} // namespace DBus +} // namespace CommonAPI + diff --git a/CommonAPI-DBus/src/CommonAPI/DBus/DBusConnection.h b/CommonAPI-DBus/src/CommonAPI/DBus/DBusConnection.h new file mode 100644 index 0000000..1d397c6 --- /dev/null +++ b/CommonAPI-DBus/src/CommonAPI/DBus/DBusConnection.h @@ -0,0 +1,175 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#ifndef COMMONAPI_DBUS_DBUS_CONNECTION_H_ +#define COMMONAPI_DBUS_DBUS_CONNECTION_H_ + +#include "DBusProxyConnection.h" +#include "DBusDaemonProxy.h" +#include "DBusServiceRegistry.h" +#include "DBusObjectManager.h" + +#include + + +namespace CommonAPI { +namespace DBus { + +class DBusConnection; +class DBusObjectManager; + +class DBusConnectionStatusEvent: public Event { + friend class DBusConnection; +}; + + +class DBusConnection: public DBusProxyConnection, public std::enable_shared_from_this { + public: + enum BusType { + SESSION = DBUS_BUS_SESSION, + SYSTEM = DBUS_BUS_SYSTEM, + STARTER = DBUS_BUS_STARTER, + WRAPPED + }; + + inline static std::shared_ptr getBus(const BusType& busType); + inline static std::shared_ptr wrapLibDBus(::DBusConnection* libDbusConnection); + inline static std::shared_ptr getSessionBus(); + inline static std::shared_ptr getSystemBus(); + inline static std::shared_ptr getStarterBus(); + + DBusConnection(const DBusConnection&) = delete; + DBusConnection(::DBusConnection* libDbusConnection); + + DBusConnection& operator=(const DBusConnection&) = delete; + virtual ~DBusConnection(); + + BusType getBusType() const; + + bool connect(); + bool connect(DBusError& dbusError); + void disconnect(); + + virtual bool isConnected() const; + + virtual DBusConnectionStatusEvent& getConnectionStatusEvent(); + + virtual bool requestServiceNameAndBlock(const std::string& serviceName) const; + virtual bool releaseServiceName(const std::string& serviceName) const; + + bool sendDBusMessage(const DBusMessage& dbusMessage, uint32_t* allocatedSerial = NULL) const; + + static const int kDefaultSendTimeoutMs = 100 * 1000; + + std::future sendDBusMessageWithReplyAsync( + const DBusMessage& dbusMessage, + std::unique_ptr dbusMessageReplyAsyncHandler, + int timeoutMilliseconds = kDefaultSendTimeoutMs) const; + + DBusMessage sendDBusMessageWithReplyAndBlock(const DBusMessage& dbusMessage, + DBusError& dbusError, + int timeoutMilliseconds = kDefaultSendTimeoutMs) const; + + DBusSignalHandlerToken addSignalMemberHandler(const std::string& objectPath, + const std::string& interfaceName, + const std::string& interfaceMemberName, + const std::string& interfaceMemberSignature, + DBusSignalHandler* dbusSignalHandler); + + void registerObjectPath(const std::string& objectPath); + void unregisterObjectPath(const std::string& objectPath); + + void removeSignalMemberHandler(const DBusSignalHandlerToken& dbusSignalHandlerToken); + + bool readWriteDispatch(int timeoutMilliseconds = -1); + + virtual const std::shared_ptr& getDBusDaemonProxy(); + virtual const std::shared_ptr& getDBusServiceRegistry(); + virtual const std::shared_ptr& getDBusObjectManager(); + + private: + void dispatch(); + + std::thread dispatchThread_; + bool stopDispatching_; + + DBusConnection(BusType busType); + + void addLibdbusSignalMatchRule(const std::string& objectPath, + const std::string& interfaceName, + const std::string& interfaceMemberName); + + void removeLibdbusSignalMatchRule(const std::string& objectPath, + const std::string& interfaceName, + const std::string& interfaceMemberName); + + void initLibdbusObjectPathHandlerAfterConnect(); + + void initLibdbusSignalFilterAfterConnect(); + + ::DBusHandlerResult onLibdbusObjectPathMessage(::DBusMessage* libdbusMessage) const; + + ::DBusHandlerResult onLibdbusSignalFilter(::DBusMessage* libdbusMessage); + + static void onLibdbusPendingCallNotifyThunk(::DBusPendingCall* libdbusPendingCall, void *userData); + static void onLibdbusDataCleanup(void* userData); + + static ::DBusHandlerResult onLibdbusObjectPathMessageThunk(::DBusConnection* libdbusConnection, + ::DBusMessage* libdbusMessage, + void* userData); + + static ::DBusHandlerResult onLibdbusSignalFilterThunk(::DBusConnection* libdbusConnection, + ::DBusMessage* libdbusMessage, + void* userData); + + BusType busType_; + + ::DBusConnection* libdbusConnection_; + + std::shared_ptr dbusDaemonProxy_; + std::shared_ptr dbusServiceRegistry_; + std::shared_ptr dbusObjectManager_; + + DBusConnectionStatusEvent dbusConnectionStatusEvent_; + + typedef std::tuple DBusSignalMatchRuleTuple; + typedef std::pair DBusSignalMatchRuleMapping; + typedef std::unordered_map DBusSignalMatchRulesMap; + DBusSignalMatchRulesMap dbusSignalMatchRulesMap_; + + bool isLibdbusSignalFilterAdded_; + + DBusSignalHandlerTable dbusSignalHandlerTable_; + + // referenceCount, objectPath + typedef std::unordered_map LibdbusRegisteredObjectPathHandlersTable; + LibdbusRegisteredObjectPathHandlersTable libdbusRegisteredObjectPaths_; + + static DBusObjectPathVTable libdbusObjectPathVTable_; +}; + +std::shared_ptr DBusConnection::getBus(const BusType& busType) { + return std::shared_ptr(new DBusConnection(busType)); +} + +std::shared_ptr DBusConnection::wrapLibDBus(::DBusConnection* libDbusConnection) { + return std::shared_ptr(new DBusConnection(libDbusConnection)); +} + +std::shared_ptr DBusConnection::getSessionBus() { + return getBus(BusType::SESSION); +} + +std::shared_ptr DBusConnection::getSystemBus() { + return getBus(BusType::SYSTEM); +} + +std::shared_ptr DBusConnection::getStarterBus() { + return getBus(BusType::STARTER); +} + + +} // namespace DBus +} // namespace CommonAPI + +#endif // COMMONAPI_DBUS_DBUS_CONNECTION_H_ diff --git a/CommonAPI-DBus/src/CommonAPI/DBus/DBusDaemonProxy.cpp b/CommonAPI-DBus/src/CommonAPI/DBus/DBusDaemonProxy.cpp new file mode 100644 index 0000000..8700ee7 --- /dev/null +++ b/CommonAPI-DBus/src/CommonAPI/DBus/DBusDaemonProxy.cpp @@ -0,0 +1,110 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include "DBusDaemonProxy.h" +#include "DBusProxyHelper.h" +#include + + +namespace CommonAPI { +namespace DBus { + +DBusDaemonProxy::DBusDaemonProxy(const std::shared_ptr& connection): + DBusProxy("org.freedesktop.DBus", "/org/freedesktop/DBus", getInterfaceName(), connection, true), + nameOwnerChangedEvent_(*this, "NameOwnerChanged", "sss") { +} + +const char* DBusDaemonProxy::getInterfaceName() const { + return "org.freedesktop.DBus"; +} + +DBusDaemonProxy::NameOwnerChangedEvent& DBusDaemonProxy::getNameOwnerChangedEvent() { + return nameOwnerChangedEvent_; +} + +void DBusDaemonProxy::listNames(CommonAPI::CallStatus& callStatus, std::vector& busNames) const { + DBusMessage dbusMethodCall = createMethodCall("ListNames", ""); + + DBusError dbusError; + DBusMessage dbusMessageReply = getDBusConnection()->sendDBusMessageWithReplyAndBlock( + dbusMethodCall, + dbusError); + + if (dbusError || !dbusMessageReply.isMethodReturnType()) { + callStatus = CallStatus::REMOTE_ERROR; + return; + } + + DBusInputStream inputStream(dbusMessageReply); + const bool success = DBusSerializableArguments>::deserialize(inputStream, busNames); + if (!success) { + callStatus = CallStatus::REMOTE_ERROR; + return; + } + callStatus = CallStatus::SUCCESS; + +} + +std::future DBusDaemonProxy::listNamesAsync(ListNamesAsyncCallback listNamesAsyncCallback) const { + DBusMessage dbusMessage = createMethodCall("ListNames", ""); + + return getDBusConnection()->sendDBusMessageWithReplyAsync( + dbusMessage, + DBusProxyAsyncCallbackHandler>::create(listNamesAsyncCallback)); +} + +void DBusDaemonProxy::nameHasOwner(const std::string& busName, CommonAPI::CallStatus& callStatus, bool& hasOwner) const { + + DBusMessage dbusMethodCall = createMethodCall("NameHasOwner", "s"); + + DBusOutputStream outputStream(dbusMethodCall); + bool success = DBusSerializableArguments::serialize(outputStream, busName); + if (!success) { + callStatus = CallStatus::OUT_OF_MEMORY; + return; + } + outputStream.flush(); + + DBusError dbusError; + DBusMessage dbusMessageReply = getDBusConnection()->sendDBusMessageWithReplyAndBlock( + dbusMethodCall, + dbusError); + if (dbusError || !dbusMessageReply.isMethodReturnType()) { + callStatus = CallStatus::REMOTE_ERROR; + return; + } + + DBusInputStream inputStream(dbusMessageReply); + success = DBusSerializableArguments::deserialize(inputStream, hasOwner); + if (!success) { + callStatus = CallStatus::REMOTE_ERROR; + return; + } + callStatus = CallStatus::SUCCESS; + +} + +std::future DBusDaemonProxy::nameHasOwnerAsync(const std::string& busName, NameHasOwnerAsyncCallback nameHasOwnerAsyncCallback) const { + + DBusMessage dbusMessage = createMethodCall("NameHasOwner", "s"); + + DBusOutputStream outputStream(dbusMessage); + const bool success = DBusSerializableArguments::serialize(outputStream, busName); + if (!success) { + std::promise promise; + promise.set_value(CallStatus::OUT_OF_MEMORY); + return promise.get_future(); + } + outputStream.flush(); + + return getDBusConnection()->sendDBusMessageWithReplyAsync( + dbusMessage, + DBusProxyAsyncCallbackHandler::create(nameHasOwnerAsyncCallback)); + +} + +void DBusDaemonProxy::getOwnVersion(uint16_t& ownVersionMajor, uint16_t& ownVersionMinor) const { +} + +} // namespace DBus +} // namespace CommonAPI diff --git a/CommonAPI-DBus/src/CommonAPI/DBus/DBusDaemonProxy.h b/CommonAPI-DBus/src/CommonAPI/DBus/DBusDaemonProxy.h new file mode 100644 index 0000000..2abda78 --- /dev/null +++ b/CommonAPI-DBus/src/CommonAPI/DBus/DBusDaemonProxy.h @@ -0,0 +1,51 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#ifndef COMMONAPI_DBUS_DBUS_DAEMON_PROXY_H_ +#define COMMONAPI_DBUS_DBUS_DAEMON_PROXY_H_ + +#include "DBusProxy.h" +#include "DBusEvent.h" + +#include "DBusServiceStatusEvent.h" + +#include +#include + +namespace CommonAPI { +namespace DBus { + +class DBusServiceStatusEvent; + +class DBusDaemonProxy: public DBusProxy { + + public: + typedef Event NameOwnerChangedEvent; + typedef std::function)> ListNamesAsyncCallback; + typedef std::function NameHasOwnerAsyncCallback; + + + DBusDaemonProxy(const std::shared_ptr& connection); + + const char* getInterfaceName() const; + + NameOwnerChangedEvent& getNameOwnerChangedEvent(); + + void listNames(CommonAPI::CallStatus& callStatus, std::vector& busNames) const; + std::future listNamesAsync(ListNamesAsyncCallback listNamesAsyncCallback) const; + + void nameHasOwner(const std::string& busName, CommonAPI::CallStatus& callStatus, bool& hasOwner) const; + std::future nameHasOwnerAsync(const std::string& busName, NameHasOwnerAsyncCallback nameHasOwnerAsyncCallback) const; + + protected: + void getOwnVersion(uint16_t& ownVersionMajor, uint16_t& ownVersionMinor) const; + + private: + DBusEvent nameOwnerChangedEvent_; + +}; + +} // namespace DBus +} // namespace CommonAPI + +#endif // COMMONAPI_DBUS_DBUS_DAEMON_PROXY_H_ diff --git a/CommonAPI-DBus/src/CommonAPI/DBus/DBusError.cpp b/CommonAPI-DBus/src/CommonAPI/DBus/DBusError.cpp new file mode 100644 index 0000000..937a22a --- /dev/null +++ b/CommonAPI-DBus/src/CommonAPI/DBus/DBusError.cpp @@ -0,0 +1,42 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include "DBusError.h" + +#include +#include + +namespace CommonAPI { +namespace DBus { + + +DBusError::DBusError() { + dbus_error_init(&libdbusError_); +} + +DBusError::~DBusError() { + dbus_error_free(&libdbusError_); +} + +DBusError::operator bool() const { + return dbus_error_is_set(&libdbusError_); +} + +void DBusError::clear() { + dbus_error_free(&libdbusError_); +} + +std::string DBusError::getName() const { + assert(*this); + + return std::string(libdbusError_.name); +} + +std::string DBusError::getMessage() const { + assert(*this); + + return std::string(libdbusError_.message); +} + +} // namespace DBus +} // namespace CommonAPI diff --git a/CommonAPI-DBus/src/CommonAPI/DBus/DBusError.h b/CommonAPI-DBus/src/CommonAPI/DBus/DBusError.h new file mode 100644 index 0000000..d8f33ee --- /dev/null +++ b/CommonAPI-DBus/src/CommonAPI/DBus/DBusError.h @@ -0,0 +1,37 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#ifndef COMMONAPI_DBUS_DBUS_ERROR_H_ +#define COMMONAPI_DBUS_DBUS_ERROR_H_ + +#include +#include + +namespace CommonAPI { +namespace DBus { + +class DBusConnection; + + +class DBusError { + public: + DBusError(); + ~DBusError(); + + operator bool() const; + + void clear(); + + std::string getName() const; + std::string getMessage() const; + + private: + ::DBusError libdbusError_; + + friend class DBusConnection; +}; + +} // namespace DBus +} // namespace CommonAPI + +#endif // COMMONAPI_DBUS_DBUS_ERROR_H_ diff --git a/CommonAPI-DBus/src/CommonAPI/DBus/DBusEvent.h b/CommonAPI-DBus/src/CommonAPI/DBus/DBusEvent.h new file mode 100644 index 0000000..0fb0db7 --- /dev/null +++ b/CommonAPI-DBus/src/CommonAPI/DBus/DBusEvent.h @@ -0,0 +1,74 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#ifndef COMMONAPI_DBUS_DBUS_EVENT_H_ +#define COMMONAPI_DBUS_DBUS_EVENT_H_ + +#include "DBusProxyConnection.h" +#include "DBusMessage.h" +#include "DBusSerializableArguments.h" + +#include + +namespace CommonAPI { +namespace DBus { + +class DBusProxy; + + +template +class DBusEvent: public _EventType, public DBusProxyConnection::DBusSignalHandler { + public: + typedef typename _EventType::ArgumentsTuple ArgumentsTuple; + typedef typename _EventType::CancellableListener CancellableListener; + + DBusEvent(_DBusProxy& dbusProxy, const char* eventName, const char* eventSignature): + dbusProxy_(dbusProxy), + eventName_(eventName), + eventSignature_(eventSignature) { + assert(eventName); + assert(eventSignature); + } + + virtual ~DBusEvent() { + if (this->hasListeners()) + dbusProxy_.removeSignalMemberHandler(subscription_); + } + + virtual SubscriptionStatus onSignalDBusMessage(const DBusMessage& dbusMessage) { + return unpackArgumentsAndHandleSignalDBusMessage(dbusMessage, ArgumentsTuple()); + } + + protected: + virtual void onFirstListenerAdded(const CancellableListener&) { + subscription_ = dbusProxy_.addSignalMemberHandler(eventName_, eventSignature_, this); + } + + virtual void onLastListenerRemoved(const CancellableListener&) { + dbusProxy_.removeSignalMemberHandler(subscription_); + } + + private: + template + inline SubscriptionStatus unpackArgumentsAndHandleSignalDBusMessage(const DBusMessage& dbusMessage, std::tuple<_Arguments...> argTuple) { + return handleSignalDBusMessage(dbusMessage, std::move(argTuple), typename make_sequence::type()); + } + + template + inline SubscriptionStatus handleSignalDBusMessage(const DBusMessage& dbusMessage, std::tuple<_Arguments...> argTuple, index_sequence<_ArgIndices...>) { + DBusInputStream dbusInputStream(dbusMessage); + const bool success = DBusSerializableArguments<_Arguments...>::deserialize(dbusInputStream, std::get<_ArgIndices>(argTuple)...); + // Continue subscription if deserialization failed + return success ? this->notifyListeners(std::get<_ArgIndices>(argTuple)...) : SubscriptionStatus::RETAIN; + } + + _DBusProxy& dbusProxy_; + const char* eventName_; + const char* eventSignature_; + DBusProxyConnection::DBusSignalHandlerToken subscription_; +}; + +} // namespace DBus +} // namespace CommonAPI + +#endif // COMMONAPI_DBUS_DBUS_EVENT_H_ diff --git a/CommonAPI-DBus/src/CommonAPI/DBus/DBusFactory.cpp b/CommonAPI-DBus/src/CommonAPI/DBus/DBusFactory.cpp new file mode 100644 index 0000000..4bec90c --- /dev/null +++ b/CommonAPI-DBus/src/CommonAPI/DBus/DBusFactory.cpp @@ -0,0 +1,114 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include "DBusProxy.h" +#include "DBusConnection.h" +#include "DBusFactory.h" +#include "DBusServiceRegistry.h" +#include "DBusUtils.h" + +#include +#include +#include +#include +#include +#include + +namespace CommonAPI { +namespace DBus { + +std::unordered_map* registeredProxyFactoryFunctions_; +std::unordered_map* registeredAdapterFactoryFunctions_; + + +void DBusFactory::registerProxyFactoryMethod(std::string interfaceName, DBusProxyFactoryFunction proxyFactoryMethod) { + if(!registeredProxyFactoryFunctions_) { + registeredProxyFactoryFunctions_ = new std::unordered_map(); + } + registeredProxyFactoryFunctions_->insert({interfaceName, proxyFactoryMethod}); +} + +void DBusFactory::registerAdapterFactoryMethod(std::string interfaceName, DBusAdapterFactoryFunction adapterFactoryMethod) { + if(!registeredAdapterFactoryFunctions_) { + registeredAdapterFactoryFunctions_ = new std::unordered_map(); + } + registeredAdapterFactoryFunctions_->insert({interfaceName, adapterFactoryMethod}); +} + + + +DBusFactory::DBusFactory(std::shared_ptr runtime, const MiddlewareInfo* middlewareInfo) : + CommonAPI::Factory(runtime, middlewareInfo), + dbusConnection_(CommonAPI::DBus::DBusConnection::getSessionBus()), + acquiredConnectionName_("") { + dbusConnection_->connect(); +} + +DBusFactory::~DBusFactory() { +} + + +std::vector DBusFactory::getAvailableServiceInstances(const std::string& serviceInterfaceName, + const std::string& serviceDomainName) { + return dbusConnection_->getDBusServiceRegistry()->getAvailableServiceInstances(serviceInterfaceName, serviceDomainName); +} + + +bool DBusFactory::isServiceInstanceAlive(const std::string& serviceInstanceId, + const std::string& serviceInterfaceName, + const std::string& serviceDomainName) { + + return dbusConnection_->getDBusServiceRegistry()->isServiceInstanceAlive(serviceInstanceId, serviceInterfaceName, serviceDomainName); +} + +std::shared_ptr DBusFactory::createProxy(const char* interfaceName, const std::string& participantId, const std::string& domain) { + std::string connectionName; + std::string objectPath; + + findFallbackInstanceIdMapping(participantId, connectionName, objectPath); + + if(!registeredProxyFactoryFunctions_) { + registeredProxyFactoryFunctions_ = new std::unordered_map {}; + } + + for (auto it = registeredProxyFactoryFunctions_->begin(); it != registeredProxyFactoryFunctions_->end(); ++it) { + if(it->first == interfaceName) { + return (it->second)(connectionName.c_str(), objectPath.c_str(), dbusConnection_); + } + } + + return NULL; +} + +std::shared_ptr DBusFactory::createAdapter(std::shared_ptr stubBase, const char* interfaceName, const std::string& participantId, const std::string& domain) { + assert(dbusConnection_->isConnected()); + + std::string connectionName; + std::string objectPath; + findFallbackInstanceIdMapping(participantId, connectionName, objectPath); + + if(acquiredConnectionName_ == "") { + dbusConnection_->requestServiceNameAndBlock(connectionName); + acquiredConnectionName_ = connectionName; + } else if (acquiredConnectionName_ != connectionName) { + return NULL; + } + + if(!registeredAdapterFactoryFunctions_) { + registeredAdapterFactoryFunctions_ = new std::unordered_map {}; + } + + for (auto it = registeredAdapterFactoryFunctions_->begin(); it != registeredAdapterFactoryFunctions_->end(); ++it) { + if(it->first == interfaceName) { + std::shared_ptr dbusStubAdapter = (it->second)(connectionName.c_str(), objectPath.c_str(), dbusConnection_, stubBase); + dbusStubAdapter->init(); + return dbusStubAdapter; + } + } + + return NULL; +} + + +} // namespace DBus +} // namespace CommonAPI diff --git a/CommonAPI-DBus/src/CommonAPI/DBus/DBusFactory.h b/CommonAPI-DBus/src/CommonAPI/DBus/DBusFactory.h new file mode 100644 index 0000000..239f018 --- /dev/null +++ b/CommonAPI-DBus/src/CommonAPI/DBus/DBusFactory.h @@ -0,0 +1,44 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#ifndef COMMONAPI_DBUS_DBUS_FACTORY_H_ +#define COMMONAPI_DBUS_DBUS_FACTORY_H_ + +#include + +#include + +#include "CommonAPI/DBus/DBusStubAdapter.h" +#include "DBusConnection.h" + +namespace CommonAPI { +namespace DBus { + +typedef std::shared_ptr (*DBusProxyFactoryFunction) (const char* busName, const char* objectPath, std::shared_ptr dbusProxyConnection); +typedef std::shared_ptr (*DBusAdapterFactoryFunction) (std::string busName, std::string objectPath, std::shared_ptr dbusProxyConnection, std::shared_ptr stubBase); + +class DBusFactory: public Factory { + public: + DBusFactory(std::shared_ptr runtime, const MiddlewareInfo* middlewareInfo); + virtual ~DBusFactory(); + + static void registerProxyFactoryMethod(std::string interfaceName, DBusProxyFactoryFunction proxyFactoryFunction); + static void registerAdapterFactoryMethod(std::string interfaceName, DBusAdapterFactoryFunction adapterFactoryMethod); + + virtual std::vector getAvailableServiceInstances(const std::string& serviceInterfaceName, const std::string& serviceDomainName = "local"); + + virtual bool isServiceInstanceAlive(const std::string& serviceInstanceID, const std::string& serviceInterfaceName, const std::string& serviceDomainName = "local"); + + virtual std::shared_ptr createProxy(const char* interfaceName, const std::string& participantId, const std::string& domain); + + virtual std::shared_ptr createAdapter(std::shared_ptr stubBase, const char* interfaceName, const std::string& participantId, const std::string& domain); + + private: + std::shared_ptr dbusConnection_; + std::string acquiredConnectionName_; +}; + +} // namespace DBus +} // namespace CommonAPI + +#endif // COMMONAPI_DBUS_DBUS_FACTORY_H_ diff --git a/CommonAPI-DBus/src/CommonAPI/DBus/DBusFunctionalHash.cpp b/CommonAPI-DBus/src/CommonAPI/DBus/DBusFunctionalHash.cpp new file mode 100644 index 0000000..f7890f5 --- /dev/null +++ b/CommonAPI-DBus/src/CommonAPI/DBus/DBusFunctionalHash.cpp @@ -0,0 +1,85 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include "DBusFunctionalHash.h" + +#include + +#include +#include + + +/* + * @see http://code.google.com/p/smhasher/ + */ +#define SMHASHER_SEED_VALUE 0xc70f6907UL + + +namespace std { + +size_t hash< pair >::operator()(const pair& t) const { + const char* a = t.first; + const char* b = t.second; + + assert(a); + assert(b); + + uint32_t seed = static_cast(SMHASHER_SEED_VALUE); + MurmurHash3_x86_32(a, strlen(a), seed, &seed); + MurmurHash3_x86_32(b, strlen(b), seed, &seed); + + return static_cast(seed); +} + + +size_t hash< pair >::operator()(const pair& t) const { + const string& a = t.first; + const string& b = t.second; + + uint32_t seed = static_cast(SMHASHER_SEED_VALUE); + MurmurHash3_x86_32(a.c_str(), a.length(), seed, &seed); + MurmurHash3_x86_32(b.c_str(), b.length(), seed, &seed); + + return static_cast(seed); +} + + +size_t hash< tuple >::operator()(const tuple& t) const { + const string& a = get<0>(t); + const string& b = get<1>(t); + const string& c = get<2>(t); + + uint32_t seed = static_cast(SMHASHER_SEED_VALUE); + MurmurHash3_x86_32(a.c_str(), a.length(), seed, &seed); + MurmurHash3_x86_32(b.c_str(), b.length(), seed, &seed); + MurmurHash3_x86_32(c.c_str(), c.length(), seed, &seed); + + return static_cast(seed); +} + + +size_t hash< tuple >::operator()(const tuple& t) const { + const string& a = get<0>(t); + const string& b = get<1>(t); + const string& c = get<2>(t); + const string& d = get<3>(t); + + uint32_t seed = static_cast(SMHASHER_SEED_VALUE); + MurmurHash3_x86_32(a.c_str(), a.length(), seed, &seed); + MurmurHash3_x86_32(b.c_str(), b.length(), seed, &seed); + MurmurHash3_x86_32(c.c_str(), c.length(), seed, &seed); + MurmurHash3_x86_32(d.c_str(), d.length(), seed, &seed); + + return static_cast(seed); +} + + +bool equal_to< pair >::operator()(const pair& a, + const pair& b) const { + if (a.first == b.first && a.second == b.second) + return true; + + return !strcmp(a.first, b.first) && !strcmp(a.second, b.second); +} + +} // namespace std diff --git a/CommonAPI-DBus/src/CommonAPI/DBus/DBusFunctionalHash.h b/CommonAPI-DBus/src/CommonAPI/DBus/DBusFunctionalHash.h new file mode 100644 index 0000000..54b89d9 --- /dev/null +++ b/CommonAPI-DBus/src/CommonAPI/DBus/DBusFunctionalHash.h @@ -0,0 +1,55 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#ifndef COMMONAPI_DBUS_DBUS_FUNCTIONAL_HASH_H_ +#define COMMONAPI_DBUS_DBUS_FUNCTIONAL_HASH_H_ + +#include +#include +#include + +namespace std { + +template<> +struct hash< pair >: + public unary_function< pair, size_t > { + + size_t operator()(const pair& t) const; +}; + + +template<> +struct hash< pair >: + public unary_function< pair, size_t > { + + size_t operator()(const pair& t) const; +}; + + +template<> +struct hash< tuple >: + public unary_function< tuple, size_t > { + + size_t operator()(const tuple& t) const; +}; + + +template<> +struct hash< tuple >: + public std::unary_function< tuple, size_t > { + + size_t operator()(const tuple& t) const; +}; + + +template<> +struct equal_to< pair >: public binary_function< pair, + pair, + bool> { + + bool operator()(const pair& a, const pair& b) const; +}; + +} // namespace std + +#endif // COMMONAPI_DBUS_DBUS_FUNCTIONAL_HASH_H_ diff --git a/CommonAPI-DBus/src/CommonAPI/DBus/DBusHelper.h b/CommonAPI-DBus/src/CommonAPI/DBus/DBusHelper.h new file mode 100644 index 0000000..a8c285e --- /dev/null +++ b/CommonAPI-DBus/src/CommonAPI/DBus/DBusHelper.h @@ -0,0 +1,34 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#ifndef COMMONAPI_DBUS_DBUS_HELPER_H_ +#define COMMONAPI_DBUS_DBUS_HELPER_H_ + +namespace CommonAPI { +namespace DBus { + +template +struct index_sequence {}; + + +template +struct make_sequence : make_sequence {}; + +template +struct make_sequence<0, S...> { + typedef index_sequence type; +}; + + +template +struct make_sequence_range : make_sequence_range {}; + +template +struct make_sequence_range<0, _Offset, S...> { + typedef index_sequence type; +}; + +} // namespace DBus +} // namespace CommonAPI + +#endif // COMMONAPI_DBUS_DBUS_HELPER_H_ diff --git a/CommonAPI-DBus/src/CommonAPI/DBus/DBusInputStream.cpp b/CommonAPI-DBus/src/CommonAPI/DBus/DBusInputStream.cpp new file mode 100644 index 0000000..6f1d8ae --- /dev/null +++ b/CommonAPI-DBus/src/CommonAPI/DBus/DBusInputStream.cpp @@ -0,0 +1,233 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include "DBusInputStream.h" + +namespace CommonAPI { +namespace DBus { + +DBusInputStream::DBusInputStream(const CommonAPI::DBus::DBusMessage& message) : + message_(message), + dataBegin_(message.getBodyData()), + currentDataPosition_(0), + dataLength_(message.getBodyLength()), + exception_(nullptr) { +} + +DBusInputStream::~DBusInputStream() { +} + +const CommonAPI::DBus::DBusError& DBusInputStream::getError() const { + return *exception_; +} + +bool DBusInputStream::isErrorSet() const { + return exception_ != nullptr; +} + +void DBusInputStream::clearError() { + exception_ = nullptr; +} + +void DBusInputStream::alignToBoundary(const size_t alignBoundary) { + const unsigned int alignMask = alignBoundary - 1; + currentDataPosition_ = (currentDataPosition_ + alignMask) & (~alignMask); +} + +char* DBusInputStream::readRawData(const size_t numBytesToRead) { + assert((currentDataPosition_ + numBytesToRead) <= dataLength_); + + char* dataPtr = (char*) (dataBegin_ + currentDataPosition_); + currentDataPosition_ += numBytesToRead; + return dataPtr; +} + +template <> +DBusInputStream& DBusInputStream::readBasicTypeValue(float& val) { + if (sizeof(val) > 1) + alignToBoundary(sizeof(double)); + + val = (float)(*(reinterpret_cast(readRawData(sizeof(double))))); + return *this; +} + +InputStream& DBusInputStream::readValue(bool& boolValue) { + alignToBoundary(4); + return readBasicTypeValue(boolValue); +} + +InputStream& DBusInputStream::readValue(int8_t& int8Value) { return readBasicTypeValue(int8Value); } +InputStream& DBusInputStream::readValue(int16_t& int16Value) { return readBasicTypeValue(int16Value); } +InputStream& DBusInputStream::readValue(int32_t& int32Value) { return readBasicTypeValue(int32Value); } +InputStream& DBusInputStream::readValue(int64_t& int64Value) { return readBasicTypeValue(int64Value); } + +InputStream& DBusInputStream::readValue(uint8_t& uint8Value) { return readBasicTypeValue(uint8Value); } +InputStream& DBusInputStream::readValue(uint16_t& uint16Value) { return readBasicTypeValue(uint16Value); } +InputStream& DBusInputStream::readValue(uint32_t& uint32Value) { return readBasicTypeValue(uint32Value); } +InputStream& DBusInputStream::readValue(uint64_t& uint64Value) { return readBasicTypeValue(uint64Value); } + +InputStream& DBusInputStream::readValue(float& floatValue) { return readBasicTypeValue(floatValue); } +InputStream& DBusInputStream::readValue(double& doubleValue) { return readBasicTypeValue(doubleValue); } + +InputStream& DBusInputStream::readValue(std::string& stringValue) { + uint32_t lengthOfString; + readValue(lengthOfString); + + // length field does not include terminating 0-byte, therefore length of data to read is +1 + char* dataPtr = readRawData(lengthOfString + 1); + + // The string contained in a DBus-message is required to be 0-terminated, therefore the following line works + stringValue = dataPtr; + + return *this; +} + +InputStream& DBusInputStream::readValue(ByteBuffer& byteBufferValue) { + *this >> byteBufferValue; + return *this; +} + +InputStream& DBusInputStream::readEnumValue(int8_t& int8BackingTypeValue) { return readValue(int8BackingTypeValue); } +InputStream& DBusInputStream::readEnumValue(int16_t& int16BackingTypeValue) { return readValue(int16BackingTypeValue); } +InputStream& DBusInputStream::readEnumValue(int32_t& int32BackingTypeValue) { return readValue(int32BackingTypeValue); } +InputStream& DBusInputStream::readEnumValue(int64_t& int64BackingTypeValue) { return readValue(int64BackingTypeValue); } +InputStream& DBusInputStream::readEnumValue(uint8_t& uint8BackingTypeValue) { return readValue(uint8BackingTypeValue); } +InputStream& DBusInputStream::readEnumValue(uint16_t& uint16BackingTypeValue) { return readValue(uint16BackingTypeValue); } +InputStream& DBusInputStream::readEnumValue(uint32_t& uint32BackingTypeValue) { return readValue(uint32BackingTypeValue); } +InputStream& DBusInputStream::readEnumValue(uint64_t& uint64BackingTypeValue) { return readValue(uint64BackingTypeValue); } + +InputStream& DBusInputStream::readVersionValue(Version& versionValue) { + alignToBoundary(8); + readValue(versionValue.Major); + readValue(versionValue.Minor); + return *this; +} + +void DBusInputStream::beginReadSerializableStruct(const SerializableStruct& serializableStruct) { + alignToBoundary(8); +} + +void DBusInputStream::endReadSerializableStruct(const SerializableStruct& serializableStruct) { } + + +void DBusInputStream::beginReadBoolVector() { + beginReadGenericVector(); + savedStreamPositions_.push(currentDataPosition_); +} + +void DBusInputStream::beginReadInt8Vector() { + beginReadGenericVector(); + savedStreamPositions_.push(currentDataPosition_); +} + +void DBusInputStream::beginReadInt16Vector() { + beginReadGenericVector(); + savedStreamPositions_.push(currentDataPosition_); +} + +void DBusInputStream::beginReadInt32Vector() { + beginReadGenericVector(); + savedStreamPositions_.push(currentDataPosition_); +} + +void DBusInputStream::beginReadInt64Vector() { + beginReadGenericVector(); + alignToBoundary(8); + savedStreamPositions_.push(currentDataPosition_); +} + +void DBusInputStream::beginReadUInt8Vector() { + beginReadGenericVector(); + savedStreamPositions_.push(currentDataPosition_); +} + +void DBusInputStream::beginReadUInt16Vector() { + beginReadGenericVector(); + savedStreamPositions_.push(currentDataPosition_); +} + +void DBusInputStream::beginReadUInt32Vector() { + beginReadGenericVector(); + savedStreamPositions_.push(currentDataPosition_); +} + +void DBusInputStream::beginReadUInt64Vector() { + beginReadGenericVector(); + alignToBoundary(8); + savedStreamPositions_.push(currentDataPosition_); +} + +void DBusInputStream::beginReadFloatVector() { + beginReadGenericVector(); + alignToBoundary(8); + savedStreamPositions_.push(currentDataPosition_); +} + +void DBusInputStream::beginReadDoubleVector() { + beginReadGenericVector(); + alignToBoundary(8); + savedStreamPositions_.push(currentDataPosition_); +} + +void DBusInputStream::beginReadStringVector() { + beginReadGenericVector(); + savedStreamPositions_.push(currentDataPosition_); +} + +void DBusInputStream::beginReadByteBufferVector() { + beginReadGenericVector(); + savedStreamPositions_.push(currentDataPosition_); +} + +void DBusInputStream::beginReadVersionVector() { + beginReadGenericVector(); + alignToBoundary(8); + savedStreamPositions_.push(currentDataPosition_); +} + +void DBusInputStream::beginReadVectorOfSerializableStructs() { + beginReadGenericVector(); + alignToBoundary(8); + savedStreamPositions_.push(currentDataPosition_); +} + +void DBusInputStream::beginReadVectorOfVectors() { + beginReadGenericVector(); + savedStreamPositions_.push(currentDataPosition_); +} + +void DBusInputStream::beginReadVectorOfMaps() { + beginReadGenericVector(); + alignToBoundary(8); + savedStreamPositions_.push(currentDataPosition_); +} + +bool DBusInputStream::hasMoreVectorElements() { + return bytesToRead_.top() > currentDataPosition_ - savedStreamPositions_.top(); +} + +void DBusInputStream::endReadVector() { + bytesToRead_.pop(); + savedStreamPositions_.pop(); +} + +void DBusInputStream::beginReadMap() { + uint32_t vectorByteSize; + readBasicTypeValue(vectorByteSize); + bytesToRead_.push(vectorByteSize); + alignToBoundary(8); + savedStreamPositions_.push(currentDataPosition_); +} + +bool DBusInputStream::hasMoreMapElements() { + return bytesToRead_.top() > currentDataPosition_ - savedStreamPositions_.top(); +} + +void DBusInputStream::endReadMap() { + bytesToRead_.pop(); + savedStreamPositions_.pop(); +} + + +} // namespace DBus +} // namespace CommonAPI diff --git a/CommonAPI-DBus/src/CommonAPI/DBus/DBusInputStream.h b/CommonAPI-DBus/src/CommonAPI/DBus/DBusInputStream.h new file mode 100644 index 0000000..0ab77d4 --- /dev/null +++ b/CommonAPI-DBus/src/CommonAPI/DBus/DBusInputStream.h @@ -0,0 +1,209 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#ifndef COMMONAPI_DBUS_DBUS_INPUT_STREAM_H_ +#define COMMONAPI_DBUS_DBUS_INPUT_STREAM_H_ + +#include "DBusError.h" +#include "DBusMessage.h" + +#include + +#include +#include +#include +#include +#include + +namespace CommonAPI { +namespace DBus { + +/** + * Used to mark the position of a pointer within an array of bytes. + */ +typedef uint32_t position_t; + +/** + * @class DBusInputMessageStream + * + * Used to deserialize and read data from a #DBusMessage. For all data types that can be read from a #DBusMessage, a ">>"-operator should be defined to handle the reading + * (this operator is predefined for all basic data types and for vectors). + */ +class DBusInputStream: public InputStream { + public: + virtual bool hasError() const { return isErrorSet(); } + + virtual InputStream& readValue(bool& boolValue); + + virtual InputStream& readValue(int8_t& int8Value); + virtual InputStream& readValue(int16_t& int16Value); + virtual InputStream& readValue(int32_t& int32Value); + virtual InputStream& readValue(int64_t& int64Value); + + virtual InputStream& readValue(uint8_t& uint8Value); + virtual InputStream& readValue(uint16_t& uint16Value); + virtual InputStream& readValue(uint32_t& uint32Value); + virtual InputStream& readValue(uint64_t& uint64Value); + + virtual InputStream& readValue(float& floatValue); + virtual InputStream& readValue(double& doubleValue); + + virtual InputStream& readValue(std::string& stringValue); + virtual InputStream& readValue(ByteBuffer& byteBufferValue); + + virtual InputStream& readEnumValue(int8_t& int8BackingTypeValue); + virtual InputStream& readEnumValue(int16_t& int16BackingTypeValue); + virtual InputStream& readEnumValue(int32_t& int32BackingTypeValue); + virtual InputStream& readEnumValue(int64_t& int64BackingTypeValue); + virtual InputStream& readEnumValue(uint8_t& uint8BackingTypeValue); + virtual InputStream& readEnumValue(uint16_t& uint16BackingTypeValue); + virtual InputStream& readEnumValue(uint32_t& uint32BackingTypeValue); + virtual InputStream& readEnumValue(uint64_t& uint64BackingTypeValue); + + virtual InputStream& readVersionValue(Version& versionValue); + + virtual void beginReadSerializableStruct(const SerializableStruct& serializableStruct); + virtual void endReadSerializableStruct(const SerializableStruct& serializableStruct); + + virtual void beginReadBoolVector(); + virtual void beginReadInt8Vector(); + virtual void beginReadInt16Vector(); + virtual void beginReadInt32Vector(); + virtual void beginReadInt64Vector(); + virtual void beginReadUInt8Vector(); + virtual void beginReadUInt16Vector(); + virtual void beginReadUInt32Vector(); + virtual void beginReadUInt64Vector(); + virtual void beginReadFloatVector(); + virtual void beginReadDoubleVector(); + virtual void beginReadStringVector(); + virtual void beginReadByteBufferVector(); + virtual void beginReadVersionVector(); + virtual void beginReadVectorOfSerializableStructs(); + virtual void beginReadVectorOfVectors(); + virtual void beginReadVectorOfMaps(); + + virtual bool hasMoreVectorElements(); + virtual void endReadVector(); + + virtual void beginReadMap(); + virtual bool hasMoreMapElements(); + virtual void endReadMap(); + + + /** + * Creates a #DBusInputMessageStream which can be used to deserialize and read data from the given #DBusMessage. + * As no message-signature is checked, the user is responsible to ensure that the correct data types are read in the correct order. + * + * @param message the #DBusMessage from which data should be read. + */ + DBusInputStream(const CommonAPI::DBus::DBusMessage& message); + DBusInputStream(const DBusInputStream& imessagestream) = delete; + + /** + * Destructor; does not call the destructor of the referred #DBusMessage. Make sure to maintain a reference to the + * #DBusMessage outside of the stream if you intend to make further use of the message. + */ + ~DBusInputStream(); + + /** + * Marks the stream as erroneous. + */ + void setError(); + + /** + * @return An instance of #DBusError if this stream is in an erroneous state, NULL otherwise + */ + const CommonAPI::DBus::DBusError& getError() const; + + /** + * @return true if this stream is in an erroneous state, false otherwise. + */ + bool isErrorSet() const; + + /** + * Marks the state of the stream as cleared from all errors. Further reading is possible afterwards. + * The stream will have maintained the last valid position from before its state became erroneous. + */ + void clearError(); + + /** + * Aligns the stream to the given byte boundary, i.e. the stream skips as many bytes as are necessary to execute the next read + * starting from the given boundary. + * + * @param alignBoundary the byte boundary to which the stream needs to be aligned. + */ + void alignToBoundary(const size_t alignBoundary); + + /** + * Reads the given number of bytes and returns them as an array of characters. + * + * Actually, for performance reasons this command only returns a pointer to the current position in the stream, + * and then increases the position of this pointer by the number of bytes indicated by the given parameter. + * It is the user's responsibility to actually use only the number of bytes he indicated he would use. + * It is assumed the user knows what kind of value is stored next in the #DBusMessage the data is streamed from. + * Using a reinterpret_cast on the returned pointer should then restore the original value. + * + * Example use case: + * @code + * ... + * inputMessageStream.alignForBasicType(sizeof(int32_t)); + * char* const dataPtr = inputMessageStream.read(sizeof(int32_t)); + * int32_t val = *(reinterpret_cast(dataPtr)); + * ... + * @endcode + */ + char* readRawData(const size_t numBytesToRead); + + /** + * Handles all reading of basic types from a given #DBusInputMessageStream. + * Basic types in this context are: uint8_t, uint16_t, uint32_t, uint64_t, int8_t, int16_t, int32_t, int64_t, float, double. + * Any types not listed here (especially all complex types, e.g. structs, unions etc.) need to provide a + * specialized implementation of this operator. + * + * @tparam _BasicType The type of the value that is to be read from the given stream. + * @param val The variable in which the retrieved value is to be stored + * @param inputMessageStream The stream which the value is to be read from + * @return The given inputMessageStream to allow for successive reading + */ + template + DBusInputStream& readBasicTypeValue(_BasicType& val) { + if (sizeof(val) > 1) + alignToBoundary(sizeof(_BasicType)); + + val = *(reinterpret_cast<_BasicType*>(readRawData(sizeof(_BasicType)))); + return *this; + } + + /** + * Returns the position of the reading pointer, relative to the beginning of the data stream. + */ + position_t getCurrentPosition() const; + + private: + inline void beginReadGenericVector() { + uint32_t vectorByteSize; + readBasicTypeValue(vectorByteSize); + bytesToRead_.push(vectorByteSize); + } + + char* dataBegin_; + position_t currentDataPosition_; + size_t dataLength_; + CommonAPI::DBus::DBusError* exception_; + CommonAPI::DBus::DBusMessage message_; + + std::stack bytesToRead_; + std::stack savedStreamPositions_; +}; + + +inline void DBusInputStream::setError() { + exception_ = new CommonAPI::DBus::DBusError(); +} + + +} // namespace DBus +} // namespace CommonAPI + +#endif // COMMONAPI_DBUS_DBUS_INPUT_STREAM_H_ diff --git a/CommonAPI-DBus/src/CommonAPI/DBus/DBusMessage.cpp b/CommonAPI-DBus/src/CommonAPI/DBus/DBusMessage.cpp new file mode 100644 index 0000000..5e032e9 --- /dev/null +++ b/CommonAPI-DBus/src/CommonAPI/DBus/DBusMessage.cpp @@ -0,0 +1,239 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include "DBusMessage.h" + +#include +#include + +namespace CommonAPI { +namespace DBus { + +DBusMessage::DBusMessage(): + libdbusMessage_(NULL) { +} + +DBusMessage::DBusMessage(::DBusMessage* libdbusMessage) { + libdbusMessage_ = libdbusMessage != NULL ? dbus_message_ref(libdbusMessage) : NULL; +} + +DBusMessage::DBusMessage(::DBusMessage* libdbusMessage, bool increaseReferenceCount) { + assert(libdbusMessage); + + libdbusMessage_ = increaseReferenceCount ? dbus_message_ref(libdbusMessage) : libdbusMessage; +} + +DBusMessage::DBusMessage(const DBusMessage& src) { + libdbusMessage_ = src.libdbusMessage_ != NULL ? dbus_message_ref(src.libdbusMessage_) : NULL; +} + +DBusMessage::DBusMessage(DBusMessage&& rsrc) { + libdbusMessage_ = rsrc.libdbusMessage_; + rsrc.libdbusMessage_ = NULL; +} + +DBusMessage::~DBusMessage() { + if (libdbusMessage_) + dbus_message_unref(libdbusMessage_); +} + +DBusMessage& DBusMessage::operator=(const DBusMessage& src) { + if (this != &src) { + if (libdbusMessage_) + dbus_message_unref(libdbusMessage_); + + libdbusMessage_ = src.libdbusMessage_ != NULL ? dbus_message_ref(src.libdbusMessage_) : NULL; + } + + return *this; +} + +DBusMessage& DBusMessage::operator=(DBusMessage&& rsrc) { + if (this != &rsrc) { + if (libdbusMessage_) + dbus_message_unref(libdbusMessage_); + + libdbusMessage_ = rsrc.libdbusMessage_; + rsrc.libdbusMessage_ = NULL; + } + + return *this; +} + +DBusMessage::operator bool() const { + const bool isNotNullDBusMessage = (libdbusMessage_ != NULL); + return isNotNullDBusMessage; +} + +DBusMessage DBusMessage::createOrgFreedesktopOrgMethodCall(const char* methodName, const char* signature) { + return DBusMessage::createMethodCall("org.freedesktop.DBus", + "/", + "org.freedesktop.DBus", + methodName, + signature); +} + +DBusMessage DBusMessage::createOrgFreedesktopOrgMethodCall(const std::string& methodName, + const std::string& signature) { + assert(!methodName.empty()); + + return createOrgFreedesktopOrgMethodCall(methodName.c_str(), + signature.empty() ? NULL : signature.c_str()); +} + +DBusMessage DBusMessage::createMethodCall(const char* busName, + const char* objectPath, + const char* interfaceName, + const char* methodName, + const char* signature) { + assert(busName); + assert(objectPath); + assert(interfaceName); + assert(methodName); + + ::DBusMessage* libdbusMessageCall = dbus_message_new_method_call(busName, + objectPath, + interfaceName, + methodName); + assert(libdbusMessageCall); + + if (signature) + dbus_message_set_signature(libdbusMessageCall, signature); + + const bool increaseLibdbusMessageReferenceCount = false; + return DBusMessage(libdbusMessageCall, increaseLibdbusMessageReferenceCount); +} + +DBusMessage DBusMessage::createMethodCall(const std::string& busName, + const std::string& objectPath, + const std::string& interfaceName, + const std::string& methodName, + const std::string& signature) { + assert(!busName.empty()); + assert(!objectPath.empty()); + assert(!interfaceName.empty()); + assert(!methodName.empty()); + + return createMethodCall(busName.c_str(), + objectPath.c_str(), + interfaceName.c_str(), + methodName.c_str(), + signature.empty() ? NULL : signature.c_str()); +} + +DBusMessage DBusMessage::createMethodReturn(const char* signature) const { + ::DBusMessage* libdbusMessageReturn = dbus_message_new_method_return(libdbusMessage_); + assert(libdbusMessageReturn); + + if (signature) + dbus_message_set_signature(libdbusMessageReturn, signature); + + const bool increaseLibdbusMessageReferenceCount = false; + return DBusMessage(libdbusMessageReturn, increaseLibdbusMessageReferenceCount); +} + +DBusMessage DBusMessage::createMethodReturn(const std::string& signature) const { + return createMethodReturn(signature.empty() ? NULL : signature.c_str()); +} + +DBusMessage DBusMessage::createSignal(const char* objectPath, + const char* interfaceName, + const char* signalName, + const char* signature) { + assert(objectPath); + assert(interfaceName); + assert(signalName); + + ::DBusMessage* libdbusMessageSignal = dbus_message_new_signal(objectPath, + interfaceName, + signalName); + assert(libdbusMessageSignal); + + if (signature) + dbus_message_set_signature(libdbusMessageSignal, signature); + + const bool increaseLibdbusMessageReferenceCount = false; + return DBusMessage(libdbusMessageSignal, increaseLibdbusMessageReferenceCount); +} + +DBusMessage DBusMessage::createSignal(const std::string& objectPath, + const std::string& interfaceName, + const std::string& signalName, + const std::string& signature) { + assert(!objectPath.empty()); + assert(!interfaceName.empty()); + assert(!signalName.empty()); + + return createSignal(objectPath.c_str(), + interfaceName.c_str(), + signalName.c_str(), + signature.empty() ? NULL : signature.c_str()); +} + +const char* DBusMessage::getObjectPath() const { + return dbus_message_get_path(libdbusMessage_); +} + +const char* DBusMessage::getSenderName() const { + return dbus_message_get_sender(libdbusMessage_); +} + +const char* DBusMessage::getInterfaceName() const { + return dbus_message_get_interface(libdbusMessage_); +} + +const char* DBusMessage::getMemberName() const { + return dbus_message_get_member(libdbusMessage_); +} + +const char* DBusMessage::getSignatureString() const { + return dbus_message_get_signature(libdbusMessage_); +} + +const char* DBusMessage::getErrorName() const { + assert(isErrorType()); + + return dbus_message_get_error_name(libdbusMessage_); +} + +bool DBusMessage::hasMemberName(const char* memberName) const { + const char* dbusMessageMemberName = getMemberName(); + + assert(memberName); + assert(dbusMessageMemberName); + + return !strcmp(dbusMessageMemberName, memberName); +} + +bool DBusMessage::hasSignature(const char* signature) const { + const char* dbusMessageSignature = getSignatureString(); + + assert(signature); + assert(dbusMessageSignature); + + return !strcmp(dbusMessageSignature, signature); +} + +const DBusMessage::Type DBusMessage::getType() const { + const int libdbusType = dbus_message_get_type(libdbusMessage_); + return static_cast(libdbusType); +} + +char* DBusMessage::getBodyData() const { + return dbus_message_get_body(libdbusMessage_); +} + +int DBusMessage::getBodyLength() const { + return dbus_message_get_body_length(libdbusMessage_); +} + +int DBusMessage::getBodySize() const { + return dbus_message_get_body_allocated(libdbusMessage_); +} + +bool DBusMessage::setBodyLength(const int bodyLength) { + return dbus_message_set_body_length(libdbusMessage_, bodyLength); +} + +} // namespace DBus +} // namespace CommonAPI diff --git a/CommonAPI-DBus/src/CommonAPI/DBus/DBusMessage.h b/CommonAPI-DBus/src/CommonAPI/DBus/DBusMessage.h new file mode 100644 index 0000000..aefa305 --- /dev/null +++ b/CommonAPI-DBus/src/CommonAPI/DBus/DBusMessage.h @@ -0,0 +1,121 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#ifndef COMMONAPI_DBUS_DBUS_MESSAGE_H_ +#define COMMONAPI_DBUS_DBUS_MESSAGE_H_ + +#include + +#include + +namespace CommonAPI { +namespace DBus { + +class DBusConnection; + +class DBusMessage { + public: + DBusMessage(); + DBusMessage(::DBusMessage* libdbusMessage); + DBusMessage(::DBusMessage* libdbusMessage, bool increaseReferenceCount); + DBusMessage(const DBusMessage& src); + DBusMessage(DBusMessage&& src); + + ~DBusMessage(); + + DBusMessage& operator=(const DBusMessage& src); + DBusMessage& operator=(DBusMessage&& rsrc); + operator bool() const; + + static DBusMessage createOrgFreedesktopOrgMethodCall(const char* methodName, + const char* signature = NULL); + + static DBusMessage createOrgFreedesktopOrgMethodCall(const std::string& methodName, + const std::string& signature = ""); + + static DBusMessage createMethodCall(const char* busName, + const char* objectPath, + const char* interfaceName, + const char* methodName, + const char* signature = NULL); + + static DBusMessage createMethodCall(const std::string& busName, + const std::string& objectPath, + const std::string& interfaceName, + const std::string& methodName, + const std::string& signature = ""); + + DBusMessage createMethodReturn(const char* signature = NULL) const; + + DBusMessage createMethodReturn(const std::string& signature) const; + + static DBusMessage createSignal(const char* objectPath, + const char* interfaceName, + const char* signalName, + const char* signature = NULL); + + static DBusMessage createSignal(const std::string& objectPath, + const std::string& interfaceName, + const std::string& signalName, + const std::string& signature = ""); + + const char* getSenderName() const; + const char* getObjectPath() const; + const char* getInterfaceName() const; + const char* getMemberName() const; + const char* getSignatureString() const; + const char* getErrorName() const; + + bool hasMemberName(const char* memberName) const; + bool hasSignature(const char* signature) const; + + enum class Type: int { + Invalid = DBUS_MESSAGE_TYPE_INVALID, + MethodCall = DBUS_MESSAGE_TYPE_METHOD_CALL, + MethodReturn = DBUS_MESSAGE_TYPE_METHOD_RETURN, + Error = DBUS_MESSAGE_TYPE_ERROR, + Signal = DBUS_MESSAGE_TYPE_SIGNAL + }; + const Type getType() const; + inline bool isInvalidType() const; + inline bool isMethodCallType() const; + inline bool isMethodReturnType() const; + inline bool isErrorType() const; + inline bool isSignalType() const; + + char* getBodyData() const; + int getBodyLength() const; + int getBodySize() const; + + bool setBodyLength(const int bodyLength); + + private: + ::DBusMessage* libdbusMessage_; + + friend class DBusConnection; +}; + +bool DBusMessage::isInvalidType() const { + return (getType() == Type::Invalid); +} + +bool DBusMessage::isMethodCallType() const { + return (getType() == Type::MethodCall); +} + +bool DBusMessage::isMethodReturnType() const { + return (getType() == Type::MethodReturn); +} + +bool DBusMessage::isErrorType() const { + return (getType() == Type::Error); +} + +bool DBusMessage::isSignalType() const { + return (getType() == Type::Signal); +} + +} // namespace DBus +} // namespace CommonAPI + +#endif // COMMONAPI_DBUS_DBUS_MESSAGE_H_ diff --git a/CommonAPI-DBus/src/CommonAPI/DBus/DBusMultiEvent.h b/CommonAPI-DBus/src/CommonAPI/DBus/DBusMultiEvent.h new file mode 100644 index 0000000..7bb47a5 --- /dev/null +++ b/CommonAPI-DBus/src/CommonAPI/DBus/DBusMultiEvent.h @@ -0,0 +1,113 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#ifndef COMMONAPI_DBUS_DBUS_MULTI_EVENT_H_ +#define COMMONAPI_DBUS_DBUS_MULTI_EVENT_H_ + +#include + +#include +#include + +namespace CommonAPI { +namespace DBus { + +template +class DBusMultiEvent { + public: + typedef std::function Listener; + typedef std::unordered_multimap ListenersMap; + typedef typename ListenersMap::iterator Subscription; + + Subscription subscribeAll(const Listener& listener); + Subscription subscribe(const std::string& name, const Listener& listener); + + void unsubscribe(Subscription listenerSubscription); + + virtual ~DBusMultiEvent() { } + + protected: + SubscriptionStatus notifyListeners(const std::string& name, const _Arguments&... eventArguments); + + virtual void onFirstListenerAdded(const std::string& name, const Listener& listener) { } + virtual void onListenerAdded(const std::string& name, const Listener& listener) { } + + virtual void onListenerRemoved(const std::string& name, const Listener& listener) { } + virtual void onLastListenerRemoved(const std::string& name, const Listener& listener) { } + + private: + typedef std::pair IteratorRange; + SubscriptionStatus notifyListenersRange(const std::string& name, IteratorRange listenersRange, const _Arguments&... eventArguments); + + ListenersMap listenersMap_; +}; + +template +typename DBusMultiEvent<_Arguments...>::Subscription +DBusMultiEvent<_Arguments...>::subscribeAll(const Listener& listener) { + return subscribe(std::string(), listener); +} + +template +typename DBusMultiEvent<_Arguments...>::Subscription +DBusMultiEvent<_Arguments...>::subscribe(const std::string& name, const Listener& listener) { + const bool firstListenerAdded = listenersMap_.empty(); + + auto listenerSubscription = listenersMap_.insert({name, listener}); + + if (firstListenerAdded) + onFirstListenerAdded(name, listener); + + onListenerAdded(name, listener); + + return listenerSubscription; +} + +template +void DBusMultiEvent<_Arguments...>::unsubscribe(Subscription listenerSubscription) { + const std::string name = listenerSubscription->first; + const Listener listener = listenerSubscription->second; + + listenersMap_.erase(listenerSubscription); + + onListenerRemoved(name, listener); + + const bool lastListenerRemoved = listenersMap_.empty(); + if (lastListenerRemoved) + onLastListenerRemoved(name, listener); +} + +template +SubscriptionStatus DBusMultiEvent<_Arguments...>::notifyListeners(const std::string& name, const _Arguments&... eventArguments) { + const SubscriptionStatus subscriptionStatus = notifyListenersRange(name, listenersMap_.equal_range(name), eventArguments...); + + if (subscriptionStatus == SubscriptionStatus::CANCEL) + return SubscriptionStatus::CANCEL; + + return notifyListenersRange(name, listenersMap_.equal_range(std::string()), eventArguments...); +} + +template +SubscriptionStatus DBusMultiEvent<_Arguments...>::notifyListenersRange( + const std::string& name, + IteratorRange listenersRange, + const _Arguments&... eventArguments) { + for (auto iterator = listenersRange.first; iterator != listenersRange.second; ) { + const Listener& listener = iterator->second; + const SubscriptionStatus listenerSubcriptionStatus = listener(name, eventArguments...); + + if (listenerSubcriptionStatus == SubscriptionStatus::CANCEL) { + auto listenerIterator = iterator; + listenersMap_.erase(listenerIterator); + iterator++; + } else + iterator++; + } + + return listenersMap_.empty() ? SubscriptionStatus::CANCEL : SubscriptionStatus::RETAIN; +} + +} // namespace DBus +} // namespace CommonAPI + +#endif // COMMONAPI_DBUS_DBUS_MULTI_EVENT_H_ diff --git a/CommonAPI-DBus/src/CommonAPI/DBus/DBusObjectManager.cpp b/CommonAPI-DBus/src/CommonAPI/DBus/DBusObjectManager.cpp new file mode 100644 index 0000000..42a53b7 --- /dev/null +++ b/CommonAPI-DBus/src/CommonAPI/DBus/DBusObjectManager.cpp @@ -0,0 +1,98 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include "DBusObjectManager.h" +#include "DBusOutputStream.h" + +#include + +namespace CommonAPI { +namespace DBus { + +DBusObjectManager::DBusObjectManager(const std::shared_ptr& dbusConnection): + dbusConnection_(dbusConnection) { + + registerInterfaceHandler("/", + "org.freedesktop.DBus.ObjectManager", + std::bind(&DBusObjectManager::onGetDBusObjectManagerData, this, std::placeholders::_1)); +} + +DBusInterfaceHandlerToken DBusObjectManager::registerInterfaceHandler(const std::string& objectPath, + const std::string& interfaceName, + const DBusMessageInterfaceHandler& dbusMessageInterfaceHandler) { + DBusInterfaceHandlerPath handlerPath(objectPath, interfaceName); + bool noSuchHandlerRegistered = dbusRegisteredObjectsTable_.find(handlerPath) == dbusRegisteredObjectsTable_.end(); + + assert(noSuchHandlerRegistered); + + dbusRegisteredObjectsTable_.insert({handlerPath, dbusMessageInterfaceHandler}); + dbusConnection_->registerObjectPath(objectPath); + + return handlerPath; +} + +void DBusObjectManager::unregisterInterfaceHandler(const DBusInterfaceHandlerToken& dbusInterfaceHandlerToken) { + const std::string& objectPath = dbusInterfaceHandlerToken.first; + + dbusConnection_->unregisterObjectPath(objectPath); + + dbusRegisteredObjectsTable_.erase(dbusInterfaceHandlerToken); +} + +bool DBusObjectManager::handleMessage(const DBusMessage& dbusMessage) const { + const char* objectPath = dbusMessage.getObjectPath(); + const char* interfaceName = dbusMessage.getInterfaceName(); + + assert(objectPath); + assert(interfaceName); + + DBusInterfaceHandlerPath handlerPath(objectPath, interfaceName); + auto handlerIterator = dbusRegisteredObjectsTable_.find(handlerPath); + const bool foundDBusInterfaceHandler = handlerIterator != dbusRegisteredObjectsTable_.end(); + bool dbusMessageHandled = false; + + if (foundDBusInterfaceHandler) { + const DBusMessageInterfaceHandler& interfaceHandlerDBusMessageHandler = handlerIterator->second; + dbusMessageHandled = interfaceHandlerDBusMessageHandler(dbusMessage); + } + + return dbusMessageHandled; +} + +bool DBusObjectManager::onGetDBusObjectManagerData(const DBusMessage& callMessage) { + + DBusObjectToInterfaceDict dictToSend; + + const char* interfaceName = callMessage.getInterfaceName(); + const char* signature = callMessage.getSignatureString(); + + assert(!strcmp(interfaceName, "org.freedesktop.DBus.ObjectManager")); + assert(!strcmp(signature, "")); + assert(callMessage.getType() == DBusMessage::Type::MethodCall); + + auto registeredObjectsIterator = dbusRegisteredObjectsTable_.begin(); + + while(registeredObjectsIterator != dbusRegisteredObjectsTable_.end()) { + DBusInterfaceHandlerPath handlerPath = registeredObjectsIterator->first; + auto foundDictEntry = dictToSend.find(handlerPath.first); + + if(foundDictEntry == dictToSend.end()) { + dictToSend.insert( { handlerPath.first, { { handlerPath.second, {} } } } ); + } else { + foundDictEntry->second.insert( {handlerPath.second, {} } ); + } + + ++registeredObjectsIterator; + } + + DBusMessage replyMessage = callMessage.createMethodReturn(DBusServiceRegistry::getManagedObjectsDBusSignature_); + + DBusOutputStream outStream(replyMessage); + outStream << dictToSend; + outStream.flush(); + return dbusConnection_->sendDBusMessage(replyMessage); +} + + +} // namespace DBus +} // namespace CommonAPI diff --git a/CommonAPI-DBus/src/CommonAPI/DBus/DBusObjectManager.h b/CommonAPI-DBus/src/CommonAPI/DBus/DBusObjectManager.h new file mode 100644 index 0000000..ed1d599 --- /dev/null +++ b/CommonAPI-DBus/src/CommonAPI/DBus/DBusObjectManager.h @@ -0,0 +1,54 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#ifndef COMMONAPI_DBUS_DBUS_OBJECT_MANAGER_H_ +#define COMMONAPI_DBUS_DBUS_OBJECT_MANAGER_H_ + +#include "DBusMessage.h" +#include "DBusConnection.h" + +namespace CommonAPI { +namespace DBus { + +// objectPath, interfaceName +typedef std::function DBusMessageInterfaceHandler; +typedef std::pair DBusInterfaceHandlerPath; +typedef DBusInterfaceHandlerPath DBusInterfaceHandlerToken; + +class DBusConnection; + +class DBusObjectManager { + public: + DBusObjectManager(const std::shared_ptr&); + + void init(); + + const DBusInterfaceHandlerToken registerInterfaceHandlerForDBusObject(const std::string& objectPath, + const std::string& interfaceName, + const DBusMessageInterfaceHandler& dbusMessageInterfaceHandler); + + DBusInterfaceHandlerToken registerInterfaceHandler(const std::string& objectPath, + const std::string& interfaceName, + const DBusMessageInterfaceHandler& dbusMessageInterfaceHandler); + + void unregisterInterfaceHandler(const DBusInterfaceHandlerToken& dbusInterfaceHandlerToken); + + bool handleMessage(const DBusMessage&) const; + + + private: + void addLibdbusObjectPathHandler(const std::string& objectPath); + void removeLibdbusObjectPathHandler(const std::string& objectPath); + + bool onGetDBusObjectManagerData(const DBusMessage& callMessage); + + typedef std::unordered_map DBusRegisteredObjectsTable; + DBusRegisteredObjectsTable dbusRegisteredObjectsTable_; + + std::shared_ptr dbusConnection_; +}; + +} // namespace DBus +} // namespace CommonAPI + +#endif // COMMONAPI_DBUS_DBUS_OBJECT_MANAGER_H_ diff --git a/CommonAPI-DBus/src/CommonAPI/DBus/DBusOutputStream.cpp b/CommonAPI-DBus/src/CommonAPI/DBus/DBusOutputStream.cpp new file mode 100644 index 0000000..e829bcb --- /dev/null +++ b/CommonAPI-DBus/src/CommonAPI/DBus/DBusOutputStream.cpp @@ -0,0 +1,42 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include "DBusOutputStream.h" + +namespace CommonAPI { +namespace DBus { + +DBusOutputStream::DBusOutputStream(DBusMessage dbusMessage) : + dbusMessage_(dbusMessage) { +} + +DBusOutputStream::~DBusOutputStream() { +} + +void DBusOutputStream::flush() { + const int toWrite = payload_.size(); + const bool success = dbusMessage_.setBodyLength(toWrite); + char* destinationDataPtr = dbusMessage_.getBodyData(); + + memcpy(destinationDataPtr, payload_.c_str(), toWrite); +} + +void DBusOutputStream::reserveMemory(size_t numOfBytes) { + assert(numOfBytes >= 0); + + payload_.reserve(numOfBytes); +} + +DBusOutputStream& DBusOutputStream::writeString(const char* cString, const uint32_t& length) { + assert(cString != NULL); + assert(cString[length] == '\0'); + + *this << length; + + writeRawData(cString, length + 1); + + return *this; +} + +} // namespace DBus +} // namespace CommonAPI diff --git a/CommonAPI-DBus/src/CommonAPI/DBus/DBusOutputStream.h b/CommonAPI-DBus/src/CommonAPI/DBus/DBusOutputStream.h new file mode 100644 index 0000000..e1bca16 --- /dev/null +++ b/CommonAPI-DBus/src/CommonAPI/DBus/DBusOutputStream.h @@ -0,0 +1,337 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#ifndef COMMONAPI_DBUS_DBUS_OUTPUT_MESSAGE_STREAM_H_ +#define COMMONAPI_DBUS_DBUS_OUTPUT_MESSAGE_STREAM_H_ + +#include "DBusMessage.h" +#include "DBusError.h" + +#include + +#include +#include +#include +#include +#include + +namespace CommonAPI { +namespace DBus { + +/** + * Used to mark the position of a pointer within an array of bytes. + */ +typedef uint32_t position_t; + + +/** + * @class DBusOutputMessageStream + * + * Used to serialize and write data into a #DBusMessage. For all data types that may be written to a #DBusMessage, a "<<"-operator should be defined to handle the writing + * (this operator is predefined for all basic data types and for vectors). The signature that has to be written to the #DBusMessage separately is assumed + * to match the actual data that is inserted via the #DBusOutputMessageStream. + */ +class DBusOutputStream: public OutputStream { + public: + virtual OutputStream& writeValue(const bool& boolValue) { return writeBasicTypeValue(boolValue); } + + virtual OutputStream& writeValue(const int8_t& int8Value) { return writeBasicTypeValue(int8Value); } + virtual OutputStream& writeValue(const int16_t& int16Value) { return writeBasicTypeValue(int16Value); } + virtual OutputStream& writeValue(const int32_t& int32Value) { return writeBasicTypeValue(int32Value); } + virtual OutputStream& writeValue(const int64_t& int64Value) { return writeBasicTypeValue(int64Value); } + + virtual OutputStream& writeValue(const uint8_t& uint8Value) { return writeBasicTypeValue(uint8Value); } + virtual OutputStream& writeValue(const uint16_t& uint16Value) { return writeBasicTypeValue(uint16Value); } + virtual OutputStream& writeValue(const uint32_t& uint32Value) { return writeBasicTypeValue(uint32Value); } + virtual OutputStream& writeValue(const uint64_t& uint64Value) { return writeBasicTypeValue(uint64Value); } + + virtual OutputStream& writeValue(const float& floatValue) { return writeBasicTypeValue((double) floatValue); } + virtual OutputStream& writeValue(const double& doubleValue) { return writeBasicTypeValue(doubleValue); } + + virtual OutputStream& writeValue(const std::string& stringValue) { return writeString(stringValue.c_str(), stringValue.length()); } + + inline virtual OutputStream& writeValue(const ByteBuffer& byteBufferValue); + + virtual OutputStream& writeEnumValue(const int8_t& int8BackingTypeValue) { return writeValue(int8BackingTypeValue); } + virtual OutputStream& writeEnumValue(const int16_t& int16BackingTypeValue) { return writeValue(int16BackingTypeValue); } + virtual OutputStream& writeEnumValue(const int32_t& int32BackingTypeValue) { return writeValue(int32BackingTypeValue); } + virtual OutputStream& writeEnumValue(const int64_t& int64BackingTypeValue) { return writeValue(int64BackingTypeValue); } + virtual OutputStream& writeEnumValue(const uint8_t& uint8BackingTypeValue) { return writeValue(uint8BackingTypeValue); } + virtual OutputStream& writeEnumValue(const uint16_t& uint16BackingTypeValue) { return writeValue(uint16BackingTypeValue); } + virtual OutputStream& writeEnumValue(const uint32_t& uint32BackingTypeValue) { return writeValue(uint32BackingTypeValue); } + virtual OutputStream& writeEnumValue(const uint64_t& uint64BackingTypeValue) { return writeValue(uint64BackingTypeValue); } + + virtual void beginWriteBoolVector(uint32_t sizeOfVector) { + beginWriteGenericVector(); + rememberCurrentStreamPosition(); + } + virtual void beginWriteInt8Vector(uint32_t sizeOfVector) { + beginWriteGenericVector(); + rememberCurrentStreamPosition(); + } + virtual void beginWriteInt16Vector(uint32_t sizeOfVector) { + beginWriteGenericVector(); + rememberCurrentStreamPosition(); + } + virtual void beginWriteInt32Vector(uint32_t sizeOfVector) { + beginWriteGenericVector(); + rememberCurrentStreamPosition(); + } + virtual void beginWriteInt64Vector(uint32_t sizeOfVector) { + beginWriteGenericVector(); + alignToBoundary(8); + rememberCurrentStreamPosition(); + } + virtual void beginWriteUInt8Vector(uint32_t sizeOfVector) { + beginWriteGenericVector(); + rememberCurrentStreamPosition(); + } + virtual void beginWriteUInt16Vector(uint32_t sizeOfVector) { + beginWriteGenericVector(); + rememberCurrentStreamPosition(); + } + virtual void beginWriteUInt32Vector(uint32_t sizeOfVector) { + beginWriteGenericVector(); + rememberCurrentStreamPosition(); + } + virtual void beginWriteUInt64Vector(uint32_t sizeOfVector) { + beginWriteGenericVector(); + alignToBoundary(8); + rememberCurrentStreamPosition(); + } + virtual void beginWriteFloatVector(uint32_t sizeOfVector) { + beginWriteGenericVector(); + alignToBoundary(8); + rememberCurrentStreamPosition(); + } + virtual void beginWriteDoubleVector(uint32_t sizeOfVector) { + beginWriteGenericVector(); + alignToBoundary(8); + rememberCurrentStreamPosition(); + } + virtual void beginWriteStringVector(uint32_t sizeOfVector) { + beginWriteGenericVector(); + rememberCurrentStreamPosition(); + } + virtual void beginWriteByteBufferVector(uint32_t sizeOfVector) { + beginWriteGenericVector(); + rememberCurrentStreamPosition(); + } + virtual void beginWriteVersionVector(uint32_t sizeOfVector) { + beginWriteGenericVector(); + alignToBoundary(8); + rememberCurrentStreamPosition(); + } + virtual void beginWriteVectorOfSerializableStructs(uint32_t sizeOfVector) { + beginWriteGenericVector(); + alignToBoundary(8); + rememberCurrentStreamPosition(); + } + virtual void beginWriteVectorOfVectors(uint32_t sizeOfVector) { + beginWriteGenericVector(); + rememberCurrentStreamPosition(); + } + virtual void beginWriteVectorOfMaps(uint32_t sizeOfVector) { + beginWriteGenericVector(); + alignToBoundary(8); + rememberCurrentStreamPosition(); + } + + virtual void endWriteVector() { + uint32_t numOfWrittenBytes = getCurrentStreamPosition() - popRememberedStreamPosition(); + writeBasicTypeValueAtPosition(popRememberedStreamPosition(), numOfWrittenBytes); + } + + virtual OutputStream& writeVersionValue(const Version& versionValue) { + alignToBoundary(8); + writeValue(versionValue.Major); + writeValue(versionValue.Minor); + return *this; + } + + virtual void beginWriteSerializableStruct(const SerializableStruct& serializableStruct) { alignToBoundary(8); } + virtual void endWriteSerializableStruct(const SerializableStruct& serializableStruct) { } + + virtual void beginWriteMap(size_t elementCount) { + alignToBoundary(sizeof(uint32_t)); + rememberCurrentStreamPosition(); + writeBasicTypeValue((uint32_t) 0); + alignToBoundary(8); + rememberCurrentStreamPosition(); + } + + virtual void endWriteMap() { + uint32_t numOfWrittenBytes = getCurrentStreamPosition() - popRememberedStreamPosition(); + writeBasicTypeValueAtPosition(popRememberedStreamPosition(), numOfWrittenBytes); + } + + virtual bool hasError() const { + return dbusError_; + } + + /** + * Creates a #DBusOutputMessageStream which can be used to serialize and write data into the given #DBusMessage. Any data written is buffered within the stream. + * Remember to call flush() when you are done with writing: Only then the data actually is written to the #DBusMessage. + * + * @param dbusMessage The #DBusMessage any data pushed into this stream should be written to. + */ + DBusOutputStream(DBusMessage dbusMessage); + + /** + * Destructor; does not call the destructor of the referred #DBusMessage. Make sure to maintain a reference to the + * #DBusMessage outside of the stream if you intend to make further use of the message, e.g. in order to send it, + * now that you have written some payload into it. + */ + virtual ~DBusOutputStream(); + + /** + * Writes the data that was buffered within this #DBusOutputMessageStream to the #DBusMessage that was given to the constructor. Each call to flush() + * will completely override the data that currently is contained in the #DBusMessage. The data that is buffered in this #DBusOutputMessageStream is + * not deleted by calling flush(). + */ + void flush(); + + /** + * Marks the stream as erroneous. + */ + inline void setError(); + + /** + * Reserves the given number of bytes for writing, thereby negating the need to dynamically allocate memory while writing. + * Use this method for optimization: If possible, reserve as many bytes as you need for your data before doing any writing. + * + * @param numOfBytes The number of bytes that should be reserved for writing. + */ + void reserveMemory(size_t numOfBytes); + + /** + * @return current data position where later writing is possible + */ + size_t getCurrentPosition(); + + template + DBusOutputStream& writeBasicTypeValue(const _BasicType& basicValue) { + if (sizeof(_BasicType) > 1) + alignToBoundary(sizeof(_BasicType)); + + writeRawData(reinterpret_cast(&basicValue), sizeof(_BasicType)); + + return *this; + } + + template + bool writeBasicTypeValueAtPosition(size_t position, const _BasicType& basicValue) { + assert(position + sizeof(_BasicType) <= payload_.size()); + + return writeRawDataAtPosition(position, reinterpret_cast(&basicValue), sizeof(_BasicType)); + } + + DBusOutputStream& writeString(const char* cString, const uint32_t& length); + + /** + * Fills the stream with 0-bytes to make the next value be aligned to the boundary given. + * This means that as many 0-bytes are written to the buffer as are necessary + * to make the next value start with the given alignment. + * + * @param alignBoundary The byte-boundary to which the next value should be aligned. + */ + virtual void alignToBoundary(const size_t alignBoundary); + + /** + * Takes sizeInByte characters, starting from the character which val points to, and stores them for later writing. + * When calling flush(), all values that were written to this stream are copied into the payload of the #DBusMessage. + * + * The array of characters might be created from a pointer to a given value by using a reinterpret_cast. Example: + * @code + * ... + * int32_t val = 15; + * outputMessageStream.alignForBasicType(sizeof(int32_t)); + * const char* const reinterpreted = reinterpret_cast(&val); + * outputMessageStream.writeValue(reinterpreted, sizeof(int32_t)); + * ... + * @endcode + * + * @param val The array of chars that should serve as input + * @param sizeInByte The number of bytes that should be written + * @return true if writing was successful, false otherwise. + * + * @see DBusOutputMessageStream() + * @see flush() + */ + bool writeRawData(const char* rawDataPtr, const size_t sizeInByte); + + bool writeRawDataAtPosition(size_t position, const char* rawDataPtr, const size_t sizeInByte); + + protected: + std::string payload_; + + private: + inline void beginWriteGenericVector() { + alignToBoundary(sizeof(uint32_t)); + rememberCurrentStreamPosition(); + writeBasicTypeValue((uint32_t) 0); + } + + inline void rememberCurrentStreamPosition() { + savedStreamPositions_.push(payload_.size()); + } + + inline size_t popRememberedStreamPosition() { + size_t val = savedStreamPositions_.top(); + savedStreamPositions_.pop(); + return val; + } + + inline size_t getCurrentStreamPosition() { + return payload_.size(); + } + + DBusError dbusError_; + DBusMessage dbusMessage_; + + std::stack savedStreamPositions_; +}; + + +//Additional 0-termination, so this is 8 byte of \0 +static const char* eightByteZeroString = "\0\0\0\0\0\0\0"; + +inline void DBusOutputStream::alignToBoundary(const size_t alignBoundary) { + assert(alignBoundary > 0 && alignBoundary <= 8 && (alignBoundary % 2 == 0 || alignBoundary == 1)); + + size_t alignMask = alignBoundary - 1; + size_t necessaryAlignment = ((alignMask - (payload_.size() & alignMask)) + 1) & alignMask; + + writeRawData(eightByteZeroString, necessaryAlignment); +} + +inline bool DBusOutputStream::writeRawData(const char* rawDataPtr, const size_t sizeInByte) { + assert(sizeInByte >= 0); + + payload_.append(rawDataPtr, sizeInByte); + + return true; +} + +inline bool DBusOutputStream::writeRawDataAtPosition(size_t position, const char* rawDataPtr, const size_t sizeInByte) { + assert(sizeInByte >= 0); + + payload_ = payload_.replace(position, sizeInByte, rawDataPtr, sizeInByte); + + return true; +} + +inline size_t DBusOutputStream::getCurrentPosition() { + return payload_.size(); +} + + +OutputStream& DBusOutputStream::writeValue(const ByteBuffer& byteBufferValue) { + *this << byteBufferValue; + return *this; +} + +} // namespace DBus +} // namespace CommonAPI + +#endif // COMMONAPI_DBUS_DBUS_OUTPUT_MESSAGE_STREAM_H_ diff --git a/CommonAPI-DBus/src/CommonAPI/DBus/DBusProxy.cpp b/CommonAPI-DBus/src/CommonAPI/DBus/DBusProxy.cpp new file mode 100644 index 0000000..e19dbda --- /dev/null +++ b/CommonAPI-DBus/src/CommonAPI/DBus/DBusProxy.cpp @@ -0,0 +1,133 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include "DBusProxy.h" +#include "DBusServiceRegistry.h" +#include "DBusUtils.h" + +#include +#include +#include +#include +#include +#include + +namespace CommonAPI { +namespace DBus { + +DBusProxyStatusEvent::DBusProxyStatusEvent(DBusProxy* dbusProxy) : + dbusProxy_(dbusProxy) { +} + +void DBusProxyStatusEvent::onFirstListenerAdded(const Listener& listener) { + auto serviceStatusListener = std::bind( + &DBusProxyStatusEvent::onServiceAvailableSignalHandler, + this, + std::placeholders::_1, + std::placeholders::_2); + + subscription_ = dbusProxy_->getDBusConnection()->getDBusServiceRegistry()->getServiceStatusEvent().subscribe( + dbusProxy_->dbusBusName_ + ":" + dbusProxy_->dbusObjectPath_ + ":" + dbusProxy_->interfaceName_, + serviceStatusListener); +} + +void DBusProxyStatusEvent::onLastListenerRemoved(const Listener& listener) { + dbusProxy_->getDBusConnection()->getDBusServiceRegistry()->getServiceStatusEvent().unsubscribe(subscription_); +} + +SubscriptionStatus DBusProxyStatusEvent::onServiceAvailableSignalHandler(const std::string& name, + const AvailabilityStatus& availabilityStatus) { + AvailabilityStatus availability = availabilityStatus; + + return notifyListeners(availability); +} + +const std::string DBusProxy::domain_ = "local"; + +DBusProxy::DBusProxy(const std::string& dbusBusName, + const std::string& dbusObjectPath, + const std::string& interfaceName, + const std::shared_ptr& dbusProxyConnection) : + dbusBusName_(dbusBusName), + dbusObjectPath_(dbusObjectPath), + interfaceName_(interfaceName), + statusEvent_(this), + interfaceVersionAttribute_(*this, "getInterfaceVersion"), + available_(false), + availableSet_(false), + connection_(dbusProxyConnection) { +} + +DBusProxy::DBusProxy(const std::string& dbusBusName, + const std::string& dbusObjectPath, + const std::string& interfaceName, + const std::shared_ptr& connection, + const bool isAlwaysAvailable) : + dbusBusName_(dbusBusName), + dbusObjectPath_(dbusObjectPath), + interfaceName_(interfaceName), + statusEvent_(this), + interfaceVersionAttribute_(*this, "getInterfaceVersion"), + available_(isAlwaysAvailable), + availableSet_(isAlwaysAvailable), + connection_(connection) { +} + +std::string DBusProxy::getAddress() const { + return domain_ + ":" + interfaceName_ + ":" + dbusBusName_; +} + +const std::string& DBusProxy::getDomain() const { + return domain_; +} + +const std::string& DBusProxy::getServiceId() const { + return getInterfaceName(); +} + +const std::string& DBusProxy::getInstanceId() const { + return dbusBusName_; +} + + +bool DBusProxy::isAvailable() const { + if (!availableSet_) { + auto status = getDBusConnection()->getDBusServiceRegistry()->getReadyFuture().wait_for(std::chrono::milliseconds(1)); + if (checkReady(status)) { + available_ = getDBusConnection()->getDBusServiceRegistry()->isServiceInstanceAlive(getAddress()); + availableSet_ = true; + } + } + return available_; +} + +bool DBusProxy::isAvailableBlocking() const { + + if (!availableSet_) { + getDBusConnection()->getDBusServiceRegistry()->getReadyFuture().wait(); + available_ = getDBusConnection()->getDBusServiceRegistry()->isServiceInstanceAlive(getAddress()); + availableSet_ = true; + } + return available_; +} + +ProxyStatusEvent& DBusProxy::getProxyStatusEvent() { + return statusEvent_; +} + +InterfaceVersionAttribute& DBusProxy::getInterfaceVersionAttribute() { + return interfaceVersionAttribute_; +} + +DBusMessage DBusProxy::createMethodCall(const char* methodName, + const char* methodSignature) const { + return DBusMessage::createMethodCall( + dbusBusName_.c_str(), + dbusObjectPath_.c_str(), + getInterfaceName().c_str(), + methodName, + methodSignature); +} + +} // namespace DBus +} // namespace CommonAPI diff --git a/CommonAPI-DBus/src/CommonAPI/DBus/DBusProxy.h b/CommonAPI-DBus/src/CommonAPI/DBus/DBusProxy.h new file mode 100644 index 0000000..9f5db75 --- /dev/null +++ b/CommonAPI-DBus/src/CommonAPI/DBus/DBusProxy.h @@ -0,0 +1,139 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#ifndef COMMONAPI_DBUS_DBUS_PROXY_H_ +#define COMMONAPI_DBUS_DBUS_PROXY_H_ + +#include "DBusProxyConnection.h" +#include "DBusAttribute.h" + +#include +#include + +#include +#include +#include + +namespace CommonAPI { +namespace DBus { + +class DBusProxy; + +typedef Event ProxyStatusEvent; + +class DBusProxyStatusEvent: public ProxyStatusEvent { + public: + DBusProxyStatusEvent(DBusProxy* dbusProxy); + + void onFirstListenerAdded(const Listener& listener); + void onLastListenerRemoved(const Listener& listener); + + Subscription subscribe(Listener listener); + + private: + SubscriptionStatus onServiceAvailableSignalHandler(const std::string& name, const AvailabilityStatus& availabilityStatus); + + DBusProxy* dbusProxy_; + DBusServiceStatusEvent::Subscription subscription_; + + friend class DBusProxy; + +}; + + +class DBusProxy: public virtual CommonAPI::Proxy { + public: + DBusProxy(const std::string& dbusBusName, + const std::string& dbusObjectPath, + const std::string& interfaceName, + const std::shared_ptr& dbusProxyConnection); + + virtual std::string getAddress() const; + virtual const std::string& getDomain() const; + virtual const std::string& getServiceId() const; + virtual const std::string& getInstanceId() const; + virtual bool isAvailable() const; + virtual bool isAvailableBlocking() const; + virtual ProxyStatusEvent& getProxyStatusEvent(); + virtual InterfaceVersionAttribute& getInterfaceVersionAttribute(); + + inline const std::string& getDBusBusName() const; + inline const std::string& getDBusObjectPath() const; + inline const std::string& getInterfaceName() const; + inline const std::shared_ptr& getDBusConnection() const; + + DBusMessage createMethodCall(const char* methodName, + const char* methodSignature = NULL) const; + + inline DBusProxyConnection::DBusSignalHandlerToken addSignalMemberHandler( + const std::string& signalName, + const std::string& signalSignature, + DBusProxyConnection::DBusSignalHandler* dbusSignalHandler); + + inline void removeSignalMemberHandler(const DBusProxyConnection::DBusSignalHandlerToken& dbusSignalHandlerToken); + + protected: + DBusProxy(const DBusProxy& abstractProxy) = delete; + + DBusProxy(const std::string& busName, + const std::string& objectId, + const std::string& interfaceName, + const std::shared_ptr& connection, + const bool isAlwaysAvailable); + + virtual void getOwnVersion(uint16_t& ownVersionMajor, uint16_t& ownVersionMinor) const = 0; + + DBusProxyStatusEvent statusEvent_; + DBusProxyStatusEvent::Subscription remoteStatusSubscription_; + + private: + void onServiceAlive(bool alive); + + const std::string dbusBusName_; + const std::string dbusObjectPath_; + const std::string interfaceName_; + + mutable bool available_; + mutable bool availableSet_; + + std::shared_ptr connection_; + + DBusReadonlyAttribute interfaceVersionAttribute_; + + static const std::string domain_; + + friend class DBusProxyStatusEvent; +}; + +const std::string& DBusProxy::getDBusBusName() const { + return dbusBusName_; +} + +const std::string& DBusProxy::getDBusObjectPath() const { + return dbusObjectPath_; +} + +const std::string& DBusProxy::getInterfaceName() const { + return interfaceName_; +} + +const std::shared_ptr& DBusProxy::getDBusConnection() const { + return connection_; +} + +DBusProxyConnection::DBusSignalHandlerToken DBusProxy::addSignalMemberHandler( + const std::string& signalName, + const std::string& signalSignature, + DBusProxyConnection::DBusSignalHandler* dbusSignalHandler) { + return connection_->addSignalMemberHandler(dbusObjectPath_, getInterfaceName(), signalName, signalSignature, dbusSignalHandler); +} + +void DBusProxy::removeSignalMemberHandler(const DBusProxyConnection::DBusSignalHandlerToken& dbusSignalHandlerToken) { + return connection_->removeSignalMemberHandler(dbusSignalHandlerToken); +} + +} // namespace DBus +} // namespace CommonAPI + +#endif // COMMONAPI_DBUS_DBUS_PROXY_H_ + diff --git a/CommonAPI-DBus/src/CommonAPI/DBus/DBusProxyAsyncCallbackHandler.h b/CommonAPI-DBus/src/CommonAPI/DBus/DBusProxyAsyncCallbackHandler.h new file mode 100644 index 0000000..8fd76ea --- /dev/null +++ b/CommonAPI-DBus/src/CommonAPI/DBus/DBusProxyAsyncCallbackHandler.h @@ -0,0 +1,72 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#ifndef COMMONAPI_DBUS_DBUS_PROXY_ASYNC_CALLBACK_HANDLER_H_ +#define COMMONAPI_DBUS_DBUS_PROXY_ASYNC_CALLBACK_HANDLER_H_ + +#include "DBusProxyConnection.h" +#include "DBusMessage.h" +#include "DBusSerializableArguments.h" +#include "DBusHelper.h" + +#include +#include +#include +#include + + +namespace CommonAPI { +namespace DBus { + +template +class DBusProxyAsyncCallbackHandler: public DBusProxyConnection::DBusMessageReplyAsyncHandler { + public: + typedef std::function FunctionType; + + static inline std::unique_ptr create(FunctionType&& callback) { + return std::unique_ptr( + new DBusProxyAsyncCallbackHandler(std::move(callback))); + } + + DBusProxyAsyncCallbackHandler() = delete; + DBusProxyAsyncCallbackHandler(FunctionType&& callback): + callback_(std::move(callback)) { + } + + virtual std::future getFuture() { + return promise_.get_future(); + } + + virtual void onDBusMessageReply(const CallStatus& dbusMessageCallStatus, const DBusMessage& dbusMessage) { + promise_.set_value(handleDBusMessageReply(dbusMessageCallStatus, dbusMessage, typename make_sequence::type())); + } + + private: + template + inline CallStatus handleDBusMessageReply(const CallStatus dbusMessageCallStatus, const DBusMessage& dbusMessage, index_sequence<_ArgIndices...>) const { + CallStatus callStatus = dbusMessageCallStatus; + std::tuple<_ArgTypes...> argTuple; + + if (dbusMessageCallStatus == CallStatus::SUCCESS) { + if (!dbusMessage.isErrorType()) { + DBusInputStream dbusInputStream(dbusMessage); + const bool success = DBusSerializableArguments<_ArgTypes...>::deserialize(dbusInputStream, std::get<_ArgIndices>(argTuple)...); + if (!success) + callStatus = CallStatus::REMOTE_ERROR; + } else { + callStatus = CallStatus::REMOTE_ERROR; + } + } + + callback_(callStatus, std::move(std::get<_ArgIndices>(argTuple))...); + return callStatus; + } + + std::promise promise_; + const FunctionType callback_; +}; + +} // namespace DBus +} // namespace CommonAPI + +#endif // COMMONAPI_DBUS_DBUS_PROXY_ASYNC_CALLBACK_HANDLER_H_ diff --git a/CommonAPI-DBus/src/CommonAPI/DBus/DBusProxyConnection.h b/CommonAPI-DBus/src/CommonAPI/DBus/DBusProxyConnection.h new file mode 100644 index 0000000..c8f5b7e --- /dev/null +++ b/CommonAPI-DBus/src/CommonAPI/DBus/DBusProxyConnection.h @@ -0,0 +1,94 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#ifndef COMMONAPI_DBUS_DBUS_PROXY_CONNECTION_H_ +#define COMMONAPI_DBUS_DBUS_PROXY_CONNECTION_H_ + +#include "DBusError.h" +#include "DBusMessage.h" + +#include "DBusFunctionalHash.h" +#include "DBusServiceStatusEvent.h" + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace CommonAPI { +namespace DBus { + + +typedef std::function DBusMessageHandler; + +class DBusDaemonProxy; +class DBusServiceRegistry; +class DBusObjectManager; + + +class DBusProxyConnection { + public: + class DBusMessageReplyAsyncHandler { + public: + virtual ~DBusMessageReplyAsyncHandler() { } + virtual std::future getFuture() = 0; + virtual void onDBusMessageReply(const CallStatus&, const DBusMessage&) = 0; + }; + + class DBusSignalHandler { + public: + virtual ~DBusSignalHandler() { } + virtual SubscriptionStatus onSignalDBusMessage(const DBusMessage&) = 0; + }; + + // objectPath, interfaceName, interfaceMemberName, interfaceMemberSignature + typedef std::tuple DBusSignalHandlerPath; + typedef std::unordered_multimap DBusSignalHandlerTable; + typedef DBusSignalHandlerPath DBusSignalHandlerToken; + + + virtual ~DBusProxyConnection() { } + + virtual bool isConnected() const = 0; + + virtual bool sendDBusMessage(const DBusMessage& dbusMessage, uint32_t* allocatedSerial = NULL) const = 0; + + static const int kDefaultSendTimeoutMs = 100 * 1000; + + virtual std::future sendDBusMessageWithReplyAsync( + const DBusMessage& dbusMessage, + std::unique_ptr dbusMessageReplyAsyncHandler, + int timeoutMilliseconds = kDefaultSendTimeoutMs) const = 0; + + virtual DBusMessage sendDBusMessageWithReplyAndBlock( + const DBusMessage& dbusMessage, + DBusError& dbusError, + int timeoutMilliseconds = kDefaultSendTimeoutMs) const = 0; + + virtual DBusSignalHandlerToken addSignalMemberHandler( + const std::string& objectPath, + const std::string& interfaceName, + const std::string& interfaceMemberName, + const std::string& interfaceMemberSignature, + DBusSignalHandler* dbusSignalHandler) = 0; + + virtual void removeSignalMemberHandler(const DBusSignalHandlerToken& dbusSignalHandlerToken) = 0; + + virtual const std::shared_ptr& getDBusDaemonProxy() = 0; + virtual const std::shared_ptr& getDBusServiceRegistry() = 0; + virtual const std::shared_ptr& getDBusObjectManager() = 0; +}; + + +} // namespace DBus +} // namespace CommonAPI + +#endif //COMMONAPI_DBUS_DBUS_PROXY_CONNECTION_H_ diff --git a/CommonAPI-DBus/src/CommonAPI/DBus/DBusProxyHelper.h b/CommonAPI-DBus/src/CommonAPI/DBus/DBusProxyHelper.h new file mode 100644 index 0000000..efea71d --- /dev/null +++ b/CommonAPI-DBus/src/CommonAPI/DBus/DBusProxyHelper.h @@ -0,0 +1,139 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#ifndef COMMONAPI_DBUS_DBUS_PROXY_HELPER_H_ +#define COMMONAPI_DBUS_DBUS_PROXY_HELPER_H_ + +#include "DBusMessage.h" +#include "DBusSerializableArguments.h" +#include "DBusProxyAsyncCallbackHandler.h" + +#include +#include +#include +#include + +namespace CommonAPI { +namespace DBus { + + +class DBusProxy; + + +template< class, class > +struct DBusProxyHelper; + +template < + template class _In, class... _InArgs, + template class _Out, class... _OutArgs> +struct DBusProxyHelper<_In<_InArgs...>, _Out<_OutArgs...>> { + template + static void callMethod(const _DBusProxy& dbusProxy, + const char* methodName, + const char* methodSignature, + const _InArgs&... inArgs, + CommonAPI::CallStatus& callStatus) { + if (dbusProxy.isAvailableBlocking()) { + + DBusMessage dbusMessage = dbusProxy.createMethodCall(methodName, methodSignature); + + if (sizeof...(_InArgs) > 0) { + DBusOutputStream outputStream(dbusMessage); + const bool success = DBusSerializableArguments<_InArgs...>::serialize(outputStream, inArgs...); + if (!success) { + callStatus = CallStatus::OUT_OF_MEMORY; + return; + } + outputStream.flush(); + } + + const bool dbusMessageSent = dbusProxy.getDBusConnection()->sendDBusMessage(dbusMessage); + callStatus = dbusMessageSent ? CallStatus::SUCCESS : CallStatus::OUT_OF_MEMORY; + } else { + callStatus = CallStatus::NOT_AVAILABLE; + } + } + + template + static void callMethodWithReply( + const _DBusProxy& dbusProxy, + const char* methodName, + const char* methodSignature, + const _InArgs&... inArgs, + CommonAPI::CallStatus& callStatus, + _OutArgs&... outArgs) { + + if (dbusProxy.isAvailableBlocking()) { + + DBusMessage dbusMethodCall = dbusProxy.createMethodCall(methodName, methodSignature); + + if (sizeof...(_InArgs) > 0) { + DBusOutputStream outputStream(dbusMethodCall); + const bool success = DBusSerializableArguments<_InArgs...>::serialize(outputStream, inArgs...); + if (!success) { + callStatus = CallStatus::OUT_OF_MEMORY; + return; + } + outputStream.flush(); + } + + DBusError dbusError; + DBusMessage dbusMessageReply = dbusProxy.getDBusConnection()->sendDBusMessageWithReplyAndBlock(dbusMethodCall, dbusError); + if (dbusError || !dbusMessageReply.isMethodReturnType()) { + callStatus = CallStatus::REMOTE_ERROR; + return; + } + + if (sizeof...(_OutArgs) > 0) { + DBusInputStream inputStream(dbusMessageReply); + const bool success = DBusSerializableArguments<_OutArgs...>::deserialize(inputStream, outArgs...); + if (!success) { + callStatus = CallStatus::REMOTE_ERROR; + return; + } + } + + callStatus = CallStatus::SUCCESS; + } else { + callStatus = CallStatus::NOT_AVAILABLE; + } + } + + template + static std::future callMethodAsync( + const _DBusProxy& dbusProxy, + const char* methodName, + const char* methodSignature, + const _InArgs&... inArgs, + _AsyncCallback asyncCallback) { + + if (dbusProxy.isAvailable()) { + + DBusMessage dbusMessage = dbusProxy.createMethodCall(methodName, methodSignature); + + if (sizeof...(_InArgs) > 0) { + DBusOutputStream outputStream(dbusMessage); + const bool success = DBusSerializableArguments<_InArgs...>::serialize(outputStream, inArgs...); + if (!success) { + std::promise promise; + promise.set_value(CallStatus::OUT_OF_MEMORY); + return promise.get_future(); + } + outputStream.flush(); + } + + return dbusProxy.getDBusConnection()->sendDBusMessageWithReplyAsync( + dbusMessage, + DBusProxyAsyncCallbackHandler<_OutArgs...>::create(std::move(asyncCallback))); + } else { + std::promise promise; + promise.set_value(CallStatus::NOT_AVAILABLE); + return promise.get_future(); + } + } +}; + +} // namespace DBus +} // namespace CommonAPI + +#endif // COMMONAPI_DBUS_DBUS_PROXY_HELPER_H_ diff --git a/CommonAPI-DBus/src/CommonAPI/DBus/DBusRuntime.cpp b/CommonAPI-DBus/src/CommonAPI/DBus/DBusRuntime.cpp new file mode 100644 index 0000000..9179ce7 --- /dev/null +++ b/CommonAPI-DBus/src/CommonAPI/DBus/DBusRuntime.cpp @@ -0,0 +1,29 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include "DBusRuntime.h" + +namespace CommonAPI { +namespace DBus { + +const MiddlewareInfo DBusRuntime::middlewareInfo_("DBus", &DBusRuntime::getInstance); + +__attribute__((constructor)) void registerDBusMiddleware(void) { + Runtime::registerRuntimeLoader("DBus", &DBusRuntime::getInstance); +} + +std::shared_ptr DBusRuntime::getInstance() { + static std::shared_ptr singleton_; + if(!singleton_) { + singleton_ = std::make_shared(); + } + return singleton_; +} + +std::shared_ptr DBusRuntime::createFactory() { + auto factory = std::make_shared(this->shared_from_this(), &middlewareInfo_); + return factory; +} + +} // namespace DBus +} // namespace CommonAPI diff --git a/CommonAPI-DBus/src/CommonAPI/DBus/DBusRuntime.h b/CommonAPI-DBus/src/CommonAPI/DBus/DBusRuntime.h new file mode 100644 index 0000000..52f7fa0 --- /dev/null +++ b/CommonAPI-DBus/src/CommonAPI/DBus/DBusRuntime.h @@ -0,0 +1,33 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#ifndef COMMONAPI_DBUS_DBUS_RUNTIME_H_ +#define COMMONAPI_DBUS_DBUS_RUNTIME_H_ + +#include "CommonAPI/Runtime.h" + +#include "DBusFactory.h" + +namespace CommonAPI { +namespace DBus { + +class DBusRuntime: public Runtime, public std::enable_shared_from_this { + public: + static std::shared_ptr getInstance(); + + std::shared_ptr createFactory(); + + static const MiddlewareInfo middlewareInfo_; +}; + +} // namespace DBus +} // namespace CommonAPI + + +extern "C" { + +CommonAPI::MiddlewareInfo middlewareInfo = CommonAPI::DBus::DBusRuntime::middlewareInfo_; + +} + +#endif // COMMONAPI_DBUS_DBUS_RUNTIME_H_ diff --git a/CommonAPI-DBus/src/CommonAPI/DBus/DBusSerializableArguments.h b/CommonAPI-DBus/src/CommonAPI/DBus/DBusSerializableArguments.h new file mode 100644 index 0000000..c028f17 --- /dev/null +++ b/CommonAPI-DBus/src/CommonAPI/DBus/DBusSerializableArguments.h @@ -0,0 +1,58 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#ifndef COMMONAPI_DBUS_SERIALIZABLE_ARGUMENTS_H_ +#define COMMONAPI_DBUS_SERIALIZABLE_ARGUMENTS_H_ + +#include "DBusInputStream.h" +#include "DBusOutputStream.h" + +namespace CommonAPI { +namespace DBus { + +template +struct DBusSerializableArguments; + +template <> +struct DBusSerializableArguments<> { + static inline bool serialize(OutputStream& outputStream) { + return true; + } + + static inline bool deserialize(DBusInputStream& inputStream) { + return true; + } +}; + +template +struct DBusSerializableArguments<_ArgumentType> { + static inline bool serialize(OutputStream& outputStream, const _ArgumentType& argument) { + outputStream << argument; + return !outputStream.hasError(); + } + + static inline bool deserialize(DBusInputStream& inputStream, _ArgumentType& argument) { + inputStream >> argument; + return !inputStream.hasError(); + } +}; + +template +struct DBusSerializableArguments<_ArgumentType, _Rest...> { + static inline bool serialize(OutputStream& outputStream, const _ArgumentType& argument, const _Rest&... rest) { + outputStream << argument; + const bool success = !outputStream.hasError(); + return success ? DBusSerializableArguments<_Rest...>::serialize(outputStream, rest...) : false; + } + + static inline bool deserialize(DBusInputStream& inputStream, _ArgumentType& argument, _Rest&... rest) { + inputStream >> argument; + const bool success = !inputStream.hasError(); + return success ? DBusSerializableArguments<_Rest...>::deserialize(inputStream, rest...) : false; + } +}; + +} // namespace DBus +} // namespace CommonAPI + +#endif // COMMONAPI_DBUS_SERIALIZABLE_ARGUMENTS_H_ diff --git a/CommonAPI-DBus/src/CommonAPI/DBus/DBusServiceRegistry.cpp b/CommonAPI-DBus/src/CommonAPI/DBus/DBusServiceRegistry.cpp new file mode 100644 index 0000000..bf43a28 --- /dev/null +++ b/CommonAPI-DBus/src/CommonAPI/DBus/DBusServiceRegistry.cpp @@ -0,0 +1,312 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include +#include +#include +#include +#include +#include + +#include "DBusServiceRegistry.h" +#include "DBusInputStream.h" +#include "DBusDaemonProxy.h" +#include "DBusConnection.h" +#include "DBusUtils.h" + + +namespace CommonAPI { +namespace DBus { + + +DBusServiceRegistry::DBusServiceRegistry(std::shared_ptr dbusConnection) : + dbusConnection_(dbusConnection), + ready(false), + serviceStatusEvent_(std::shared_ptr(this)), + readyPromise_(), + readyMutex_() +{ + readyFuture_ = readyPromise_.get_future(); + cacheAllServices(); + dbusNameOwnerChangedEventSubscription_ = + dbusConnection_->getDBusDaemonProxy()->getNameOwnerChangedEvent().subscribe( + std::bind(&DBusServiceRegistry::onDBusNameOwnerChangedEvent, + this, + std::placeholders::_1, + std::placeholders::_2, + std::placeholders::_3)); + std::thread(std::bind(&DBusServiceRegistry::isReadyBlocking, this)).detach(); +} + +void DBusServiceRegistry::registerAvailabilityListener(const std::string& service, const std::function& listener) { + availabilityCallbackList.insert({service, listener}); + +} + +DBusServiceStatusEvent& DBusServiceRegistry::getServiceStatusEvent() { + return serviceStatusEvent_; +} + +DBusServiceRegistry::~DBusServiceRegistry() { + dbusConnection_->getDBusDaemonProxy()->getNameOwnerChangedEvent().unsubscribe(dbusNameOwnerChangedEventSubscription_); +} + +std::future& DBusServiceRegistry::getReadyFuture() { + return readyFuture_; +} + +bool DBusServiceRegistry::isReadyBlocking() { + if (!ready) { + readyMutex_.lock(); + auto status = readyFuture_.wait_for(std::chrono::seconds(5)); + if (checkReady(status)) { + ready = true; + } else { + ready = true; + readyPromise_.set_value(true); + } + readyMutex_.unlock(); + } + return ready; +} + +bool DBusServiceRegistry::isReady() { + return ready; +} + +std::vector DBusServiceRegistry::getAvailableServiceInstances(const std::string& serviceInterfaceName, + const std::string& serviceDomainName) { + if (!isReadyBlocking()) { + return std::vector(); + } + + if (serviceDomainName != "local" || !dbusConnection_->isConnected()) { + return std::vector(); + } + + std::vector addressesOfKnownServiceInstances; + auto knownServiceInstancesIteratorPair = dbusCachedProvidersForInterfaces_.equal_range(serviceInterfaceName); + + while(knownServiceInstancesIteratorPair.first != knownServiceInstancesIteratorPair.second) { + const DBusServiceInstanceId dbusServiceInstanceId = knownServiceInstancesIteratorPair.first->second; + addressesOfKnownServiceInstances.push_back(findInstanceIdMapping(dbusServiceInstanceId)); + ++knownServiceInstancesIteratorPair.first; + } + + return addressesOfKnownServiceInstances; +} + +void DBusServiceRegistry::onManagedPathsList(const CallStatus& status, DBusObjectToInterfaceDict managedObjects, + std::list::iterator iter, std::shared_ptr> list) { + + auto objectPathIterator = managedObjects.begin(); + + while (objectPathIterator != managedObjects.end()) { + const std::string& serviceObjPath = objectPathIterator->first; + auto interfaceNameIterator = objectPathIterator->second.begin(); + + while (interfaceNameIterator != objectPathIterator->second.end()) { + const std::string& interfaceName = interfaceNameIterator->first; + dbusCachedProvidersForInterfaces_.insert( { interfaceName, { *iter, serviceObjPath } }); + ++interfaceNameIterator; + } + ++objectPathIterator; + } + + list->erase(iter); + + if (list->size() == 0) { + readyMutex_.lock(); + if (!ready) { + readyPromise_.set_value(true); + ready = true; + } + readyMutex_.unlock(); + } +} + +bool DBusServiceRegistry::isServiceInstanceAlive(const std::string& address) { + std::vector parts = split(address, ':'); + return isServiceInstanceAlive(parts[2], parts[1], parts[0]); +} + + +bool DBusServiceRegistry::isServiceInstanceAlive(const std::string& serviceInstanceID, + const std::string& serviceInterfaceName, + const std::string& serviceDomainName ) { + if (!isReadyBlocking()) { + return false; + } + + if (serviceDomainName != "local" || !dbusConnection_->isConnected()) { + return false; + } + + DBusServiceInstanceId serviceInstanceId = findInstanceIdMapping(serviceInstanceID); + + auto knownInstancesForInterfaceIteratorPair = dbusCachedProvidersForInterfaces_.equal_range(serviceInterfaceName); + + while(knownInstancesForInterfaceIteratorPair.first != knownInstancesForInterfaceIteratorPair.second) { + DBusServiceInstanceId knownServiceId = knownInstancesForInterfaceIteratorPair.first->second; + if(knownServiceId == serviceInstanceId) { + return true; + } + ++knownInstancesForInterfaceIteratorPair.first; + } + + return false; +} + +void DBusServiceRegistry::getManagedObjects(const std::string& dbusWellKnownBusName) { + auto callMessage = DBusMessage::createMethodCall( + dbusWellKnownBusName.c_str(), + "/", + "org.freedesktop.DBus.ObjectManager", + "GetManagedObjects", + ""); + dbusConnection_->sendDBusMessageWithReplyAsync( + callMessage, + DBusProxyAsyncCallbackHandler::create( + std::bind( + &DBusServiceRegistry::onManagedPaths, + this, + std::placeholders::_1, + std::placeholders::_2, + dbusWellKnownBusName)), 100); + +} + +void DBusServiceRegistry::onManagedPaths(const CallStatus& status, DBusObjectToInterfaceDict managedObjects, + std::string dbusWellKnownBusName) { + + auto objectPathIterator = managedObjects.begin(); + + while (objectPathIterator != managedObjects.end()) { + const std::string& serviceObjPath = objectPathIterator->first; + auto interfaceNameIterator = objectPathIterator->second.begin(); + + while (interfaceNameIterator != objectPathIterator->second.end()) { + const std::string& interfaceName = interfaceNameIterator->first; + dbusCachedProvidersForInterfaces_.insert( { interfaceName, { dbusWellKnownBusName, serviceObjPath } }); + updateListeners(dbusWellKnownBusName, serviceObjPath, interfaceName, true); + ++interfaceNameIterator; + } + + ++objectPathIterator; + } +} + +void DBusServiceRegistry::updateListeners(const std::string& conName, const std::string& objName, const std::string& intName , bool available) { + auto found = availabilityCallbackList.equal_range(findCommonAPIAddressForDBusAddress(conName, objName, intName)); + auto foundIter = found.first; + while (foundIter != found.second) { + foundIter->second(true); + foundIter++; + } + +} + +void DBusServiceRegistry::addProvidedServiceInstancesToCache(const std::string& dbusNames) { + getManagedObjects(dbusNames); +} + +void DBusServiceRegistry::addProvidedServiceInstancesToCache(std::vector& dbusNames) { + + std::shared_ptr> dbusList = std::make_shared>(dbusNames.begin(), dbusNames.end()); + + auto iter = dbusList->begin(); + + while (iter != dbusList->end()) { + + auto callMessage = DBusMessage::createMethodCall( + iter->c_str(), + "/", + "org.freedesktop.DBus.ObjectManager", + "GetManagedObjects", + ""); + dbusConnection_->sendDBusMessageWithReplyAsync( + callMessage, + DBusProxyAsyncCallbackHandler::create( + std::bind( + &DBusServiceRegistry::onManagedPathsList, + this, + std::placeholders::_1, + std::placeholders::_2, + iter, + dbusList)), 10); + iter++; + } +} + + +DBusServiceInstanceId DBusServiceRegistry::findInstanceIdMapping(const std::string& instanceId) const { + DBusServiceInstanceId instanceDescriptor; + findFallbackInstanceIdMapping(instanceId, instanceDescriptor.first, instanceDescriptor.second); + return instanceDescriptor; +} + +std::string DBusServiceRegistry::findInstanceIdMapping(const DBusServiceInstanceId& dbusInstanceId) const { + return findFallbackInstanceIdMapping(dbusInstanceId.first, dbusInstanceId.second); +} + +inline const bool isServiceName(const std::string& name) { + return name[0] != ':'; +} + +void DBusServiceRegistry::onDBusNameOwnerChangedEvent(const std::string& affectedName, + const std::string& oldOwner, + const std::string& newOwner) { + if (isServiceName(affectedName)) { + if(!oldOwner.empty()) { + removeProvidedServiceInstancesFromCache(affectedName); + } + + if (!newOwner.empty()) { + addProvidedServiceInstancesToCache(affectedName); + } + } +} + + +void DBusServiceRegistry::removeProvidedServiceInstancesFromCache(const std::string& dbusWellKnownBusName) { + auto providersForInterfacesIteratorPair = dbusCachedProvidersForInterfaces_.equal_range(dbusWellKnownBusName); + + //Iteriere über (interfaceName, (serviceInstanceId)) + while(providersForInterfacesIteratorPair.first != providersForInterfacesIteratorPair.second) { + + DBusServiceInstanceId dbusInstanceId = providersForInterfacesIteratorPair.first->second; + if(dbusInstanceId.first == dbusWellKnownBusName) { + auto toErase = providersForInterfacesIteratorPair.first; + ++providersForInterfacesIteratorPair.first; + dbusCachedProvidersForInterfaces_.erase(toErase); + } + + ++providersForInterfacesIteratorPair.first; + } +} + +void DBusServiceRegistry::onListNames(const CommonAPI::CallStatus& callStatus, std::vector existingBusConnections) { + + if (callStatus == CallStatus::SUCCESS) { + std::vector dbusLivingServiceBusNames; + for (const std::string& connectionName : existingBusConnections) { + const bool isWellKnownName = (connectionName[0] != ':'); + + if (isWellKnownName) { + dbusLivingServiceBusNames.push_back(connectionName); + } + } + addProvidedServiceInstancesToCache(dbusLivingServiceBusNames); + } +} + +void DBusServiceRegistry::cacheAllServices() { + CommonAPI::CallStatus callStatus; + std::vector existingBusConnections; + dbusConnection_->getDBusDaemonProxy()->listNames(callStatus, existingBusConnections); + onListNames(callStatus, existingBusConnections); +} + + +}// namespace DBus +} // namespace CommonAPI diff --git a/CommonAPI-DBus/src/CommonAPI/DBus/DBusServiceRegistry.h b/CommonAPI-DBus/src/CommonAPI/DBus/DBusServiceRegistry.h new file mode 100644 index 0000000..f4c9a77 --- /dev/null +++ b/CommonAPI-DBus/src/CommonAPI/DBus/DBusServiceRegistry.h @@ -0,0 +1,116 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#ifndef COMMONAPI_DBUS_DBUS_SERVICE_REGISTRY_H_ +#define COMMONAPI_DBUS_DBUS_SERVICE_REGISTRY_H_ + + +#include +#include + +#include "DBusConnection.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace CommonAPI { +namespace DBus { + +typedef Event NameOwnerChangedEvent; + +typedef Event::Subscription NameOwnerChangedEventSubscription; + +typedef std::pair DBusServiceInstanceId; + +typedef std::unordered_map PropertyDictStub; +typedef std::unordered_map InterfaceToPropertyDict; +typedef std::unordered_map DBusObjectToInterfaceDict; + +class DBusConnection; +class DBusDaemonProxy; + + +class DBusServiceRegistry { + public: + static constexpr const char* getManagedObjectsDBusSignature_ = "a{oa{sa{sv}}}"; + + DBusServiceRegistry() = delete; + DBusServiceRegistry(const DBusServiceRegistry&) = delete; + DBusServiceRegistry& operator=(const DBusServiceRegistry&) = delete; + + DBusServiceRegistry(std::shared_ptr connection); + ~DBusServiceRegistry(); + + std::vector getAvailableServiceInstances(const std::string& interfaceName, + const std::string& domainName = "local"); + + bool isServiceInstanceAlive(const std::string& instanceID, + const std::string& interfaceName, + const std::string& domainName = "local"); + + bool isServiceInstanceAlive(const std::string& address); + + bool isReady(); + + bool isReadyBlocking(); + + void registerAvailabilityListener(const std::string& service, const std::function& listener); + + std::future& getReadyFuture(); + + DBusServiceStatusEvent& getServiceStatusEvent(); + + private: + void cacheAllServices(); + + void removeProvidedServiceInstancesFromCache(const std::string& serviceBusName); + void addProvidedServiceInstancesToCache(std::vector& dbusNames); + void addProvidedServiceInstancesToCache(const std::string& dbusNames); + void addAllProvidedServiceInstancesToCache(const std::vector& serviceBusNames); + + void getManagedObjects(const std::string& serviceBusName); + + void onDBusNameOwnerChangedEvent(const std::string& name, const std::string& oldOwner, const std::string& newOwner); + + bool isRemoteServiceVersionMatchingLocalVersion(const std::string& serviceBusName, const std::string& serviceInterfaceName); + bool isServiceInstanceAliveHelper(const std::string& connectionName) const; + + DBusServiceInstanceId findInstanceIdMapping(const std::string& instanceId) const; + std::string findInstanceIdMapping(const DBusServiceInstanceId& dbusInstanceId) const; + + void onManagedPaths(const CallStatus& status, DBusObjectToInterfaceDict replyMessage, std::string dbusWellKnownBusName); + void onManagedPathsList(const CallStatus& status, DBusObjectToInterfaceDict managedObjects, std::list::iterator iter, std::shared_ptr> list); + + std::multimap dbusCachedProvidersForInterfaces_; + + std::shared_ptr dbusConnection_; + + std::unordered_multimap> availabilityCallbackList; + + bool ready; + + void onListNames(const CommonAPI::CallStatus&, std::vector); + + NameOwnerChangedEvent::Subscription dbusNameOwnerChangedEventSubscription_; + + void updateListeners(const std::string& conName, const std::string& objName, const std::string& intName , bool available); + + mutable std::future readyFuture_; + mutable std::promise readyPromise_; + + std::mutex readyMutex_; + + DBusServiceStatusEvent serviceStatusEvent_; +}; + + +} // namespace DBus +} // namespace CommonAPI + +#endif // COMMONAPI_DBUS_DBUS_SERVICE_REGISTRY_H_ diff --git a/CommonAPI-DBus/src/CommonAPI/DBus/DBusServiceStatusEvent.cpp b/CommonAPI-DBus/src/CommonAPI/DBus/DBusServiceStatusEvent.cpp new file mode 100644 index 0000000..1ae833a --- /dev/null +++ b/CommonAPI-DBus/src/CommonAPI/DBus/DBusServiceStatusEvent.cpp @@ -0,0 +1,44 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include "DBusServiceStatusEvent.h" +#include "DBusServiceRegistry.h" +#include + +namespace CommonAPI { +namespace DBus { + +DBusServiceStatusEvent::DBusServiceStatusEvent(std::shared_ptr registry) : + registry_(registry) { +} + +void DBusServiceStatusEvent::onFirstListenerAdded(const std::string& serviceName, const Listener& listener) { + if (registry_) { + registry_->registerAvailabilityListener(serviceName, std::bind( + &DBusServiceStatusEvent::availabilityEvent, + this, + serviceName, + std::placeholders::_1)); + } +} + +void DBusServiceStatusEvent::availabilityEvent(const std::string& name, const bool& available) { + + const AvailabilityStatus availabilityStatus = !available ? AvailabilityStatus::NOT_AVAILABLE : + AvailabilityStatus::AVAILABLE; + notifyListeners(name, availabilityStatus); +} + +void DBusServiceStatusEvent::onListenerAdded(const std::string& name, const Listener& listener) { + if (registry_) { + const AvailabilityStatus availabilityStatus = + !registry_->isServiceInstanceAlive(name) ? AvailabilityStatus::NOT_AVAILABLE : + AvailabilityStatus::AVAILABLE; + + notifyListeners(name, availabilityStatus); + } + +} + +} // namespace DBus +} // namespace CommonAPI diff --git a/CommonAPI-DBus/src/CommonAPI/DBus/DBusServiceStatusEvent.h b/CommonAPI-DBus/src/CommonAPI/DBus/DBusServiceStatusEvent.h new file mode 100644 index 0000000..0c4f6e9 --- /dev/null +++ b/CommonAPI-DBus/src/CommonAPI/DBus/DBusServiceStatusEvent.h @@ -0,0 +1,39 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#ifndef COMMONAPI_DBUS_DBUS_SERVICE_STATUS_EVENT_H_ +#define COMMONAPI_DBUS_DBUS_SERVICE_STATUS_EVENT_H_ + +#include "DBusMultiEvent.h" + +#include +#include + +#include +#include + +namespace CommonAPI { +namespace DBus { + + +class DBusServiceRegistry; + +class DBusServiceStatusEvent: public DBusMultiEvent { + public: + DBusServiceStatusEvent(std::shared_ptr registry); + + protected: + void onFirstListenerAdded(const std::string& serviceName, const Listener& listener); + void onListenerAdded(const std::string& serviceName, const Listener& listener); + + private: + void availabilityEvent(const std::string& name, const bool& available); + + std::shared_ptr registry_; +}; + +} // namespace DBus +} // namespace CommonAPI + +#endif // COMMONAPI_DBUS_DBUS_SERVICE_STATUS_EVENT_H_ + diff --git a/CommonAPI-DBus/src/CommonAPI/DBus/DBusStubAdapter.cpp b/CommonAPI-DBus/src/CommonAPI/DBus/DBusStubAdapter.cpp new file mode 100644 index 0000000..b217871 --- /dev/null +++ b/CommonAPI-DBus/src/CommonAPI/DBus/DBusStubAdapter.cpp @@ -0,0 +1,103 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include "DBusStubAdapter.h" + +#include + +#include +#include +#include + +namespace CommonAPI { +namespace DBus { + +const std::string DBusStubAdapter::domain_ = "local"; + +DBusStubAdapter::DBusStubAdapter(const std::string& dbusBusName, + const std::string& dbusObjectPath, + const std::string& interfaceName, + const std::shared_ptr& dbusConnection) : + dbusBusName_(dbusBusName), + dbusObjectPath_(dbusObjectPath), + interfaceName_(interfaceName), + dbusConnection_(dbusConnection), + isInitialized_(false) { + + assert(!dbusBusName_.empty()); + assert(!interfaceName_.empty()); + assert(!dbusObjectPath_.empty()); + assert(dbusObjectPath_[0] == '/'); + assert(!interfaceName.empty()); + assert(dbusConnection_); +} + +DBusStubAdapter::~DBusStubAdapter() { + assert(dbusConnection_); + assert(isInitialized_); + + dbusConnection_->getDBusObjectManager()->unregisterInterfaceHandler(dbusIntrospectionInterfaceHandlerToken_); + dbusConnection_->getDBusObjectManager()->unregisterInterfaceHandler(dbusInterfaceHandlerToken_); +} + +void DBusStubAdapter::init() { + dbusIntrospectionInterfaceHandlerToken_ = dbusConnection_->getDBusObjectManager()->registerInterfaceHandler( + dbusObjectPath_, + "org.freedesktop.DBus.Introspectable", + std::bind(&DBusStubAdapter::onIntrospectionInterfaceDBusMessage, this, std::placeholders::_1)); + + dbusInterfaceHandlerToken_ = dbusConnection_->getDBusObjectManager()->registerInterfaceHandler( + dbusObjectPath_, + interfaceName_, + std::bind(&DBusStubAdapter::onInterfaceDBusMessage, this, std::placeholders::_1)); + + isInitialized_ = true; +} + +const std::string DBusStubAdapter::getAddress() const { + return domain_ + ":" + interfaceName_ + ":" + dbusBusName_; +} + +const std::string& DBusStubAdapter::getDomain() const { + return domain_; +} + +const std::string& DBusStubAdapter::getServiceId() const { + return interfaceName_; +} + +const std::string& DBusStubAdapter::getInstanceId() const { + return dbusObjectPath_; +} + +bool DBusStubAdapter::onIntrospectionInterfaceDBusMessage(const DBusMessage& dbusMessage) { + bool dbusMessageHandled = false; + + if (dbusMessage.isMethodCallType() && dbusMessage.hasMemberName("Introspect")) { + std::stringstream xmlData(std::ios_base::out); + xmlData << "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + << getMethodsDBusIntrospectionXmlData() << "\n" + "\n" + ""; + + DBusMessage dbusMessageReply = dbusMessage.createMethodReturn("s"); + DBusOutputStream dbusOutputStream(dbusMessageReply); + dbusOutputStream << xmlData.str(); + dbusOutputStream.flush(); + + dbusMessageHandled = dbusConnection_->sendDBusMessage(dbusMessageReply); + } + + return dbusMessageHandled; +} + +} // namespace dbus +} // namespace CommonAPI diff --git a/CommonAPI-DBus/src/CommonAPI/DBus/DBusStubAdapter.h b/CommonAPI-DBus/src/CommonAPI/DBus/DBusStubAdapter.h new file mode 100644 index 0000000..90c12f5 --- /dev/null +++ b/CommonAPI-DBus/src/CommonAPI/DBus/DBusStubAdapter.h @@ -0,0 +1,69 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#ifndef COMMONAPI_DBUS_DBUS_STUB_ADAPTER_H_ +#define COMMONAPI_DBUS_DBUS_STUB_ADAPTER_H_ + +#include "DBusConnection.h" + +#include +#include + +#include +#include + +namespace CommonAPI { +namespace DBus { + +class DBusStubAdapter: virtual public CommonAPI::StubAdapter { + public: + DBusStubAdapter(const std::string& dbusBusName, + const std::string& dbusObjectPath, + const std::string& interfaceName, + const std::shared_ptr& dbusConnection); + + virtual ~DBusStubAdapter(); + + virtual void init(); + + virtual const std::string getAddress() const; + virtual const std::string& getDomain() const; + virtual const std::string& getServiceId() const; + virtual const std::string& getInstanceId() const; + + inline const std::string& getObjectPath() const; + + inline const std::shared_ptr& getDBusConnection() const; + + protected: + virtual const char* getMethodsDBusIntrospectionXmlData() const = 0; + virtual bool onInterfaceDBusMessage(const DBusMessage& dbusMessage) = 0; + + private: + bool onIntrospectionInterfaceDBusMessage(const DBusMessage& dbusMessage); + + const std::string dbusBusName_; + const std::string dbusObjectPath_; + const std::string interfaceName_; + const std::shared_ptr dbusConnection_; + + bool isInitialized_; + + DBusInterfaceHandlerToken dbusIntrospectionInterfaceHandlerToken_; + DBusInterfaceHandlerToken dbusInterfaceHandlerToken_; + + static const std::string domain_; +}; + +const std::string& DBusStubAdapter::getObjectPath() const { + return dbusObjectPath_; +} + +const std::shared_ptr& DBusStubAdapter::getDBusConnection() const { + return dbusConnection_; +} + +} // namespace dbus +} // namespace CommonAPI + +#endif // COMMONAPI_DBUS_DBUS_STUB_ADAPTER_H_ diff --git a/CommonAPI-DBus/src/CommonAPI/DBus/DBusStubAdapterHelper.h b/CommonAPI-DBus/src/CommonAPI/DBus/DBusStubAdapterHelper.h new file mode 100644 index 0000000..0f20bd5 --- /dev/null +++ b/CommonAPI-DBus/src/CommonAPI/DBus/DBusStubAdapterHelper.h @@ -0,0 +1,362 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#ifndef COMMONAPI_DBUS_DBUS_STUB_ADAPTER_HELPER_H_ +#define COMMONAPI_DBUS_DBUS_STUB_ADAPTER_HELPER_H_ + +#include "DBusStubAdapter.h" +#include "DBusInputStream.h" +#include "DBusOutputStream.h" +#include "DBusHelper.h" + +#include +#include +#include +#include +#include + +namespace CommonAPI { +namespace DBus { + +template +class DBusStubAdapterHelper: public DBusStubAdapter, public std::enable_shared_from_this { + public: + typedef typename _StubClass::StubAdapterType StubAdapterType; + typedef typename _StubClass::RemoteEventHandlerType RemoteEventHandlerType; + + class StubDispatcher { + public: + virtual ~StubDispatcher() { } + virtual bool dispatchDBusMessage(const DBusMessage& dbusMessage, DBusStubAdapterHelper<_StubClass>& dbusStubAdapterHelper) = 0; + }; + + public: + DBusStubAdapterHelper(const std::string& dbusBusName, + const std::string& dbusObjectPath, + const std::string& interfaceName, + const std::shared_ptr& dbusConnection, + std::shared_ptr<_StubClass> stub): + DBusStubAdapter(dbusBusName, dbusObjectPath, interfaceName, dbusConnection), + stub_(stub) { + } + + virtual ~DBusStubAdapterHelper() { } + + virtual void init() { + DBusStubAdapter::init(); + remoteEventHandler_ = stub_->initStubAdapter(getStubAdapter()); + } + + inline std::shared_ptr getStubAdapter() { + return this->shared_from_this(); + } + + inline const std::shared_ptr<_StubClass>& getStub() { + return stub_; + } + + inline RemoteEventHandlerType* getRemoteEventHandler() { + return remoteEventHandler_; + } + + protected: + // interfaceMemberName, interfaceMemberSignature + typedef std::pair DBusInterfaceMemberPath; + typedef std::unordered_map StubDispatcherTable; + + virtual bool onInterfaceDBusMessage(const DBusMessage& dbusMessage) { + const char* interfaceMemberName = dbusMessage.getMemberName(); + const char* interfaceMemberSignature = dbusMessage.getSignatureString(); + + assert(interfaceMemberName); + assert(interfaceMemberSignature); + + DBusInterfaceMemberPath dbusInterfaceMemberPath(interfaceMemberName, interfaceMemberSignature); + auto findIterator = this->stubDispatcherTable_.find(dbusInterfaceMemberPath); + const bool foundInterfaceMemberHandler = (findIterator != this->stubDispatcherTable_.end()); + bool dbusMessageHandled = false; + + if (foundInterfaceMemberHandler) { + StubDispatcher* stubDispatcher = findIterator->second; + dbusMessageHandled = stubDispatcher->dispatchDBusMessage(dbusMessage, *this); + } + + return dbusMessageHandled; + } + + std::shared_ptr<_StubClass> stub_; + RemoteEventHandlerType* remoteEventHandler_; + static const StubDispatcherTable stubDispatcherTable_; +}; + +template< class > +struct DBusStubSignalHelper; + +template class _In, class... _InArgs> +struct DBusStubSignalHelper<_In<_InArgs...>> { + template + static bool sendSignal(const _DBusStub& dbusStub, + const char* signalName, + const char* signalSignature, + const _InArgs&... inArgs) { + DBusMessage dbusMessage = DBusMessage::createSignal( + dbusStub.getObjectPath().c_str(), + dbusStub.getInterfaceName(), + signalName, + signalSignature); + + if (sizeof...(_InArgs) > 0) { + DBusOutputStream outputStream(dbusMessage); + const bool success = DBusSerializableArguments<_InArgs...>::serialize(outputStream, inArgs...); + if (!success) { + return false; + } + outputStream.flush(); + } + + const bool dbusMessageSent = dbusStub.getDBusConnection()->sendDBusMessage(dbusMessage); + return dbusMessageSent; + } +}; + + + +template< class, class > +class DBusMethodStubDispatcher; + +template < + typename _StubClass, + template class _In, class... _InArgs> +class DBusMethodStubDispatcher<_StubClass, _In<_InArgs...> >: public DBusStubAdapterHelper<_StubClass>::StubDispatcher { + public: + typedef DBusStubAdapterHelper<_StubClass> DBusStubAdapterHelperType; + typedef void (_StubClass::*_StubFunctor)(_InArgs...); + + DBusMethodStubDispatcher(_StubFunctor stubFunctor): + stubFunctor_(stubFunctor) { + } + + bool dispatchDBusMessage(const DBusMessage& dbusMessage, DBusStubAdapterHelperType& dbusStubAdapterHelper) { + return handleDBusMessage(dbusMessage, dbusStubAdapterHelper, typename make_sequence::type()); + } + + private: + template + inline bool handleDBusMessage(const DBusMessage& dbusMessage, + DBusStubAdapterHelperType& dbusStubAdapterHelper, + index_sequence<_InArgIndices...>) const { + std::tuple<_InArgs...> argTuple; + + if (sizeof...(_InArgs) > 0) { + DBusInputStream dbusInputStream(dbusMessage); + const bool success = DBusSerializableArguments<_InArgs...>::deserialize(dbusInputStream, std::get<_InArgIndices>(argTuple)...); + if (!success) + return false; + } + + (dbusStubAdapterHelper.getStub().get()->*stubFunctor_)(std::move(std::get<_InArgIndices>(argTuple))...); + + return true; + } + + _StubFunctor stubFunctor_; +}; + + +template< class, class, class > +class DBusMethodWithReplyStubDispatcher; + +template < + typename _StubClass, + template class _In, class... _InArgs, + template class _Out, class... _OutArgs> +class DBusMethodWithReplyStubDispatcher<_StubClass, _In<_InArgs...>, _Out<_OutArgs...> >: + public DBusStubAdapterHelper<_StubClass>::StubDispatcher { + public: + typedef DBusStubAdapterHelper<_StubClass> DBusStubAdapterHelperType; + typedef void (_StubClass::*_StubFunctor)(_InArgs..., _OutArgs&...); + + DBusMethodWithReplyStubDispatcher(_StubFunctor stubFunctor, const char* dbusReplySignature): + stubFunctor_(stubFunctor), + dbusReplySignature_(dbusReplySignature) { + } + + bool dispatchDBusMessage(const DBusMessage& dbusMessage, DBusStubAdapterHelperType& dbusStubAdapterHelper) { + return handleDBusMessage( + dbusMessage, + dbusStubAdapterHelper, + typename make_sequence_range::type(), + typename make_sequence_range::type()); + } + + private: + template + inline bool handleDBusMessage(const DBusMessage& dbusMessage, + DBusStubAdapterHelperType& dbusStubAdapterHelper, + index_sequence<_InArgIndices...>, + index_sequence<_OutArgIndices...>) const { + std::tuple<_InArgs..., _OutArgs...> argTuple; + + if (sizeof...(_InArgs) > 0) { + DBusInputStream dbusInputStream(dbusMessage); + const bool success = DBusSerializableArguments<_InArgs...>::deserialize(dbusInputStream, std::get<_InArgIndices>(argTuple)...); + if (!success) + return false; + } + + (dbusStubAdapterHelper.getStub().get()->*stubFunctor_)(std::move(std::get<_InArgIndices>(argTuple))..., std::get<_OutArgIndices>(argTuple)...); + + DBusMessage dbusMessageReply = dbusMessage.createMethodReturn(dbusReplySignature_); + + if (sizeof...(_OutArgs) > 0) { + DBusOutputStream dbusOutputStream(dbusMessageReply); + const bool success = DBusSerializableArguments<_OutArgs...>::serialize(dbusOutputStream, std::get<_OutArgIndices>(argTuple)...); + if (!success) + return false; + + dbusOutputStream.flush(); + } + + return dbusStubAdapterHelper.getDBusConnection()->sendDBusMessage(dbusMessageReply); + } + + _StubFunctor stubFunctor_; + const char* dbusReplySignature_; +}; + + +template +class DBusGetAttributeStubDispatcher: public DBusStubAdapterHelper<_StubClass>::StubDispatcher { + public: + typedef DBusStubAdapterHelper<_StubClass> DBusStubAdapterHelperType; + typedef const _AttributeType& (_StubClass::*GetStubFunctor)(); + + DBusGetAttributeStubDispatcher(GetStubFunctor getStubFunctor, const char* dbusSignature): + getStubFunctor_(getStubFunctor), + dbusSignature_(dbusSignature) { + } + + bool dispatchDBusMessage(const DBusMessage& dbusMessage, DBusStubAdapterHelperType& dbusStubAdapterHelper) { + return sendAttributeValueReply(dbusMessage, dbusStubAdapterHelper); + } + + protected: + inline bool sendAttributeValueReply(const DBusMessage& dbusMessage, DBusStubAdapterHelperType& dbusStubAdapterHelper) { + DBusMessage dbusMessageReply = dbusMessage.createMethodReturn(dbusSignature_); + DBusOutputStream dbusOutputStream(dbusMessageReply); + + dbusOutputStream << (dbusStubAdapterHelper.getStub().get()->*getStubFunctor_)(); + dbusOutputStream.flush(); + + return dbusStubAdapterHelper.getDBusConnection()->sendDBusMessage(dbusMessageReply); + } + + GetStubFunctor getStubFunctor_; + const char* dbusSignature_; +}; + + +template +class DBusSetAttributeStubDispatcher: public DBusGetAttributeStubDispatcher<_StubClass, _AttributeType> { + public: + typedef typename DBusGetAttributeStubDispatcher<_StubClass, _AttributeType>::DBusStubAdapterHelperType DBusStubAdapterHelperType; + typedef typename DBusStubAdapterHelperType::RemoteEventHandlerType RemoteEventHandlerType; + + typedef typename DBusGetAttributeStubDispatcher<_StubClass, _AttributeType>::GetStubFunctor GetStubFunctor; + typedef bool (RemoteEventHandlerType::*OnRemoteSetFunctor)(_AttributeType); + typedef void (RemoteEventHandlerType::*OnRemoteChangedFunctor)(); + + DBusSetAttributeStubDispatcher(GetStubFunctor getStubFunctor, + OnRemoteSetFunctor onRemoteSetFunctor, + OnRemoteChangedFunctor onRemoteChangedFunctor, + const char* dbusSignature) : + DBusGetAttributeStubDispatcher<_StubClass, _AttributeType>(getStubFunctor, dbusSignature), + onRemoteSetFunctor_(onRemoteSetFunctor), + onRemoteChangedFunctor_(onRemoteChangedFunctor) { + } + + bool dispatchDBusMessage(const DBusMessage& dbusMessage, DBusStubAdapterHelperType& dbusStubAdapterHelper) { + bool attributeValueChanged; + + if (!setAttributeValue(dbusMessage, dbusStubAdapterHelper, attributeValueChanged)) + return false; + + if (attributeValueChanged) + notifyOnRemoteChanged(dbusStubAdapterHelper); + + return true; + } + + protected: + inline bool setAttributeValue(const DBusMessage& dbusMessage, DBusStubAdapterHelperType& dbusStubAdapterHelper, bool& attributeValueChanged) { + DBusInputStream dbusInputStream(dbusMessage); + _AttributeType attributeValue; + dbusInputStream >> attributeValue; + if (dbusInputStream.hasError()) + return false; + + attributeValueChanged = (dbusStubAdapterHelper.getRemoteEventHandler()->*onRemoteSetFunctor_)(std::move(attributeValue)); + + return this->sendAttributeValueReply(dbusMessage, dbusStubAdapterHelper); + } + + inline void notifyOnRemoteChanged(DBusStubAdapterHelperType& dbusStubAdapterHelper) { + (dbusStubAdapterHelper.getRemoteEventHandler()->*onRemoteChangedFunctor_)(); + } + + inline const _AttributeType& getAttributeValue(DBusStubAdapterHelperType& dbusStubAdapterHelper) { + return (dbusStubAdapterHelper.getStub().get()->*(this->getStubFunctor_))(); + } + + const OnRemoteSetFunctor onRemoteSetFunctor_; + const OnRemoteChangedFunctor onRemoteChangedFunctor_; +}; + + +template +class DBusSetObservableAttributeStubDispatcher: public DBusSetAttributeStubDispatcher<_StubClass, _AttributeType> { + public: + typedef typename DBusSetAttributeStubDispatcher<_StubClass, _AttributeType>::DBusStubAdapterHelperType DBusStubAdapterHelperType; + typedef typename DBusStubAdapterHelperType::StubAdapterType StubAdapterType; + + typedef typename DBusSetAttributeStubDispatcher<_StubClass, _AttributeType>::GetStubFunctor GetStubFunctor; + typedef typename DBusSetAttributeStubDispatcher<_StubClass, _AttributeType>::OnRemoteSetFunctor OnRemoteSetFunctor; + typedef typename DBusSetAttributeStubDispatcher<_StubClass, _AttributeType>::OnRemoteChangedFunctor OnRemoteChangedFunctor; + typedef void (StubAdapterType::*FireChangedFunctor)(const _AttributeType&); + + DBusSetObservableAttributeStubDispatcher(GetStubFunctor getStubFunctor, + OnRemoteSetFunctor onRemoteSetFunctor, + OnRemoteChangedFunctor onRemoteChangedFunctor, + FireChangedFunctor fireChangedFunctor, + const char* dbusSignature) : + DBusSetAttributeStubDispatcher<_StubClass, _AttributeType>(getStubFunctor, + onRemoteSetFunctor, + onRemoteChangedFunctor, + dbusSignature), + fireChangedFunctor_(fireChangedFunctor) { + } + + bool dispatchDBusMessage(const DBusMessage& dbusMessage, DBusStubAdapterHelperType& dbusStubAdapterHelper) { + bool attributeValueChanged; + if (!this->setAttributeValue(dbusMessage, dbusStubAdapterHelper, attributeValueChanged)) + return false; + + if (attributeValueChanged) { + fireAttributeValueChanged(dbusStubAdapterHelper); + this->notifyOnRemoteChanged(dbusStubAdapterHelper); + } + return true; + } + + private: + inline void fireAttributeValueChanged(DBusStubAdapterHelperType& dbusStubAdapterHelper) { + (dbusStubAdapterHelper.getStubAdapter().get()->*fireChangedFunctor_)(this->getAttributeValue(dbusStubAdapterHelper)); + } + + const FireChangedFunctor fireChangedFunctor_; +}; + +} // namespace DBus +} // namespace CommonAPI + +#endif // COMMONAPI_DBUS_DBUS_STUB_ADAPTER_HELPER_H_ diff --git a/CommonAPI-DBus/src/CommonAPI/DBus/DBusUtils.h b/CommonAPI-DBus/src/CommonAPI/DBus/DBusUtils.h new file mode 100644 index 0000000..fa26f0c --- /dev/null +++ b/CommonAPI-DBus/src/CommonAPI/DBus/DBusUtils.h @@ -0,0 +1,64 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#ifndef DBUSUTILS_H_ +#define DBUSUTILS_H_ + +#include +#include +#include +#include + +namespace CommonAPI { +namespace DBus { + +inline std::vector& split(const std::string& s, char delim, std::vector& elems) { + std::istringstream ss(s); + std::string item; + while (std::getline(ss, item, delim)) { + elems.push_back(item); + } + return elems; +} + +inline std::vector split(const std::string& s, char delim) { + std::vector elems; + return split(s, delim, elems); +} + +inline void findFallbackInstanceIdMapping(const std::string& instanceId, + std::string& connectionName, + std::string& objectPath) { + connectionName = instanceId; + objectPath = '/' + instanceId; + std::replace(objectPath.begin(), objectPath.end(), '.', '/'); +} + +inline std::string findCommonAPIAddressForDBusAddress(const std::string& conName, + const std::string& objName, + const std::string& intName) { + + return "local:" + intName + ":" + conName; +} + +inline std::string findFallbackInstanceIdMapping(const std::string& connectionName, const std::string& objectPath) { + return connectionName; +} + +template +inline bool checkReady(_FutureWaitType&); + +template<> +inline bool checkReady(bool& returnedValue) { + return returnedValue; +} + +template<> +inline bool checkReady(std::future_status& returnedValue) { + return returnedValue == std::future_status::ready; +} + +} +} + +#endif /* DBUSUTILS_H_ */ diff --git a/CommonAPI-DBus/src/murmurhash/MurmurHash3.cpp b/CommonAPI-DBus/src/murmurhash/MurmurHash3.cpp new file mode 100644 index 0000000..c2d2fb7 --- /dev/null +++ b/CommonAPI-DBus/src/murmurhash/MurmurHash3.cpp @@ -0,0 +1,335 @@ +//----------------------------------------------------------------------------- +// MurmurHash3 was written by Austin Appleby, and is placed in the public +// domain. The author hereby disclaims copyright to this source code. + +// Note - The x86 and x64 versions do _not_ produce the same results, as the +// algorithms are optimized for their respective platforms. You can still +// compile and run any of them on any platform, but your performance with the +// non-native version will be less than optimal. + +#include "MurmurHash3.h" + +//----------------------------------------------------------------------------- +// Platform-specific functions and macros + +// Microsoft Visual Studio + +#if defined(_MSC_VER) + +#define FORCE_INLINE __forceinline + +#include + +#define ROTL32(x,y) _rotl(x,y) +#define ROTL64(x,y) _rotl64(x,y) + +#define BIG_CONSTANT(x) (x) + +// Other compilers + +#else // defined(_MSC_VER) + +#define FORCE_INLINE __attribute__((always_inline)) + +inline uint32_t rotl32 ( uint32_t x, int8_t r ) +{ + return (x << r) | (x >> (32 - r)); +} + +inline uint64_t rotl64 ( uint64_t x, int8_t r ) +{ + return (x << r) | (x >> (64 - r)); +} + +#define ROTL32(x,y) rotl32(x,y) +#define ROTL64(x,y) rotl64(x,y) + +#define BIG_CONSTANT(x) (x##LLU) + +#endif // !defined(_MSC_VER) + +//----------------------------------------------------------------------------- +// Block read - if your platform needs to do endian-swapping or can only +// handle aligned reads, do the conversion here + +inline uint32_t getblock ( const uint32_t * p, int i ) +{ + return p[i]; +} + +inline uint64_t getblock ( const uint64_t * p, int i ) +{ + return p[i]; +} + +//----------------------------------------------------------------------------- +// Finalization mix - force all bits of a hash block to avalanche + +inline uint32_t fmix ( uint32_t h ) +{ + h ^= h >> 16; + h *= 0x85ebca6b; + h ^= h >> 13; + h *= 0xc2b2ae35; + h ^= h >> 16; + + return h; +} + +//---------- + +inline uint64_t fmix ( uint64_t k ) +{ + k ^= k >> 33; + k *= BIG_CONSTANT(0xff51afd7ed558ccd); + k ^= k >> 33; + k *= BIG_CONSTANT(0xc4ceb9fe1a85ec53); + k ^= k >> 33; + + return k; +} + +//----------------------------------------------------------------------------- + +void MurmurHash3_x86_32 ( const void * key, int len, + uint32_t seed, void * out ) +{ + const uint8_t * data = (const uint8_t*)key; + const int nblocks = len / 4; + + uint32_t h1 = seed; + + uint32_t c1 = 0xcc9e2d51; + uint32_t c2 = 0x1b873593; + + //---------- + // body + + const uint32_t * blocks = (const uint32_t *)(data + nblocks*4); + + for(int i = -nblocks; i; i++) + { + uint32_t k1 = getblock(blocks,i); + + k1 *= c1; + k1 = ROTL32(k1,15); + k1 *= c2; + + h1 ^= k1; + h1 = ROTL32(h1,13); + h1 = h1*5+0xe6546b64; + } + + //---------- + // tail + + const uint8_t * tail = (const uint8_t*)(data + nblocks*4); + + uint32_t k1 = 0; + + switch(len & 3) + { + case 3: k1 ^= tail[2] << 16; + case 2: k1 ^= tail[1] << 8; + case 1: k1 ^= tail[0]; + k1 *= c1; k1 = ROTL32(k1,15); k1 *= c2; h1 ^= k1; + }; + + //---------- + // finalization + + h1 ^= len; + + h1 = fmix(h1); + + *(uint32_t*)out = h1; +} + +//----------------------------------------------------------------------------- + +void MurmurHash3_x86_128 ( const void * key, const int len, + uint32_t seed, void * out ) +{ + const uint8_t * data = (const uint8_t*)key; + const int nblocks = len / 16; + + uint32_t h1 = seed; + uint32_t h2 = seed; + uint32_t h3 = seed; + uint32_t h4 = seed; + + uint32_t c1 = 0x239b961b; + uint32_t c2 = 0xab0e9789; + uint32_t c3 = 0x38b34ae5; + uint32_t c4 = 0xa1e38b93; + + //---------- + // body + + const uint32_t * blocks = (const uint32_t *)(data + nblocks*16); + + for(int i = -nblocks; i; i++) + { + uint32_t k1 = getblock(blocks,i*4+0); + uint32_t k2 = getblock(blocks,i*4+1); + uint32_t k3 = getblock(blocks,i*4+2); + uint32_t k4 = getblock(blocks,i*4+3); + + k1 *= c1; k1 = ROTL32(k1,15); k1 *= c2; h1 ^= k1; + + h1 = ROTL32(h1,19); h1 += h2; h1 = h1*5+0x561ccd1b; + + k2 *= c2; k2 = ROTL32(k2,16); k2 *= c3; h2 ^= k2; + + h2 = ROTL32(h2,17); h2 += h3; h2 = h2*5+0x0bcaa747; + + k3 *= c3; k3 = ROTL32(k3,17); k3 *= c4; h3 ^= k3; + + h3 = ROTL32(h3,15); h3 += h4; h3 = h3*5+0x96cd1c35; + + k4 *= c4; k4 = ROTL32(k4,18); k4 *= c1; h4 ^= k4; + + h4 = ROTL32(h4,13); h4 += h1; h4 = h4*5+0x32ac3b17; + } + + //---------- + // tail + + const uint8_t * tail = (const uint8_t*)(data + nblocks*16); + + uint32_t k1 = 0; + uint32_t k2 = 0; + uint32_t k3 = 0; + uint32_t k4 = 0; + + switch(len & 15) + { + case 15: k4 ^= tail[14] << 16; + case 14: k4 ^= tail[13] << 8; + case 13: k4 ^= tail[12] << 0; + k4 *= c4; k4 = ROTL32(k4,18); k4 *= c1; h4 ^= k4; + + case 12: k3 ^= tail[11] << 24; + case 11: k3 ^= tail[10] << 16; + case 10: k3 ^= tail[ 9] << 8; + case 9: k3 ^= tail[ 8] << 0; + k3 *= c3; k3 = ROTL32(k3,17); k3 *= c4; h3 ^= k3; + + case 8: k2 ^= tail[ 7] << 24; + case 7: k2 ^= tail[ 6] << 16; + case 6: k2 ^= tail[ 5] << 8; + case 5: k2 ^= tail[ 4] << 0; + k2 *= c2; k2 = ROTL32(k2,16); k2 *= c3; h2 ^= k2; + + case 4: k1 ^= tail[ 3] << 24; + case 3: k1 ^= tail[ 2] << 16; + case 2: k1 ^= tail[ 1] << 8; + case 1: k1 ^= tail[ 0] << 0; + k1 *= c1; k1 = ROTL32(k1,15); k1 *= c2; h1 ^= k1; + }; + + //---------- + // finalization + + h1 ^= len; h2 ^= len; h3 ^= len; h4 ^= len; + + h1 += h2; h1 += h3; h1 += h4; + h2 += h1; h3 += h1; h4 += h1; + + h1 = fmix(h1); + h2 = fmix(h2); + h3 = fmix(h3); + h4 = fmix(h4); + + h1 += h2; h1 += h3; h1 += h4; + h2 += h1; h3 += h1; h4 += h1; + + ((uint32_t*)out)[0] = h1; + ((uint32_t*)out)[1] = h2; + ((uint32_t*)out)[2] = h3; + ((uint32_t*)out)[3] = h4; +} + +//----------------------------------------------------------------------------- + +void MurmurHash3_x64_128 ( const void * key, const int len, + const uint32_t seed, void * out ) +{ + const uint8_t * data = (const uint8_t*)key; + const int nblocks = len / 16; + + uint64_t h1 = seed; + uint64_t h2 = seed; + + uint64_t c1 = BIG_CONSTANT(0x87c37b91114253d5); + uint64_t c2 = BIG_CONSTANT(0x4cf5ad432745937f); + + //---------- + // body + + const uint64_t * blocks = (const uint64_t *)(data); + + for(int i = 0; i < nblocks; i++) + { + uint64_t k1 = getblock(blocks,i*2+0); + uint64_t k2 = getblock(blocks,i*2+1); + + k1 *= c1; k1 = ROTL64(k1,31); k1 *= c2; h1 ^= k1; + + h1 = ROTL64(h1,27); h1 += h2; h1 = h1*5+0x52dce729; + + k2 *= c2; k2 = ROTL64(k2,33); k2 *= c1; h2 ^= k2; + + h2 = ROTL64(h2,31); h2 += h1; h2 = h2*5+0x38495ab5; + } + + //---------- + // tail + + const uint8_t * tail = (const uint8_t*)(data + nblocks*16); + + uint64_t k1 = 0; + uint64_t k2 = 0; + + switch(len & 15) + { + case 15: k2 ^= uint64_t(tail[14]) << 48; + case 14: k2 ^= uint64_t(tail[13]) << 40; + case 13: k2 ^= uint64_t(tail[12]) << 32; + case 12: k2 ^= uint64_t(tail[11]) << 24; + case 11: k2 ^= uint64_t(tail[10]) << 16; + case 10: k2 ^= uint64_t(tail[ 9]) << 8; + case 9: k2 ^= uint64_t(tail[ 8]) << 0; + k2 *= c2; k2 = ROTL64(k2,33); k2 *= c1; h2 ^= k2; + + case 8: k1 ^= uint64_t(tail[ 7]) << 56; + case 7: k1 ^= uint64_t(tail[ 6]) << 48; + case 6: k1 ^= uint64_t(tail[ 5]) << 40; + case 5: k1 ^= uint64_t(tail[ 4]) << 32; + case 4: k1 ^= uint64_t(tail[ 3]) << 24; + case 3: k1 ^= uint64_t(tail[ 2]) << 16; + case 2: k1 ^= uint64_t(tail[ 1]) << 8; + case 1: k1 ^= uint64_t(tail[ 0]) << 0; + k1 *= c1; k1 = ROTL64(k1,31); k1 *= c2; h1 ^= k1; + }; + + //---------- + // finalization + + h1 ^= len; h2 ^= len; + + h1 += h2; + h2 += h1; + + h1 = fmix(h1); + h2 = fmix(h2); + + h1 += h2; + h2 += h1; + + ((uint64_t*)out)[0] = h1; + ((uint64_t*)out)[1] = h2; +} + +//----------------------------------------------------------------------------- + diff --git a/CommonAPI-DBus/src/murmurhash/MurmurHash3.h b/CommonAPI-DBus/src/murmurhash/MurmurHash3.h new file mode 100644 index 0000000..58e9820 --- /dev/null +++ b/CommonAPI-DBus/src/murmurhash/MurmurHash3.h @@ -0,0 +1,37 @@ +//----------------------------------------------------------------------------- +// MurmurHash3 was written by Austin Appleby, and is placed in the public +// domain. The author hereby disclaims copyright to this source code. + +#ifndef _MURMURHASH3_H_ +#define _MURMURHASH3_H_ + +//----------------------------------------------------------------------------- +// Platform-specific functions and macros + +// Microsoft Visual Studio + +#if defined(_MSC_VER) + +typedef unsigned char uint8_t; +typedef unsigned long uint32_t; +typedef unsigned __int64 uint64_t; + +// Other compilers + +#else // defined(_MSC_VER) + +#include + +#endif // !defined(_MSC_VER) + +//----------------------------------------------------------------------------- + +void MurmurHash3_x86_32 ( const void * key, int len, uint32_t seed, void * out ); + +void MurmurHash3_x86_128 ( const void * key, int len, uint32_t seed, void * out ); + +void MurmurHash3_x64_128 ( const void * key, int len, uint32_t seed, void * out ); + +//----------------------------------------------------------------------------- + +#endif // _MURMURHASH3_H_ diff --git a/CommonAPI-DBus/src/test/DBusBenchmarkingTest.cpp b/CommonAPI-DBus/src/test/DBusBenchmarkingTest.cpp new file mode 100644 index 0000000..e9bec02 --- /dev/null +++ b/CommonAPI-DBus/src/test/DBusBenchmarkingTest.cpp @@ -0,0 +1,217 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include +#include +#include + +#include +#include + +#include + +#include + +#include +#include +#include +#include +#include + + +class BenchmarkingTest: public ::testing::Test { + protected: + DBusMessage* libdbusMessage; + DBusMessageIter libdbusMessageWriteIter; + size_t numOfElements; + + void SetUp() { + numOfElements = 2; + libdbusMessage = dbus_message_new_method_call("no.bus.here", "/no/object/here", NULL, "noMethodHere"); + ASSERT_TRUE(libdbusMessage != NULL); + dbus_message_iter_init_append(libdbusMessage, &libdbusMessageWriteIter); + } + + void TearDown() { + dbus_message_unref(libdbusMessage); + } +}; + +template +void prepareLibdbusArray(DBusMessage* libdbusMessage, + const int arrayElementLibdbusType, + const char* arrayElementLibdbusTypeAsString, + const _ArrayElementLibdbusType& arrayInitElementValue, + const uint32_t arrayInitTime, + size_t& libdbusInitElementCount) { + + DBusMessageIter libdbusMessageIter; + DBusMessageIter libdbusMessageContainerIter; + + dbus_message_iter_init_append(libdbusMessage, &libdbusMessageIter); + + dbus_bool_t libdbusSuccess = dbus_message_iter_open_container(&libdbusMessageIter, + DBUS_TYPE_ARRAY, + arrayElementLibdbusTypeAsString, + &libdbusMessageContainerIter); + ASSERT_TRUE(libdbusSuccess); + + + std::chrono::milliseconds libdbusInitTime; + std::chrono::time_point clockStart = std::chrono::high_resolution_clock::now(); + + do { + for (int i = 0; i < 1000; i++) + dbus_message_iter_append_basic(&libdbusMessageContainerIter, + arrayElementLibdbusType, + &arrayInitElementValue); + + libdbusInitElementCount += 1000; + + libdbusInitTime = std::chrono::duration_cast( + std::chrono::high_resolution_clock::now() - clockStart); + } while (libdbusInitTime.count() < arrayInitTime); + + libdbusSuccess = dbus_message_iter_close_container(&libdbusMessageIter, &libdbusMessageContainerIter); + ASSERT_TRUE(libdbusSuccess); + + std::cout << "LibdbusInitTime = " << libdbusInitTime.count() << std::endl; + std::cout << "LibdbusInitElementCount = " << libdbusInitElementCount << std::endl; +} + + +template +void measureLibdbusArrayReadTime(DBusMessage* libdbusMessage, + size_t& libdbusInitElementCount, + std::chrono::milliseconds& libdbusArrayReadTime) { + + DBusMessageIter libdbusMessageIter; + DBusMessageIter libdbusMessageContainerIter; + + dbus_bool_t libdbusSuccess; + + libdbusSuccess = dbus_message_iter_init(libdbusMessage, &libdbusMessageIter); + ASSERT_TRUE(libdbusSuccess); + + dbus_message_iter_recurse(&libdbusMessageIter, &libdbusMessageContainerIter); + + size_t libdbusReadElementCount = 0; + std::chrono::time_point clockStart = std::chrono::high_resolution_clock::now(); + + do { + _ArrayElementLibdbusType libdbusValue; + + dbus_message_iter_get_basic(&libdbusMessageContainerIter, &libdbusValue); + + ++libdbusReadElementCount; + } while (dbus_message_iter_next(&libdbusMessageContainerIter)); + + libdbusArrayReadTime = std::chrono::duration_cast( + std::chrono::high_resolution_clock::now() - clockStart); + + ASSERT_EQ(libdbusInitElementCount, libdbusReadElementCount); +} + + +template +void measureCommonApiArrayReadTime(DBusMessage* libdbusMessage, + std::chrono::milliseconds& commonArrayApiReadTime, + size_t& libdbusInitElementCount) { + + CommonAPI::DBus::DBusMessage dbusMessage(libdbusMessage); + CommonAPI::DBus::DBusInputStream DBusInputStream(dbusMessage); + std::vector<_ArrayElementCommonApiType> commonApiVector; + + std::chrono::time_point clockStart = std::chrono::high_resolution_clock::now(); + + DBusInputStream >> commonApiVector; + + commonArrayApiReadTime = std::chrono::duration_cast( + std::chrono::high_resolution_clock::now() - clockStart); + + ASSERT_EQ(libdbusInitElementCount, commonApiVector.size()); +} + + +template +void measureArrayReadTime( + const int arrayElementLibdbusType, + const char* arrayElementLibdbusTypeAsString, + const _ArrayElementLibdbusType arrayInitElementValue, + const uint32_t arrayInitTime, + std::chrono::milliseconds& libdbusArrayReadTime, + std::chrono::milliseconds& commonArrayApiReadTime) { + + DBusMessage* libdbusMessage; + dbus_bool_t libdbusSuccess; + size_t libdbusInitElementCount = 0; + + libdbusMessage = dbus_message_new_method_call("no.bus.here", "/no/object/here", NULL, "noMethodHere"); + ASSERT_TRUE(libdbusMessage != NULL); + + prepareLibdbusArray<_ArrayElementLibdbusType, _ArrayElementCommonApiType>( + libdbusMessage, + arrayElementLibdbusType, + arrayElementLibdbusTypeAsString, + arrayInitElementValue, + arrayInitTime, + libdbusInitElementCount); + + measureLibdbusArrayReadTime<_ArrayElementLibdbusType, _ArrayElementCommonApiType>( + libdbusMessage, + libdbusInitElementCount, + libdbusArrayReadTime); + + measureCommonApiArrayReadTime<_ArrayElementLibdbusType, _ArrayElementCommonApiType>( + libdbusMessage, + commonArrayApiReadTime, + libdbusInitElementCount); +} + + +TEST_F(BenchmarkingTest, InputStreamReadsIntegerArrayFasterThanLibdbus) { + std::chrono::milliseconds libdbusArrayReadTime; + std::chrono::milliseconds commonApiArrayReadTime; + + measureArrayReadTime(DBUS_TYPE_INT32, + DBUS_TYPE_INT32_AS_STRING, + 1234567890, + 1000, + libdbusArrayReadTime, + commonApiArrayReadTime); + + RecordProperty("LibdbusArrayReadTime", libdbusArrayReadTime.count()); + RecordProperty("CommonApiArrayReadTime", commonApiArrayReadTime.count()); + + std::cout << "LibdbusArrayReadTime = " << libdbusArrayReadTime.count() << std::endl; + std::cout << "CommonApiArrayReadTime = " << commonApiArrayReadTime.count() << std::endl; + + ASSERT_LT(commonApiArrayReadTime.count(), libdbusArrayReadTime.count() * 0.30) + << "CommonAPI::DBus::DBusInputStream must be at least 70% faster than libdbus!"; +} + +TEST_F(BenchmarkingTest, InputStreamReadsStringArrayFasterThanLibdbus) { + std::chrono::milliseconds libdbusArrayReadTime; + std::chrono::milliseconds commonApiArrayReadTime; + + measureArrayReadTime(DBUS_TYPE_STRING, + DBUS_TYPE_STRING_AS_STRING, + const_cast("01234567890123456789"), + 1000, + libdbusArrayReadTime, + commonApiArrayReadTime); + + RecordProperty("LibdbusArrayReadTime", libdbusArrayReadTime.count()); + RecordProperty("CommonApiArrayReadTime", commonApiArrayReadTime.count()); + + std::cout << "LibdbusArrayReadTime = " << libdbusArrayReadTime.count() << std::endl; + std::cout << "CommonApiArrayReadTime = " << commonApiArrayReadTime.count() << std::endl; + + ASSERT_LT(commonApiArrayReadTime.count(), libdbusArrayReadTime.count() * 0.30) + << "CommonAPI::DBus::DBusInputStream must be at least 70% faster than libdbus!"; +} + +int main(int argc, char** argv) { + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/CommonAPI-DBus/src/test/DBusCommunicationTest.cpp b/CommonAPI-DBus/src/test/DBusCommunicationTest.cpp new file mode 100644 index 0000000..d7a0154 --- /dev/null +++ b/CommonAPI-DBus/src/test/DBusCommunicationTest.cpp @@ -0,0 +1,107 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include "commonapi/tests/PredefinedTypeCollection.h" +#include "commonapi/tests/DerivedTypeCollection.h" +#include "commonapi/tests/TestInterfaceProxy.h" +#include "commonapi/tests/TestInterfaceStubDefault.h" +#include "commonapi/tests/TestInterfaceDBusStubAdapter.h" + +#include "commonapi/tests/TestInterfaceDBusProxy.h" + + +class DBusCommunicationTest: public ::testing::Test { + protected: + virtual void SetUp() { + runtime_ = CommonAPI::Runtime::load(); + ASSERT_TRUE((bool)runtime_); + CommonAPI::DBus::DBusRuntime* dbusRuntime = dynamic_cast(&(*runtime_)); + ASSERT_TRUE(dbusRuntime != NULL); + } + + virtual void TearDown() { + } + + std::shared_ptr runtime_; + + static const std::string serviceAddress_; +}; + +const std::string DBusCommunicationTest::serviceAddress_ = "local:commonapi.tests.TestInterface:commonapi.tests.TestInterface"; + + + +namespace myExtensions { + +template +class AttributeTestExtension: public CommonAPI::AttributeExtension<_AttributeType> { + typedef CommonAPI::AttributeExtension<_AttributeType> __baseClass_t; + +public: + typedef typename _AttributeType::ValueType ValueType; + typedef typename _AttributeType::AttributeAsyncCallback AttributeAsyncCallback; + + AttributeTestExtension(_AttributeType& baseAttribute) : + CommonAPI::AttributeExtension<_AttributeType>(baseAttribute) {} + + ~AttributeTestExtension() {} + + bool testExtensionMethod() const { + return true; + } +}; + +} // namespace myExtensions + +//#################################################################################################################### + + +TEST_F(DBusCommunicationTest, RemoteMethodCallSucceeds) { + std::shared_ptr proxyFactory = runtime_->createFactory(); + ASSERT_TRUE((bool)proxyFactory); + + auto defaultTestProxy = proxyFactory->buildProxy(serviceAddress_); + ASSERT_TRUE((bool)defaultTestProxy); + + std::shared_ptr stubFactory = runtime_->createFactory(); + ASSERT_TRUE((bool)stubFactory); + + auto stub = std::make_shared(); + bool success = stubFactory->registerService(stub, serviceAddress_); + ASSERT_TRUE(success); + + uint32_t v1 = 5; + std::string v2 = "Hai :)"; + CommonAPI::CallStatus stat; + defaultTestProxy->testVoidPredefinedTypeMethod(v1, v2, stat); + + ASSERT_EQ(stat, CommonAPI::CallStatus::SUCCESS); +} + + +int main(int argc, char** argv) { + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/CommonAPI-DBus/src/test/DBusConnectionTest.cpp b/CommonAPI-DBus/src/test/DBusConnectionTest.cpp new file mode 100644 index 0000000..5882e53 --- /dev/null +++ b/CommonAPI-DBus/src/test/DBusConnectionTest.cpp @@ -0,0 +1,196 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include +#include + +#include + +#include + + +#define ASSERT_DBUSMESSAGE_EQ(_dbusMessage1, _dbusMessage2) \ + ASSERT_FALSE(_dbusMessage1.getSignatureString() == NULL); \ + ASSERT_FALSE(_dbusMessage2.getSignatureString() == NULL); \ + ASSERT_STREQ(_dbusMessage1.getSignatureString(), _dbusMessage2.getSignatureString()); \ + ASSERT_EQ(_dbusMessage1.getBodyLength(), _dbusMessage2.getBodyLength()); \ + ASSERT_FALSE(_dbusMessage1.getBodyData() == NULL); \ + ASSERT_FALSE(_dbusMessage2.getBodyData() == NULL); \ + ASSERT_EQ(memcmp(_dbusMessage1.getBodyData(), _dbusMessage2.getBodyData(), _dbusMessage1.getBodyLength()), 0) + + +namespace { + +class DBusConnectionTest: public ::testing::Test { + public: + void onConnectionStatusEvent(const common::api::AvailabilityStatus& newConnectionStatus) { + connectionStatusEventCount_++; + connectionStatus_ = newConnectionStatus; + } + + bool onInterfaceHandlerDBusMessageReply(const common::api::dbus::DBusMessage& dbusMessage, + const std::shared_ptr& dbusConnection) { + interfaceHandlerDBusMessageCount_++; + interfaceHandlerDBusMessage_ = dbusMessage; + interfaceHandlerDBusMessageReply_ = dbusMessage.createMethodReturn("si"); + + common::api::dbus::DBusOutputMessageStream dbusOutputMessageStream(interfaceHandlerDBusMessageReply_); + dbusOutputMessageStream << "This is a default message reply!" << interfaceHandlerDBusMessageCount_; + dbusOutputMessageStream.flush(); + + dbusConnection->sendDBusMessage(interfaceHandlerDBusMessageReply_); + + return true; + } + + void onDBusMessageHandler(const common::api::dbus::DBusMessage& dbusMessage) { + dbusMessageHandlerCount_++; + dbusMessageHandlerDBusMessage_ = dbusMessage; + } + + protected: + virtual void SetUp() { + dbusConnection_ = common::api::dbus::DBusConnection::getSessionBus(); + connectionStatusEventCount_ = 0; + interfaceHandlerDBusMessageCount_ = 0; + dbusMessageHandlerCount_ = 0; + } + + virtual void TearDown() { + if (dbusConnection_ && dbusConnection_->isConnected()) + dbusConnection_->disconnect(); + + // reset DBusMessage + interfaceHandlerDBusMessage_ = common::api::dbus::DBusMessage(); + interfaceHandlerDBusMessageReply_ = common::api::dbus::DBusMessage(); + + dbusMessageHandlerDBusMessage_ = common::api::dbus::DBusMessage(); + } + + + std::shared_ptr dbusConnection_; + + uint32_t connectionStatusEventCount_; + common::api::AvailabilityStatus connectionStatus_; + + uint32_t interfaceHandlerDBusMessageCount_; + common::api::dbus::DBusMessage interfaceHandlerDBusMessage_; + common::api::dbus::DBusMessage interfaceHandlerDBusMessageReply_; + + uint32_t dbusMessageHandlerCount_; + common::api::dbus::DBusMessage dbusMessageHandlerDBusMessage_; +}; + + +TEST_F(DBusConnectionTest, IsInitiallyDisconnected) { + ASSERT_FALSE(dbusConnection_->isConnected()); +} + +TEST_F(DBusConnectionTest, ConnectAndDisconnectWork) { + ASSERT_TRUE(dbusConnection_->connect()); + ASSERT_TRUE(dbusConnection_->isConnected()); + + dbusConnection_->disconnect(); + ASSERT_FALSE(dbusConnection_->isConnected()); +} + +TEST_F(DBusConnectionTest, ConnectionStatusEventWorks) { + ASSERT_EQ(connectionStatusEventCount_, 0); + + auto connectionStatusSubscription = dbusConnection_->getConnectionStatusEvent().subscribe(std::bind( + &DBusConnectionTest::onConnectionStatusEvent, + this, + std::placeholders::_1)); + + ASSERT_FALSE(dbusConnection_->isConnected()); + ASSERT_EQ(connectionStatusEventCount_, 0); + + uint32_t expectedEventCount = 0; + while (expectedEventCount < 10) { + ASSERT_TRUE(dbusConnection_->connect()); + ASSERT_TRUE(dbusConnection_->isConnected()); + ASSERT_EQ(connectionStatusEventCount_, ++expectedEventCount); + ASSERT_EQ(connectionStatus_, common::api::AvailabilityStatus::AVAILABLE); + + dbusConnection_->disconnect(); + ASSERT_FALSE(dbusConnection_->isConnected()); + ASSERT_EQ(connectionStatusEventCount_, ++expectedEventCount); + ASSERT_EQ(connectionStatus_, common::api::AvailabilityStatus::NOT_AVAILABLE); + } + + dbusConnection_->getConnectionStatusEvent().unsubscribe(connectionStatusSubscription); + ASSERT_EQ(connectionStatusEventCount_, expectedEventCount); + + ASSERT_TRUE(dbusConnection_->connect()); + ASSERT_TRUE(dbusConnection_->isConnected()); + ASSERT_EQ(connectionStatusEventCount_, expectedEventCount); + + dbusConnection_->disconnect(); + ASSERT_FALSE(dbusConnection_->isConnected()); + ASSERT_EQ(connectionStatusEventCount_, expectedEventCount); +} + +TEST_F(DBusConnectionTest, SendingAsyncDBusMessagesWorks) { + const char* busName = "common.api.dbus.test.TestInterfaceHandler"; + const char* objectPath = "/common/api/dbus/test/TestObject"; + const char* interfaceName = "common.api.dbus.test.TestInterface"; + const char* methodName = "TestMethod"; + + auto interfaceHandlerDBusConnection = common::api::dbus::DBusConnection::getSessionBus(); + + ASSERT_TRUE(interfaceHandlerDBusConnection->connect()); + ASSERT_TRUE(interfaceHandlerDBusConnection->requestServiceNameAndBlock(busName)); + + auto interfaceHandlerToken = interfaceHandlerDBusConnection->registerInterfaceHandler( + objectPath, + interfaceName, + std::bind(&DBusConnectionTest::onInterfaceHandlerDBusMessageReply, + this, + std::placeholders::_1, + interfaceHandlerDBusConnection)); + + + ASSERT_TRUE(dbusConnection_->connect()); + + for (uint32_t expectedDBusMessageCount = 1; expectedDBusMessageCount <= 10; expectedDBusMessageCount++) { + auto dbusMessageCall = common::api::dbus::DBusMessage::createMethodCall( + busName, + objectPath, + interfaceName, + methodName, + "si"); + ASSERT_TRUE(dbusMessageCall); + + common::api::dbus::DBusOutputMessageStream dbusOutputMessageStream(dbusMessageCall); + dbusOutputMessageStream << "This is a test async call" + << expectedDBusMessageCount; + dbusOutputMessageStream.flush(); + + dbusConnection_->sendDBusMessageWithReplyAsync( + dbusMessageCall, + std::bind(&DBusConnectionTest::onDBusMessageHandler, this, std::placeholders::_1)); + + for (int i = 0; i < 10 && interfaceHandlerDBusMessageCount_ < expectedDBusMessageCount; i++) + interfaceHandlerDBusConnection->readWriteDispatch(100); + + ASSERT_EQ(interfaceHandlerDBusMessageCount_, expectedDBusMessageCount); + ASSERT_DBUSMESSAGE_EQ(dbusMessageCall, interfaceHandlerDBusMessage_); + + for (int i = 0; i < 10 && dbusMessageHandlerCount_ < expectedDBusMessageCount; i++) + dbusConnection_->readWriteDispatch(100); + + ASSERT_EQ(dbusMessageHandlerCount_, expectedDBusMessageCount); + ASSERT_DBUSMESSAGE_EQ(dbusMessageHandlerDBusMessage_, interfaceHandlerDBusMessageReply_); + } + + dbusConnection_->disconnect(); + + + interfaceHandlerDBusConnection->unregisterInterfaceHandler(interfaceHandlerToken); + + ASSERT_TRUE(interfaceHandlerDBusConnection->releaseServiceName(busName)); + interfaceHandlerDBusConnection->disconnect(); +} + +} // namespace diff --git a/CommonAPI-DBus/src/test/DBusDaemonProxyTest.cpp b/CommonAPI-DBus/src/test/DBusDaemonProxyTest.cpp new file mode 100644 index 0000000..c1db30e --- /dev/null +++ b/CommonAPI-DBus/src/test/DBusDaemonProxyTest.cpp @@ -0,0 +1,159 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include +#include + +#include + +#include +#include + +namespace { + +void dispatch(std::shared_ptr dbusConnection) { + while (dbusConnection->readWriteDispatch(10)) {} +} + +class DBusDaemonProxyTest: public ::testing::Test { + protected: + + std::thread* thread; + + virtual void SetUp() { + dbusConnection_ = CommonAPI::DBus::DBusConnection::getSessionBus(); + ASSERT_TRUE(dbusConnection_->connect()); + thread = new std::thread(dispatch, dbusConnection_); + thread->detach(); + //readWriteDispatchCount_ = 0; + } + + virtual void TearDown() { + delete thread; + if (dbusConnection_ && dbusConnection_->isConnected()) { + //dbusConnection_->disconnect(); + } + } + + /*bool doReadWriteDispatch(int timeoutMilliseconds = 100) { + readWriteDispatchCount_++; + return dbusConnection_->readWriteDispatch(timeoutMilliseconds); + }*/ + + std::shared_ptr dbusConnection_; + //size_t readWriteDispatchCount_; +}; + +TEST_F(DBusDaemonProxyTest, ListNames) { + std::vector busNames; + CommonAPI::CallStatus callStatus; + + dbusConnection_->getDBusDaemonProxy()->listNames(callStatus, busNames); + ASSERT_EQ(callStatus, CommonAPI::CallStatus::SUCCESS); + + ASSERT_GT(busNames.size(), 0); + for (const std::string& busName : busNames) { + ASSERT_FALSE(busName.empty()); + ASSERT_GT(busName.length(), 1); + } +} + +TEST_F(DBusDaemonProxyTest, ListNamesAsync) { + std::promise>> promise; + auto future = promise.get_future(); + + auto callStatusFuture = dbusConnection_->getDBusDaemonProxy()->listNamesAsync( + [&](const CommonAPI::CallStatus& callStatus, std::vector busNames) { + promise.set_value(std::tuple>(callStatus, std::move(busNames))); + }); + + ASSERT_EQ(future.wait_for(std::chrono::milliseconds(200)), std::future_status::ready); + + ASSERT_EQ(callStatusFuture.get(), CommonAPI::CallStatus::SUCCESS); + + auto futureResult = future.get(); + const CommonAPI::CallStatus& callStatus = std::get<0>(futureResult); + const std::vector& busNames = std::get<1>(futureResult); + + ASSERT_EQ(callStatus, CommonAPI::CallStatus::SUCCESS); + + ASSERT_GT(busNames.size(), 0); + for (const std::string& busName : busNames) { + ASSERT_FALSE(busName.empty()); + ASSERT_GT(busName.length(), 1); + } +} + +TEST_F(DBusDaemonProxyTest, NameHasOwner) { + bool nameHasOwner; + CommonAPI::CallStatus callStatus; + + dbusConnection_->getDBusDaemonProxy()->nameHasOwner("org.freedesktop.DBus", callStatus, nameHasOwner); + ASSERT_EQ(callStatus, CommonAPI::CallStatus::SUCCESS); + ASSERT_TRUE(nameHasOwner); + + dbusConnection_->getDBusDaemonProxy()->nameHasOwner("org.freedesktop.DBus.InvalidName.XXYYZZ", callStatus, nameHasOwner); + ASSERT_EQ(callStatus, CommonAPI::CallStatus::SUCCESS); + ASSERT_FALSE(nameHasOwner); +} + +TEST_F(DBusDaemonProxyTest, NameHasOwnerAsync) { + std::promise> promise; + auto future = promise.get_future(); + + auto callStatusFuture = dbusConnection_->getDBusDaemonProxy()->nameHasOwnerAsync( + "org.freedesktop.DBus", + [&](const CommonAPI::CallStatus& callStatus, bool nameHasOwner) { + promise.set_value(std::tuple(callStatus, std::move(nameHasOwner))); + }); + + //while (readWriteDispatchCount_ < 5) { + // ASSERT_TRUE(doReadWriteDispatch()); + //if (callStatusFuture.wait_for(std::chrono::milliseconds(100)) == std::future_status::ready) + // break; + //} + //ASSERT_NE(readWriteDispatchCount_, 5); + ASSERT_EQ(future.wait_for(std::chrono::milliseconds(100)), std::future_status::ready); + + ASSERT_EQ(callStatusFuture.get(), CommonAPI::CallStatus::SUCCESS); + + auto futureResult = future.get(); + const CommonAPI::CallStatus& callStatus = std::get<0>(futureResult); + const bool& nameHasOwner = std::get<1>(futureResult); + + ASSERT_EQ(callStatus, CommonAPI::CallStatus::SUCCESS); + ASSERT_TRUE(nameHasOwner); +} + +TEST_F(DBusDaemonProxyTest, NameOwnerChangedEvent) { + std::promise promise; + auto future = promise.get_future(); + + dbusConnection_->getDBusDaemonProxy()->getNameOwnerChangedEvent().subscribe( + [&](const std::string& name, const std::string& oldOwner, const std::string& newOwner) { + static bool promiseIsSet = false; + if(!promiseIsSet) { + promiseIsSet = true; + promise.set_value(!name.empty() && (!oldOwner.empty() || !newOwner.empty())); + } + }); + + // Trigger NameOwnerChanged using a new DBusConnection + ASSERT_TRUE(CommonAPI::DBus::DBusConnection::getSessionBus()->connect()); + + //while (readWriteDispatchCount_ < 5) { + // ASSERT_TRUE(doReadWriteDispatch()); + //if (future.wait_for(std::chrono::milliseconds(100)) == std::future_status::ready) + // break; + //} + + //ASSERT_NE(readWriteDispatchCount_, 5); + ASSERT_TRUE(future.get()); +} + +} // namespace + +int main(int argc, char** argv) { + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/CommonAPI-DBus/src/test/DBusFactoryTest.cpp b/CommonAPI-DBus/src/test/DBusFactoryTest.cpp new file mode 100644 index 0000000..af7d34b --- /dev/null +++ b/CommonAPI-DBus/src/test/DBusFactoryTest.cpp @@ -0,0 +1,141 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include "commonapi/tests/PredefinedTypeCollection.h" +#include "commonapi/tests/DerivedTypeCollection.h" +#include "commonapi/tests/TestInterfaceProxy.h" +#include "commonapi/tests/TestInterfaceStubDefault.h" +#include "commonapi/tests/TestInterfaceDBusStubAdapter.h" + +#include "commonapi/tests/TestInterfaceDBusProxy.h" + +std::shared_ptr runtime_; +std::shared_ptr proxyFactory; + +class DBusProxyFactoryTest: public ::testing::Test { + protected: + virtual void SetUp() { + if(!runtime_) { + runtime_ = CommonAPI::Runtime::load(); + + } + ASSERT_TRUE((bool)runtime_); + CommonAPI::DBus::DBusRuntime* dbusRuntime = dynamic_cast(&(*runtime_)); + ASSERT_TRUE(dbusRuntime != NULL); + } + + virtual void TearDown() { + } +}; + + + +namespace myExtensions { + +template +class AttributeTestExtension: public CommonAPI::AttributeExtension<_AttributeType> { + typedef CommonAPI::AttributeExtension<_AttributeType> __baseClass_t; + +public: + typedef typename _AttributeType::ValueType ValueType; + typedef typename _AttributeType::AttributeAsyncCallback AttributeAsyncCallback; + + AttributeTestExtension(_AttributeType& baseAttribute) : + CommonAPI::AttributeExtension<_AttributeType>(baseAttribute) {} + + ~AttributeTestExtension() {} + + bool testExtensionMethod() const { + return true; + } +}; + +} // namespace myExtensions + +//#################################################################################################################### + +TEST_F(DBusProxyFactoryTest, DBusFactoryCanBeCreated) { + proxyFactory = runtime_->createFactory(); + ASSERT_TRUE((bool)proxyFactory); + CommonAPI::DBus::DBusFactory* dbusProxyFactory = dynamic_cast(&(*proxyFactory)); + ASSERT_TRUE(dbusProxyFactory != NULL); +} + +TEST_F(DBusProxyFactoryTest, CreatesDefaultTestProxy) { + ASSERT_TRUE((bool)proxyFactory); + auto defaultTestProxy = proxyFactory->buildProxy("local:commonapi.tests.TestInterface:commonapi.tests.TestInterface"); + ASSERT_TRUE((bool)defaultTestProxy); +} + +TEST_F(DBusProxyFactoryTest, CreatesDefaultExtendedTestProxy) { + ASSERT_TRUE((bool)proxyFactory); + auto defaultTestProxy = proxyFactory->buildProxyWithDefaultAttributeExtension< + commonapi::tests::TestInterfaceProxy, + myExtensions::AttributeTestExtension>("local:commonapi.tests.TestInterface:commonapi.tests.TestInterface"); + ASSERT_TRUE((bool)defaultTestProxy); +} + +TEST_F(DBusProxyFactoryTest, CreatesIndividuallyExtendedTestProxy) { + ASSERT_TRUE((bool)proxyFactory); + auto specificAttributeExtendedTestProxy = proxyFactory->buildProxy< + commonapi::tests::TestInterfaceProxy, + commonapi::tests::TestInterfaceExtensions::TestDerivedArrayAttributeAttributeExtension > + ("local:commonapi.tests.TestInterface:commonapi.tests.TestInterface"); + + ASSERT_TRUE((bool)specificAttributeExtendedTestProxy); + + auto attributeExtension = specificAttributeExtendedTestProxy->getTestDerivedArrayAttributeAttributeExtension(); + ASSERT_TRUE(attributeExtension.testExtensionMethod()); +} + +TEST_F(DBusProxyFactoryTest, HandlesRegistrationOfStubAdapters) { + ASSERT_TRUE((bool)proxyFactory); + + const std::string serviceAddress = "local:commonapi.tests.TestInterface:commonapi.tests.TestInterface"; + + auto myStub = std::make_shared(); + bool success = proxyFactory->registerService(myStub, serviceAddress); + ASSERT_TRUE(success); + + success = proxyFactory->unregisterService("SomeOther:Unknown:Service"); + ASSERT_FALSE(success); + + success = proxyFactory->unregisterService(serviceAddress); + ASSERT_TRUE(success); +} + +TEST_F(DBusProxyFactoryTest, GracefullyHandlesWrongAddresses) { + ASSERT_TRUE((bool)proxyFactory); + auto myStub = std::make_shared(); + + ASSERT_FALSE(proxyFactory->registerService(myStub, "")); + ASSERT_FALSE(proxyFactory->registerService(myStub, "too:much:stuff:here")); +} + + +int main(int argc, char** argv) { + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/CommonAPI-DBus/src/test/DBusInputStreamTest.cpp b/CommonAPI-DBus/src/test/DBusInputStreamTest.cpp new file mode 100644 index 0000000..354c792 --- /dev/null +++ b/CommonAPI-DBus/src/test/DBusInputStreamTest.cpp @@ -0,0 +1,380 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include +#include +#include + +#include +#include + +#include + +#include + +#include +#include +#include +#include +#include + + +class InputStreamTest: public ::testing::Test { + protected: + DBusMessage* libdbusMessage; + DBusMessageIter libdbusMessageWriteIter; + size_t numOfElements; + + void SetUp() { + numOfElements = 2; + libdbusMessage = dbus_message_new_method_call("no.bus.here", "/no/object/here", NULL, "noMethodHere"); + ASSERT_TRUE(libdbusMessage != NULL); + dbus_message_iter_init_append(libdbusMessage, &libdbusMessageWriteIter); + } + + void TearDown() { + dbus_message_unref(libdbusMessage); + } +}; + +TEST_F(InputStreamTest, CanBeConstructed) { + CommonAPI::DBus::DBusMessage scopedMessage(libdbusMessage); + CommonAPI::DBus::DBusInputStream inStream(scopedMessage); +} + +TEST_F(InputStreamTest, ReadsEmptyMessages) { + CommonAPI::DBus::DBusMessage scopedMessage(libdbusMessage); + CommonAPI::DBus::DBusInputStream inStream(scopedMessage); + + EXPECT_EQ(0, scopedMessage.getBodyLength()); +} + +TEST_F(InputStreamTest, ReadsBytes) { + uint8_t val = 0xff; + for (int i = 0; i < numOfElements; i += 1) { + dbus_message_iter_append_basic(&libdbusMessageWriteIter, DBUS_TYPE_BYTE, &val); + } + + CommonAPI::DBus::DBusMessage scopedMessage(libdbusMessage); + CommonAPI::DBus::DBusInputStream inStream(scopedMessage); + + EXPECT_EQ(numOfElements, scopedMessage.getBodyLength()); + for (int i = 0; i < numOfElements; i += 1) { + uint8_t readVal; + inStream >> readVal; + EXPECT_EQ(val, readVal); + } +} + +TEST_F(InputStreamTest, ReadsBools) { + dbus_bool_t f = FALSE; + dbus_bool_t t = TRUE; + for (int i = 0; i < numOfElements; i += 2) { + dbus_message_iter_append_basic(&libdbusMessageWriteIter, DBUS_TYPE_BOOLEAN, &t); + dbus_message_iter_append_basic(&libdbusMessageWriteIter, DBUS_TYPE_BOOLEAN, &f); + } + + CommonAPI::DBus::DBusMessage scopedMessage(libdbusMessage); + CommonAPI::DBus::DBusInputStream inStream(scopedMessage); + + EXPECT_EQ(numOfElements*4, scopedMessage.getBodyLength()); + for (int i = 0; i < numOfElements; i += 2) { + bool readVal; + inStream >> readVal; + EXPECT_EQ(t, readVal); + inStream >> readVal; + EXPECT_EQ(f, readVal); + } +} + +TEST_F(InputStreamTest, ReadsUint16) { + + uint16_t val = 0xffff; + for (int i = 0; i < numOfElements; i += 1) { + dbus_message_iter_append_basic(&libdbusMessageWriteIter, DBUS_TYPE_UINT16, &val); + } + + CommonAPI::DBus::DBusMessage scopedMessage(libdbusMessage); + CommonAPI::DBus::DBusInputStream inStream(scopedMessage); + + EXPECT_EQ(numOfElements*2, scopedMessage.getBodyLength()); + for (int i = 0; i < numOfElements; i += 1) { + uint16_t readVal; + inStream >> readVal; + EXPECT_EQ(val, readVal); + } +} + +TEST_F(InputStreamTest, ReadsInt16) { + + int16_t val = 0x7fff; + for (int i = 0; i < numOfElements; i += 1) { + dbus_message_iter_append_basic(&libdbusMessageWriteIter, DBUS_TYPE_INT16, &val); + } + + CommonAPI::DBus::DBusMessage scopedMessage(libdbusMessage); + CommonAPI::DBus::DBusInputStream inStream(scopedMessage); + + EXPECT_EQ(numOfElements*2, scopedMessage.getBodyLength()); + for (int i = 0; i < numOfElements; i += 1) { + int16_t readVal; + inStream >> readVal; + EXPECT_EQ(val, readVal); + } +} + +TEST_F(InputStreamTest, ReadsUint32) { + + uint32_t val = 0xffffffff; + for (int i = 0; i < numOfElements; i += 1) { + dbus_message_iter_append_basic(&libdbusMessageWriteIter, DBUS_TYPE_UINT32, &val); + } + + CommonAPI::DBus::DBusMessage scopedMessage(libdbusMessage); + CommonAPI::DBus::DBusInputStream inStream(scopedMessage); + + EXPECT_EQ(numOfElements*4, scopedMessage.getBodyLength()); + for (int i = 0; i < numOfElements; i += 1) { + uint32_t readVal; + inStream >> readVal; + EXPECT_EQ(val, readVal); + } +} + +TEST_F(InputStreamTest, ReadsInt32) { + + int32_t val = 0x7fffffff; + for (int i = 0; i < numOfElements; i += 1) { + dbus_message_iter_append_basic(&libdbusMessageWriteIter, DBUS_TYPE_INT32, &val); + } + + CommonAPI::DBus::DBusMessage scopedMessage(libdbusMessage); + CommonAPI::DBus::DBusInputStream inStream(scopedMessage); + + EXPECT_EQ(numOfElements*4, scopedMessage.getBodyLength()); + for (int i = 0; i < numOfElements; i += 1) { + int32_t readVal; + inStream >> readVal; + EXPECT_EQ(val, readVal); + } +} + +TEST_F(InputStreamTest, ReadsUint64) { + + uint64_t val = 0xffffffffffffffff; + for (int i = 0; i < numOfElements; i += 1) { + dbus_message_iter_append_basic(&libdbusMessageWriteIter, DBUS_TYPE_UINT64, &val); + } + + CommonAPI::DBus::DBusMessage scopedMessage(libdbusMessage); + CommonAPI::DBus::DBusInputStream inStream(scopedMessage); + + EXPECT_EQ(numOfElements*8, scopedMessage.getBodyLength()); + for (int i = 0; i < numOfElements; i += 1) { + uint64_t readVal; + inStream >> readVal; + EXPECT_EQ(val, readVal); + } +} + +TEST_F(InputStreamTest, ReadsInt64) { + + int64_t val = 0x7fffffffffffffff; + for (int i = 0; i < numOfElements; i += 1) { + dbus_message_iter_append_basic(&libdbusMessageWriteIter, DBUS_TYPE_INT64, &val); + } + + CommonAPI::DBus::DBusMessage scopedMessage(libdbusMessage); + CommonAPI::DBus::DBusInputStream inStream(scopedMessage); + + EXPECT_EQ(numOfElements*8, scopedMessage.getBodyLength()); + for (int i = 0; i < numOfElements; i += 1) { + int64_t readVal; + inStream >> readVal; + EXPECT_EQ(val, readVal); + } +} + +TEST_F(InputStreamTest, ReadsDoubles) { + + double val = 13.37; + for (int i = 0; i < numOfElements; i += 1) { + dbus_message_iter_append_basic(&libdbusMessageWriteIter, DBUS_TYPE_DOUBLE, &val); + } + + CommonAPI::DBus::DBusMessage scopedMessage(libdbusMessage); + CommonAPI::DBus::DBusInputStream inStream(scopedMessage); + + EXPECT_EQ(numOfElements*8, scopedMessage.getBodyLength()); + for (int i = 0; i < numOfElements; i += 1) { + double readVal; + inStream >> readVal; + EXPECT_EQ(val, readVal); + } +} + +TEST_F(InputStreamTest, ReadsStrings) { + + std::string val = "hai"; + for (int i = 0; i < numOfElements; i += 1) { + dbus_message_iter_append_basic(&libdbusMessageWriteIter, DBUS_TYPE_STRING, &val); + } + + CommonAPI::DBus::DBusMessage scopedMessage(libdbusMessage); + CommonAPI::DBus::DBusInputStream inStream(scopedMessage); + + EXPECT_EQ(numOfElements*4 + numOfElements*4, scopedMessage.getBodyLength()); + for (int i = 0; i < numOfElements; i += 1) { + std::string readVal; + inStream >> readVal; + EXPECT_EQ(val, readVal); + } +} + +namespace bmw { +namespace test { + +struct TestSerializableStruct: CommonAPI::SerializableStruct { + uint32_t a; + int16_t b; + bool c; + std::string d; + double e; + + virtual void readFromInputStream(CommonAPI::InputStream& inputStream) { + inputStream >> a >> b >> c >> d >> e; + } + + virtual void writeToOutputStream(CommonAPI::OutputStream& outputStream) const { + outputStream << a << b << c << d << e; + } +}; + +} //namespace test +} //namespace bmw + +TEST_F(InputStreamTest, ReadsStructs) { + + bmw::test::TestSerializableStruct testStruct; + testStruct.a = 15; + testStruct.b = -32; + testStruct.c = FALSE; + testStruct.d = "Hello all"; + testStruct.e = 3.414; + + DBusMessageIter subIter; + dbus_message_iter_open_container(&libdbusMessageWriteIter, DBUS_TYPE_STRUCT, NULL, &subIter); + dbus_message_iter_append_basic(&subIter, DBUS_TYPE_UINT32, &testStruct.a); + dbus_message_iter_append_basic(&subIter, DBUS_TYPE_INT16, &testStruct.b); + dbus_bool_t dbusBool = static_cast(testStruct.c); + dbus_message_iter_append_basic(&subIter, DBUS_TYPE_BOOLEAN, &dbusBool); + dbus_message_iter_append_basic(&subIter, DBUS_TYPE_STRING, &testStruct.d); + dbus_message_iter_append_basic(&subIter, DBUS_TYPE_DOUBLE, &testStruct.e); + dbus_message_iter_close_container(&libdbusMessageWriteIter, &subIter); + + CommonAPI::DBus::DBusMessage scopedMessage(libdbusMessage); + CommonAPI::DBus::DBusInputStream inStream(scopedMessage); + + //40(byte length of struct) = 4(uint32_t) + 2(int16_t) + 2(padding) + 4(bool) + 4(strlength) + // + 9(string) + 1(terminating '\0' of string) + 6(padding) + 8 (double) + EXPECT_EQ(40, scopedMessage.getBodyLength()); + + bmw::test::TestSerializableStruct verifyStruct; + inStream >> verifyStruct; + EXPECT_EQ(testStruct.a, verifyStruct.a); + EXPECT_EQ(testStruct.b, verifyStruct.b); + EXPECT_EQ(testStruct.c, verifyStruct.c); + EXPECT_EQ(testStruct.d, verifyStruct.d); + EXPECT_EQ(testStruct.e, verifyStruct.e); +} + +TEST_F(InputStreamTest, ReadsArrays) { + + std::vector testVector; + int32_t val1 = 0xffffffff; + int32_t val2 = 0x7fffffff; + for (int i = 0; i < numOfElements; i += 2) { + testVector.push_back(val1); + testVector.push_back(val2); + } + + DBusMessageIter subIter; + dbus_message_iter_open_container(&libdbusMessageWriteIter, DBUS_TYPE_ARRAY, "i", &subIter); + for (int i = 0; i < numOfElements; i++) { + dbus_message_iter_append_basic(&subIter, DBUS_TYPE_INT32, &testVector[i]); + } + dbus_message_iter_close_container(&libdbusMessageWriteIter, &subIter); + + CommonAPI::DBus::DBusMessage scopedMessage(libdbusMessage); + CommonAPI::DBus::DBusInputStream inStream(scopedMessage); + + EXPECT_EQ(scopedMessage.getBodyLength(), numOfElements*4 + 4); + std::vector verifyVector; + inStream >> verifyVector; + int32_t res1; + int32_t res2; + for (int i = 0; i < numOfElements; i += 2) { + res1 = verifyVector[i]; + EXPECT_EQ(val1, res1); + res2 = verifyVector[i + 1]; + EXPECT_EQ(val2, res2); + } +} + +TEST_F(InputStreamTest, ReadsArraysInArrays) { + size_t numOfElements = 2; + DBusMessage* dbusMessage = dbus_message_new_method_call("no.bus.here", "/no/object/here", NULL, "noMethodHere"); + ASSERT_TRUE(dbusMessage != NULL); + + DBusMessageIter writeIter; + dbus_message_iter_init_append(dbusMessage, &writeIter); + + std::vector> testVector; + int32_t val1 = 0xffffffff; + int32_t val2 = 0x7fffffff; + for (int i = 0; i < numOfElements; i++) { + std::vector inner; + for (int j = 0; j < numOfElements; j += 2) { + inner.push_back(val1); + inner.push_back(val2); + } + testVector.push_back(inner); + } + + DBusMessageIter subIter; + dbus_message_iter_open_container(&writeIter, DBUS_TYPE_ARRAY, "ai", &subIter); + for (int i = 0; i < numOfElements; i++) { + DBusMessageIter subsubIter; + dbus_message_iter_open_container(&subIter, DBUS_TYPE_ARRAY, "i", &subsubIter); + for (int j = 0; j < numOfElements; j++) { + dbus_message_iter_append_basic(&subsubIter, DBUS_TYPE_INT32, &(testVector[i][j])); + } + dbus_message_iter_close_container(&subIter, &subsubIter); + } + dbus_message_iter_close_container(&writeIter, &subIter); + + CommonAPI::DBus::DBusMessage scopedMessage(dbusMessage); + CommonAPI::DBus::DBusInputStream inStream(scopedMessage); + + // 5*5*int32_t + 5*lengthField_inner(int32_t) + lengthField_outer(int32_t) + EXPECT_EQ(numOfElements*numOfElements*4 + numOfElements*4 + 4, scopedMessage.getBodyLength()); + std::vector> verifyVector; + inStream >> verifyVector; + + int32_t res1; + int32_t res2; + for (int i = 0; i < numOfElements; i++) { + std::vector innerVerify = verifyVector[i]; + for (int j = 0; j < numOfElements; j += 2) { + res1 = innerVerify[j]; + EXPECT_EQ(val1, res1); + res2 = innerVerify[j + 1]; + EXPECT_EQ(val2, res2); + } + } +} + +int main(int argc, char** argv) { + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/CommonAPI-DBus/src/test/DBusMultipleConnectionTest.cpp b/CommonAPI-DBus/src/test/DBusMultipleConnectionTest.cpp new file mode 100644 index 0000000..910547a --- /dev/null +++ b/CommonAPI-DBus/src/test/DBusMultipleConnectionTest.cpp @@ -0,0 +1,125 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "commonapi/tests/TestInterfaceProxy.h" +#include "commonapi/tests/TestInterfaceStubDefault.h" +const std::string serviceAddress = "local:commonapi.tests.TestInterface:commonapi.tests.TestInterface"; + +class DBusMultipleConnectionTest: public ::testing::Test { + protected: + virtual void SetUp() { + proxyFactory = CommonAPI::Runtime::load()->createFactory(); + stubFactory = CommonAPI::Runtime::load()->createFactory(); + ASSERT_TRUE((bool)proxyFactory); + ASSERT_TRUE((bool)stubFactory); + + stub = std::make_shared(); + bool success = stubFactory->registerService(stub, serviceAddress); + ASSERT_TRUE(success); + + proxy = proxyFactory->buildProxy(serviceAddress); + ASSERT_TRUE((bool)proxy); + } + + virtual void TearDown() { + } + + std::shared_ptr proxyFactory; + std::shared_ptr stubFactory; + std::shared_ptr stub; + std::shared_ptr > proxy; + +}; + + +TEST_F(DBusMultipleConnectionTest, SetAttribute) { + uint32_t v1 = 5; + uint32_t v2; + CommonAPI::CallStatus stat; + proxy->getTestPredefinedTypeAttributeAttribute().setValue(v1, stat, v2); + ASSERT_EQ(stat, CommonAPI::CallStatus::SUCCESS); + ASSERT_EQ(v1, v2); +} + +TEST_F(DBusMultipleConnectionTest, SetAttributeBroadcast) { + uint32_t v1 = 6; + uint32_t v2; + uint32_t v3 = 0; + + std::promise promise; + auto future = promise.get_future(); + + proxy->getTestPredefinedTypeAttributeAttribute().getChangedEvent().subscribe([&]( + const uint32_t intVal) { + v3 = intVal; + promise.set_value(true); + }); + + CommonAPI::CallStatus stat; + proxy->getTestPredefinedTypeAttributeAttribute().setValue(v1, stat, v2); + ASSERT_EQ(stat, CommonAPI::CallStatus::SUCCESS); + ASSERT_EQ(v1, v2); + + ASSERT_TRUE(future.get()); + ASSERT_EQ(v1, v3); + +} + + +TEST_F(DBusMultipleConnectionTest, GetAttribute) { + uint32_t v1; + CommonAPI::CallStatus stat = proxy->getTestPredefinedTypeAttributeAttribute().getValue(v1); + ASSERT_EQ(stat, CommonAPI::CallStatus::SUCCESS); +} + +TEST_F(DBusMultipleConnectionTest, RemoteMethodCall) { + uint32_t v1 = 5; + std::string v2 = "Hai :)"; + CommonAPI::CallStatus stat; + proxy->testVoidPredefinedTypeMethod(v1, v2, stat); + ASSERT_EQ(stat, CommonAPI::CallStatus::SUCCESS); +} + +TEST_F(DBusMultipleConnectionTest, Broadcast) { + uint32_t v1 = 5; + uint32_t v3 = 0; + std::string v2 = "Hai :)"; + + std::promise promise; + auto future = promise.get_future(); + + proxy->getTestPredefinedTypeBroadcastEvent().subscribe([&]( + const uint32_t intVal, const std::string& strVal) { + v3 = intVal; + promise.set_value(true); + }); + + stub->firePredefinedBroadcast(v1, v2); + + ASSERT_TRUE(future.get()); + ASSERT_EQ(v1, v3); +} + + +int main(int argc, char** argv) { + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} + diff --git a/CommonAPI-DBus/src/test/DBusNameCacheTest.cpp b/CommonAPI-DBus/src/test/DBusNameCacheTest.cpp new file mode 100644 index 0000000..91061bc --- /dev/null +++ b/CommonAPI-DBus/src/test/DBusNameCacheTest.cpp @@ -0,0 +1,28 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include +#include + + + +int main(void) { + auto dbusConnection = common::api::dbus::DBusConnection::getSessionBus(); + + dbusConnection->connect(); + + common::api::dbus::DBusNameCache dbusNameCache(dbusConnection); + + dbusConnection->requestServiceNameAndBlock("common.api.dbus.test.DBusNameCache"); + + for (int i = 0; i < 5; i++) + dbusConnection->readWriteDispatch(100); + + dbusConnection->releaseServiceName("common.api.dbus.test.DBusNameCache"); + + for (int i = 0; i < 5; i++) + dbusConnection->readWriteDispatch(100); + + return 0; +} diff --git a/CommonAPI-DBus/src/test/DBusOutputStreamTest.cpp b/CommonAPI-DBus/src/test/DBusOutputStreamTest.cpp new file mode 100644 index 0000000..184b852 --- /dev/null +++ b/CommonAPI-DBus/src/test/DBusOutputStreamTest.cpp @@ -0,0 +1,706 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include +#include + +#include +#include +#include +#include + + +class OutputStreamTest: public ::testing::Test { +protected: + size_t numOfElements; + CommonAPI::DBus::DBusMessage message; + const char* busName; + const char* objectPath; + const char* interfaceName; + const char* methodName; + + void SetUp() { + numOfElements = 10; + busName = "no.bus.here"; + objectPath = "/no/object/here"; + interfaceName = "no.interface.here"; + methodName = "noMethodHere"; + } + + void TearDown() { + } +}; + +TEST_F(OutputStreamTest, CanBeConstructed) { + CommonAPI::DBus::DBusOutputStream outStream(message); +} + +TEST_F(OutputStreamTest, WritesBytes) { + const char* signature = "yyyyyyyyyy"; + message = CommonAPI::DBus::DBusMessage::createMethodCall(busName, objectPath, interfaceName, methodName, signature); + CommonAPI::DBus::DBusOutputStream outStream(message); + + outStream.reserveMemory(numOfElements); + uint8_t val1 = 0xff; + uint8_t val2 = 0x00; + for (int i = 0; i < numOfElements; i += 2) { + outStream << val1; + outStream << val2; + } + outStream.flush(); + + EXPECT_EQ(numOfElements, message.getBodyLength()); + + CommonAPI::DBus::DBusInputStream inStream(message); + + uint8_t verifyVal1; + uint8_t verifyVal2; + for (int i = 0; i < numOfElements; i += 2) { + inStream >> verifyVal1; + EXPECT_EQ(val1, verifyVal1); + + inStream >> verifyVal2; + EXPECT_EQ(val2, verifyVal2); + } +} + +TEST_F(OutputStreamTest, WritesBools) { + const char* signature = "bbbbbbbbbb"; + message = CommonAPI::DBus::DBusMessage::createMethodCall(busName, objectPath, interfaceName, methodName, signature); + CommonAPI::DBus::DBusOutputStream outStream(message); + + outStream.reserveMemory(numOfElements * 4); + bool val1 = TRUE; + bool val2 = FALSE; + for (int i = 0; i < numOfElements; i += 2) { + outStream << val1; + outStream << val2; + } + outStream.flush(); + + EXPECT_EQ(numOfElements*4, message.getBodyLength()); + + CommonAPI::DBus::DBusInputStream inStream(message); + + bool verifyVal1; + bool verifyVal2; + for (int i = 0; i < numOfElements; i += 2) { + inStream >> verifyVal1; + EXPECT_EQ(val1, verifyVal1); + + inStream >> verifyVal2; + EXPECT_EQ(val2, verifyVal2); + } +} + +TEST_F(OutputStreamTest, WritesUInt16) { + const char* signature = "qqqqqqqqqq"; + message = CommonAPI::DBus::DBusMessage::createMethodCall(busName, objectPath, interfaceName, methodName, signature); + CommonAPI::DBus::DBusOutputStream outStream(message); + + outStream.reserveMemory(numOfElements * 2); + uint16_t val1 = 0x0000; + uint16_t val2 = 0xffff; + for (int i = 0; i < numOfElements; i += 2) { + outStream << val1; + outStream << val2; + } + outStream.flush(); + + EXPECT_EQ(numOfElements*2, message.getBodyLength()); + + CommonAPI::DBus::DBusInputStream inStream(message); + + uint16_t verifyVal1; + uint16_t verifyVal2; + for (int i = 0; i < numOfElements; i += 2) { + inStream >> verifyVal1; + EXPECT_EQ(val1, verifyVal1); + + inStream >> verifyVal2; + EXPECT_EQ(val2, verifyVal2); + } +} + +TEST_F(OutputStreamTest, WritesInt16) { + const char* signature = "nnnnnnnnnn"; + message = CommonAPI::DBus::DBusMessage::createMethodCall(busName, objectPath, interfaceName, methodName, signature); + CommonAPI::DBus::DBusOutputStream outStream(message); + + outStream.reserveMemory(numOfElements * 2); + int16_t val1 = 0x7fff; + int16_t val2 = 0xffff; + for (int i = 0; i < numOfElements; i += 2) { + outStream << val1; + outStream << val2; + } + outStream.flush(); + + EXPECT_EQ(numOfElements*2, message.getBodyLength()); + + CommonAPI::DBus::DBusInputStream inStream(message); + + int16_t verifyVal1; + int16_t verifyVal2; + for (int i = 0; i < numOfElements; i += 2) { + inStream >> verifyVal1; + EXPECT_EQ(val1, verifyVal1); + + inStream >> verifyVal2; + EXPECT_EQ(val2, verifyVal2); + } +} + +TEST_F(OutputStreamTest, WritesUInt32) { + const char* signature = "uuuuuuuuuu"; + message = CommonAPI::DBus::DBusMessage::createMethodCall(busName, objectPath, interfaceName, methodName, signature); + CommonAPI::DBus::DBusOutputStream outStream(message); + + outStream.reserveMemory(numOfElements * 4); + uint32_t val1 = 0x00000000; + uint32_t val2 = 0xffffffff; + for (int i = 0; i < numOfElements; i += 2) { + outStream << val1; + outStream << val2; + } + outStream.flush(); + + EXPECT_EQ(numOfElements*4, message.getBodyLength()); + + CommonAPI::DBus::DBusInputStream inStream(message); + + uint32_t verifyVal1; + uint32_t verifyVal2; + for (int i = 0; i < numOfElements; i += 2) { + inStream >> verifyVal1; + EXPECT_EQ(val1, verifyVal1); + + inStream >> verifyVal2; + EXPECT_EQ(val2, verifyVal2); + } +} + +TEST_F(OutputStreamTest, WritesInt32) { + const char* signature = "iiiiiiiiii"; + message = CommonAPI::DBus::DBusMessage::createMethodCall(busName, objectPath, interfaceName, methodName, signature); + CommonAPI::DBus::DBusOutputStream outStream(message); + + outStream.reserveMemory(numOfElements * 4); + int32_t val1 = 0x7fffffff; + int32_t val2 = 0xffffffff; + for (int i = 0; i < numOfElements; i += 2) { + outStream << val1; + outStream << val2; + } + outStream.flush(); + + EXPECT_EQ(numOfElements*4, message.getBodyLength()); + + CommonAPI::DBus::DBusInputStream inStream(message); + + int32_t verifyVal1; + int32_t verifyVal2; + for (int i = 0; i < numOfElements; i += 2) { + inStream >> verifyVal1; + EXPECT_EQ(val1, verifyVal1); + + inStream >> verifyVal2; + EXPECT_EQ(val2, verifyVal2); + } +} + +TEST_F(OutputStreamTest, WritesUInt64) { + const char* signature = "tttttttttt"; + message = CommonAPI::DBus::DBusMessage::createMethodCall(busName, objectPath, interfaceName, methodName, signature); + CommonAPI::DBus::DBusOutputStream outStream(message); + + outStream.reserveMemory(numOfElements * 8); + uint64_t val1 = 0x0000000000000000; + uint64_t val2 = 0xffffffffffffffff; + for (int i = 0; i < numOfElements; i += 2) { + outStream << val1; + outStream << val2; + } + outStream.flush(); + + EXPECT_EQ(numOfElements*8, message.getBodyLength()); + + CommonAPI::DBus::DBusInputStream inStream(message); + + uint64_t verifyVal1; + uint64_t verifyVal2; + for (int i = 0; i < numOfElements; i += 2) { + inStream >> verifyVal1; + EXPECT_EQ(val1, verifyVal1); + + inStream >> verifyVal2; + EXPECT_EQ(val2, verifyVal2); + } +} + +TEST_F(OutputStreamTest, WritesInt64) { + const char* signature = "xxxxxxxxxx"; + message = CommonAPI::DBus::DBusMessage::createMethodCall(busName, objectPath, interfaceName, methodName, signature); + CommonAPI::DBus::DBusOutputStream outStream(message); + + outStream.reserveMemory(numOfElements * 8); + int64_t val1 = 0x7fffffffffffffff; + int64_t val2 = 0xffffffffffffffff; + for (int i = 0; i < numOfElements; i += 2) { + outStream << val1; + outStream << val2; + } + outStream.flush(); + + EXPECT_EQ(numOfElements*8, message.getBodyLength()); + + CommonAPI::DBus::DBusInputStream inStream(message); + + int64_t verifyVal1; + int64_t verifyVal2; + for (int i = 0; i < numOfElements; i += 2) { + inStream >> verifyVal1; + EXPECT_EQ(val1, verifyVal1); + + inStream >> verifyVal2; + EXPECT_EQ(val2, verifyVal2); + } +} + +TEST_F(OutputStreamTest, WritesDouble) { + const char* signature = "dddddddddd"; + message = CommonAPI::DBus::DBusMessage::createMethodCall(busName, objectPath, interfaceName, methodName, signature); + CommonAPI::DBus::DBusOutputStream outStream(message); + + outStream.reserveMemory(numOfElements * 8); + double val1 = 13.37; + double val2 = 3.414; + for (int i = 0; i < numOfElements; i += 2) { + outStream << val1; + outStream << val2; + } + outStream.flush(); + + EXPECT_EQ(numOfElements*8, message.getBodyLength()); + + CommonAPI::DBus::DBusInputStream inStream(message); + + double verifyVal1; + double verifyVal2; + std::string verifySignature; + for (int i = 0; i < numOfElements; i += 2) { + inStream >> verifyVal1; + EXPECT_EQ(val1, verifyVal1); + + inStream >> verifyVal2; + EXPECT_EQ(val2, verifyVal2); + } +} + +TEST_F(OutputStreamTest, WritesStrings) { + const char* signature = "sss"; + message = CommonAPI::DBus::DBusMessage::createMethodCall(busName, objectPath, interfaceName, methodName, signature); + CommonAPI::DBus::DBusOutputStream outStream(message); + + std::string val1 = "hai"; + std::string val2 = "ciao"; + std::string val3 = "salut"; + + //sizes of the strings + terminating null-bytes (each 1 byte) + length-fields (each 4 bytes) + outStream.reserveMemory(val1.size() + val2.size() + val3.size() + 3 + 3 * 4); + outStream << val1 << val2 << val3; + outStream.flush(); + + //Length fields + actual strings + terminating '\0's + 3(padding) + EXPECT_EQ(3*4 + 3 + 4 + 5 + 3 + 3, message.getBodyLength()); + + CommonAPI::DBus::DBusInputStream inStream(message); + + std::string verifyVal1; + std::string verifyVal2; + std::string verifyVal3; + std::string verifySignature; + + inStream >> verifyVal1; + inStream >> verifyVal2; + inStream >> verifyVal3; + + EXPECT_EQ(val1, verifyVal1); + EXPECT_EQ(val2, verifyVal2); + EXPECT_EQ(val3, verifyVal3); +} + +namespace bmw { +namespace test { + +struct myStruct: CommonAPI::SerializableStruct { + ~myStruct(); + + uint32_t a; + int16_t b; + bool c; + std::string d; + double e; + + virtual void readFromInputStream(CommonAPI::InputStream& inputMessageStream); + virtual void writeToOutputStream(CommonAPI::OutputStream& outputMessageStream) const; +}; + +myStruct::~myStruct() { +} + +void myStruct::readFromInputStream(CommonAPI::InputStream& inputMessageStream) { + inputMessageStream >> a >> b >> c >> d >> e; +} + +void myStruct::writeToOutputStream(CommonAPI::OutputStream& outputMessageStream) const { + outputMessageStream << a << b << c << d << e; +} + +} //namespace test +} //namespace bmw + +TEST_F(OutputStreamTest, WritesStructs) { + const char* signature = "(unbsd)"; + message = CommonAPI::DBus::DBusMessage::createMethodCall(busName, objectPath, interfaceName, methodName, signature); + CommonAPI::DBus::DBusOutputStream outStream(message); + + bmw::test::myStruct testStruct; + testStruct.a = 15; + testStruct.b = -32; + testStruct.c = FALSE; + testStruct.d = "Hello all"; + testStruct.e = 3.414; + + // 40(byte length of struct) = 4(uint32_t) + 2(int16_t) + 2(padding) + 4(bool) + 4(strlength) + // + 9(string) + 1(terminating '\0' of string) + 6(padding) + 8 (double) + outStream.reserveMemory(40); + outStream << testStruct; + outStream.flush(); + + EXPECT_EQ(40, message.getBodyLength()); + + CommonAPI::DBus::DBusInputStream inStream(message); + bmw::test::myStruct verifyStruct; + inStream >> verifyStruct; + + EXPECT_EQ(testStruct.a, verifyStruct.a); + EXPECT_EQ(testStruct.b, verifyStruct.b); + EXPECT_EQ(testStruct.c, verifyStruct.c); + EXPECT_EQ(testStruct.d, verifyStruct.d); + EXPECT_EQ(testStruct.e, verifyStruct.e); +} + +TEST_F(OutputStreamTest, WritesArrays) { + const char* signature = "ai"; + message = CommonAPI::DBus::DBusMessage::createMethodCall(busName, objectPath, interfaceName, methodName, signature); + CommonAPI::DBus::DBusOutputStream outStream(message); + + std::vector testVector; + int32_t val1 = 0xffffffff; + int32_t val2 = 0x7fffffff; + for (int i = 0; i < numOfElements; i += 2) { + testVector.push_back(val1); + testVector.push_back(val2); + } + + outStream.reserveMemory(numOfElements * 4 + 4); + outStream << testVector; + outStream.flush(); + + EXPECT_EQ(numOfElements*4 + 4, message.getBodyLength()); + + CommonAPI::DBus::DBusInputStream inStream(message); + std::vector verifyVector; + inStream >> verifyVector; + + int32_t res1; + int32_t res2; + for (int i = 0; i < numOfElements; i += 2) { + res1 = verifyVector[i]; + EXPECT_EQ(val1, res1); + res2 = verifyVector[i + 1]; + EXPECT_EQ(val2, res2); + } +} + +TEST_F(OutputStreamTest, WritesArraysOfStrings) { + const char* signature = "as"; + message = CommonAPI::DBus::DBusMessage::createMethodCall(busName, objectPath, interfaceName, methodName, signature); + CommonAPI::DBus::DBusOutputStream outStream(message); + + std::vector testVector; + std::string val1 = "Hai"; + std::string val2 = "Ciao"; + for (int i = 0; i < numOfElements; i += 2) { + testVector.push_back(val1); + testVector.push_back(val2); + } + + // 101 = 4(lengthFieldOfArray) + + // 4*(4(lengthField1) + 4(string1 mit \0-byte) + 4(lengthField2) + 5(string2 mit \0-byte) + 3(paddingTo4)) + + // (4(lengthField1) + 4(string1 mit \0-byte) + 4(lengthField2) + 5(string2 mit \0-byte)) + size_t vectorLength = 101; + outStream.reserveMemory(vectorLength); + outStream << testVector; + outStream.flush(); + + EXPECT_EQ(vectorLength, message.getBodyLength()); + + CommonAPI::DBus::DBusInputStream inStream(message); + std::vector verifyVector; + inStream >> verifyVector; + + std::string res1; + std::string res2; + for (int i = 0; i < numOfElements; i += 2) { + res1 = verifyVector[i]; + EXPECT_EQ(val1, res1); + res2 = verifyVector[i + 1]; + EXPECT_EQ(val2, res2); + } +} + +TEST_F(OutputStreamTest, WritesArraysInArrays) { + const char* signature = "aai"; + message = CommonAPI::DBus::DBusMessage::createMethodCall(busName, objectPath, interfaceName, methodName, signature); + CommonAPI::DBus::DBusOutputStream outStream(message); + + std::vector> testVector; + int32_t val1 = 0xffffffff; + int32_t val2 = 0x7fffffff; + for (int i = 0; i < numOfElements; i++) { + std::vector inner; + for (int j = 0; j < numOfElements; j += 2) { + inner.push_back(val1); + inner.push_back(val2); + } + testVector.push_back(inner); + } + + outStream.reserveMemory(numOfElements * numOfElements * 4 + numOfElements * 4 + 4); + outStream << testVector; + outStream.flush(); + + EXPECT_EQ(numOfElements*numOfElements*4 + numOfElements*4 + 4, message.getBodyLength()); + + CommonAPI::DBus::DBusInputStream inStream(message); + std::vector> verifyVector; + inStream >> verifyVector; + + int32_t res1; + int32_t res2; + for (int i = 0; i < numOfElements; i++) { + std::vector innerVerify = verifyVector[i]; + for (int j = 0; j < numOfElements; j += 2) { + res1 = innerVerify[j]; + EXPECT_EQ(val1, res1); + res2 = innerVerify[j + 1]; + EXPECT_EQ(val2, res2); + } + } +} + +namespace com { +namespace bmw { +namespace test { + +struct TestStruct: CommonAPI::SerializableStruct { + TestStruct(); + TestStruct(int32_t v1, double v2, double v3, std::string v4); + ~TestStruct(); + + int32_t val1; + double val2; + double val3; + std::string val4; + + virtual void readFromInputStream(CommonAPI::InputStream& inputMessageStream); + virtual void writeToOutputStream(CommonAPI::OutputStream& outputMessageStream) const; +}; + +typedef std::vector TestStructList; + +TestStruct::TestStruct() : + val1(0), val2(0), val3(0), val4("") { +} + +TestStruct::TestStruct(int32_t v1, double v2, double v3, std::string v4) : + val1(v1), val2(v2), val3(v3), val4(v4) { +} + +TestStruct::~TestStruct() { +} + +void TestStruct::readFromInputStream(CommonAPI::InputStream& inputMessageStream) { + inputMessageStream >> val1 >> val2 >> val3 >> val4; +} + +void TestStruct::writeToOutputStream(CommonAPI::OutputStream& outputMessageStream) const { + outputMessageStream << val1 << val2 << val3 << val4; +} + +} // namespace test +} // namespace bmw +} // namespace com + + +TEST_F(OutputStreamTest, WritesTestStructs) { + const char* signature = "(idds)"; + message = CommonAPI::DBus::DBusMessage::createMethodCall(busName, objectPath, interfaceName, methodName, signature); + CommonAPI::DBus::DBusOutputStream outStream(message); + + com::bmw::test::TestStruct testStruct(1, 12.6, 1e40, "XXXXXXXXXXXXXXXXXXXX"); + + //4(int32_t) + 4(padding) + 8(double) + 8(double) + 4(str_length) + 20(string) + 1(null-termination) + uint32_t expectedSize = 49; + outStream.reserveMemory(expectedSize); + outStream << testStruct; + outStream.flush(); + + EXPECT_EQ(expectedSize, message.getBodyLength()); + + CommonAPI::DBus::DBusInputStream inStream(message); + com::bmw::test::TestStruct verifyStruct; + inStream >> verifyStruct; + + EXPECT_EQ(testStruct.val1, verifyStruct.val1); + EXPECT_EQ(testStruct.val2, verifyStruct.val2); + EXPECT_EQ(testStruct.val3, verifyStruct.val3); + EXPECT_EQ(testStruct.val4, verifyStruct.val4); +} + +TEST_F(OutputStreamTest, WritesTestStructLists) { + const char* signature = "a(idds)"; + message = CommonAPI::DBus::DBusMessage::createMethodCall(busName, objectPath, interfaceName, methodName, signature); + CommonAPI::DBus::DBusOutputStream outStream(message); + + com::bmw::test::TestStructList testList; + for (int i = 0; i < numOfElements; i++) { + testList.emplace_back(1, 12.6, 1e40, "XXXXXXXXXXXXXXXXXXXX"); + } + + //struct size: 49 = 4(int32_t) + 4(padding) + 8(double) + 8(double) + 4(str_length) + 20(string) + 1(null-termination) + //array size: 4(array_length) + 4(struct_padding) + (numElements-1)*(49(struct) + 7(struct_padding)) + 49(struct) + uint32_t expectedSize = 8 + (numOfElements - 1) * (49 + 7) + 49; + outStream.reserveMemory(expectedSize); + outStream << testList; + outStream.flush(); + + EXPECT_EQ(expectedSize, message.getBodyLength()); + + CommonAPI::DBus::DBusInputStream inStream(message); + com::bmw::test::TestStructList verifyList; + inStream >> verifyList; + + EXPECT_EQ(numOfElements, verifyList.size()); +} + + + +namespace com { +namespace bmw { +namespace test { + +struct ArrayStruct: CommonAPI::SerializableStruct { + ArrayStruct(); + ArrayStruct(std::vector v1, std::vector v2, std::vector v3, std::vector v4, std::vector v5); + ~ArrayStruct(); + + std::vector val1; + std::vector val2; + std::vector val3; + std::vector val4; + std::vector val5; + + virtual void readFromInputStream(CommonAPI::InputStream& inputMessageStream); + virtual void writeToOutputStream(CommonAPI::OutputStream& outputMessageStream) const; +}; + +typedef std::vector TestStructList; + +ArrayStruct::ArrayStruct() { +} + +ArrayStruct::ArrayStruct(std::vector v1, std::vector v2, std::vector v3, std::vector v4, std::vector v5) : + val1(v1), val2(v2), val3(v3), val4(v4), val5(v5) { +} + +ArrayStruct::~ArrayStruct() { +} + +void ArrayStruct::readFromInputStream(CommonAPI::InputStream& inputMessageStream) { + inputMessageStream >> val1 >> val2 >> val3 >> val4 >> val5; +} + +void ArrayStruct::writeToOutputStream(CommonAPI::OutputStream& outputMessageStream) const { + outputMessageStream << val1 << val2 << val3 << val4 << val5; +} + +} // namespace test +} // namespace bmw +} // namespace com + + +TEST_F(OutputStreamTest, WritesStructsOfArraysWithSthBefore) { + const char* signature = "(axasadasaq)"; + message = CommonAPI::DBus::DBusMessage::createMethodCall(busName, objectPath, interfaceName, methodName, signature); + CommonAPI::DBus::DBusOutputStream outStream(message); + + com::bmw::test::ArrayStruct arrayStruct; + for (int i = 0; i < numOfElements; i++) { + arrayStruct.val1.push_back(i*50); + arrayStruct.val2.push_back("Hai"); + arrayStruct.val3.push_back(3.414); + arrayStruct.val4.push_back("Ciao"); + arrayStruct.val5.push_back(i*5); + } + uint16_t frontValue = 0; + + // 2(uint16) + 6(padding) --> 8 + // 4(LengthField) + 4(padding) + 10 * 8(int64) --> 88 --> 96 + // 4(LengthField) + 10 * (4(LengthField) + 4("Hai\0")) --> 84 --> 180 + // 4(LengthField) + 10 * 8(double) --> 84 --> 264 + // 4(LengthField) + 10 * (4(LengthField) + 5("Ciao\0") + 3(padding)) --> 124 --> 388 + // 4(LengthField) + 10 * 2(uint16) --> 24 --> 412 + size_t structLength = 412; + outStream.reserveMemory(structLength); + outStream << frontValue << arrayStruct; + outStream.flush(); + + EXPECT_EQ(structLength, message.getBodyLength()); + + CommonAPI::DBus::DBusInputStream inStream(message); + com::bmw::test::ArrayStruct verifyStruct; + + uint16_t frontVerification; + inStream >> frontVerification >> verifyStruct; + + EXPECT_EQ(frontValue, frontVerification); + + int64_t res1; + std::string res2; + double res3; + std::string res4; + uint16_t res5; + + for (int i = 0; i < numOfElements; i++) { + res1 = verifyStruct.val1[i]; + res2 = verifyStruct.val2[i]; + res3 = verifyStruct.val3[i]; + res4 = verifyStruct.val4[i]; + res5 = verifyStruct.val5[i]; + + EXPECT_EQ(i*50, res1); + EXPECT_EQ(std::string("Hai"), res2); + EXPECT_EQ(3.414, res3); + EXPECT_EQ(std::string("Ciao"), res4); + EXPECT_EQ(i*5, res5); + } +} + +int main(int argc, char** argv) { + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/CommonAPI-DBus/src/test/DBusProxyTest.cpp b/CommonAPI-DBus/src/test/DBusProxyTest.cpp new file mode 100644 index 0000000..1c9beb8 --- /dev/null +++ b/CommonAPI-DBus/src/test/DBusProxyTest.cpp @@ -0,0 +1,156 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +class TestProxy: public CommonAPI::DBus::DBusProxy { +public: + TestProxy(const std::shared_ptr& dbusConnection); + ~TestProxy() = default; + +protected: + void getOwnVersion(uint16_t& ownVersionMajor, uint16_t& ownVersionMinor) const; + +}; + +class TestStubAdapter: public CommonAPI::DBus::DBusStubAdapter { +public: + TestStubAdapter(const std::shared_ptr& dbusConnection); +protected: + bool onInterfaceDBusMessage(const CommonAPI::DBus::DBusMessage& dbusMessage); + const char* getMethodsDBusIntrospectionXmlData() const; +}; + +const char* TestStubAdapter::getMethodsDBusIntrospectionXmlData() const { + return ""; +} + +bool TestStubAdapter::onInterfaceDBusMessage(const CommonAPI::DBus::DBusMessage& dbusMessage) { + return true; +} + +TestStubAdapter::TestStubAdapter(const std::shared_ptr& dbusConnection) : + CommonAPI::DBus::DBusStubAdapter( + "com.bmw.test.Echo", + "/com/bmw/test/Echo", + "com.bmw.test.Echo", + dbusConnection) { +} + +TestProxy::TestProxy(const std::shared_ptr& dbusConnection) : + CommonAPI::DBus::DBusProxy( + "com.bmw.test.Echo", + "/com/bmw/test/Echo", + "com.bmw.test.Echo", + dbusConnection) { +} + +void TestProxy::getOwnVersion(uint16_t& ownVersionMajor, uint16_t& ownVersionMinor) const { +} + + +const static std::string ID = "com.bmw.test.Echo"; + + +class ProxyTest: public ::testing::Test { +protected: + + virtual void TearDown() { + dbusConnection_->disconnect(); + } + + void SetUp() { + dbusConnection_ = CommonAPI::DBus::DBusConnection::getSessionBus(); + ASSERT_TRUE(dbusConnection_->connect()); + proxy_ = std::make_shared(dbusConnection_); + } + + std::shared_ptr dbusConnection_; + std::shared_ptr proxy_; +}; + +TEST_F(ProxyTest, HasCorrectBusName) { + std::string actualName = proxy_->getDBusBusName(); + EXPECT_EQ("com.bmw.test.Echo", actualName); +} + +TEST_F(ProxyTest, HasCorrectObjectPath) { + std::string actualPath = proxy_->getDBusObjectPath(); + EXPECT_EQ("/com/bmw/test/Echo", actualPath); +} + +TEST_F(ProxyTest, HasCorrectInterfaceName) { + std::string actualName = proxy_->getInterfaceName(); + EXPECT_EQ("com.bmw.test.Echo", actualName); +} + +TEST_F(ProxyTest, IsNotAvailable) { + bool isAvailable = proxy_->isAvailable(); + EXPECT_FALSE(isAvailable); +} + +TEST_F(ProxyTest, ServiceRegistry) { + std::shared_ptr connection = proxy_->getDBusConnection(); + auto registry = connection->getDBusServiceRegistry(); + ASSERT_FALSE(!registry); +} + +TEST_F(ProxyTest, ServiceStatus) { + std::shared_ptr stub_ = std::make_shared(dbusConnection_); + stub_->init(); + dbusConnection_->requestServiceNameAndBlock(ID); + + std::vector actuallyAvailableServices; + + + actuallyAvailableServices = dbusConnection_->getDBusServiceRegistry()->getAvailableServiceInstances("com.bmw.test.Echo", + "local"); + + std::string toFind = "com.bmw.test.Echo"; + auto found = std::find(actuallyAvailableServices.begin(), actuallyAvailableServices.end(), toFind); + + ASSERT_TRUE(actuallyAvailableServices.begin() != actuallyAvailableServices.end()); +} + +TEST_F(ProxyTest, IsAvailableBlocking) { + std::shared_ptr stub = std::make_shared(dbusConnection_); + stub->init(); + dbusConnection_->requestServiceNameAndBlock(ID); + + bool isAvailable = proxy_->isAvailableBlocking(); + EXPECT_TRUE(isAvailable); +} + +TEST_F(ProxyTest, HasNecessaryAttributesAndEvents) { + CommonAPI::InterfaceVersionAttribute& versionAttribute = (proxy_->getInterfaceVersionAttribute()); + CommonAPI::ProxyStatusEvent& statusEvent = (proxy_->getProxyStatusEvent()); +} + +TEST_F(ProxyTest, IsConnected) { + ASSERT_TRUE(proxy_->getDBusConnection()->isConnected()); +} + +TEST_F(ProxyTest, TestInterfaceVersionAttribute) { + CommonAPI::InterfaceVersionAttribute& versionAttribute = proxy_->getInterfaceVersionAttribute(); + CommonAPI::Version version; + CommonAPI::CallStatus status = versionAttribute.getValue(version); + ASSERT_EQ(CommonAPI::CallStatus::NOT_AVAILABLE, status); +} + +int main(int argc, char** argv) { + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/CommonAPI-DBus/src/test/DBusRuntimeTest.cpp b/CommonAPI-DBus/src/test/DBusRuntimeTest.cpp new file mode 100644 index 0000000..33f4017 --- /dev/null +++ b/CommonAPI-DBus/src/test/DBusRuntimeTest.cpp @@ -0,0 +1,78 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include + +#include + +#include +#include + + + +class DBusRuntimeTest: public ::testing::Test { + protected: + virtual void SetUp() { + } + + virtual void TearDown() { + } +}; + + + +TEST_F(DBusRuntimeTest, LoadsDefaultStaticallyLinkedDBusLibrary) { + std::shared_ptr runtime = CommonAPI::Runtime::load(); + ASSERT_TRUE((bool)runtime); + CommonAPI::DBus::DBusRuntime* dbusRuntime = dynamic_cast(&(*runtime)); + ASSERT_TRUE(dbusRuntime != NULL); +} + + +TEST_F(DBusRuntimeTest, LoadsSpecifiedStaticallyLinkedDBusLibrary) { + std::shared_ptr runtime = CommonAPI::Runtime::load("DBus"); + ASSERT_TRUE((bool)runtime); + CommonAPI::DBus::DBusRuntime* dbusRuntime = dynamic_cast(&(*runtime)); + ASSERT_TRUE(dbusRuntime != NULL); +} + + +TEST_F(DBusRuntimeTest, LoadsDBusLibraryAsSingleton) { + std::shared_ptr runtime1 = CommonAPI::Runtime::load("DBus"); + std::shared_ptr runtime2 = CommonAPI::Runtime::load("DBus"); + ASSERT_TRUE((bool)runtime1); + ASSERT_TRUE((bool)runtime2); + + CommonAPI::DBus::DBusRuntime* dbusRuntime1 = dynamic_cast(&(*runtime1)); + CommonAPI::DBus::DBusRuntime* dbusRuntime2 = dynamic_cast(&(*runtime2)); + ASSERT_TRUE(dbusRuntime1 != NULL); + ASSERT_TRUE(dbusRuntime2 != NULL); + + ASSERT_TRUE(dbusRuntime1 == dbusRuntime2); +} + + +TEST_F(DBusRuntimeTest, ReturnsEmptyPointerOnRequestForUnknownMiddleware) { + std::shared_ptr runtime = CommonAPI::Runtime::load("UnknownMiddlewareId"); + ASSERT_FALSE((bool)runtime); +} + + +TEST_F(DBusRuntimeTest, DBusRuntimeLoadsDBusFactory) { + std::shared_ptr runtime = CommonAPI::Runtime::load("DBus"); + ASSERT_TRUE((bool)runtime); + CommonAPI::DBus::DBusRuntime* dbusRuntime = dynamic_cast(&(*runtime)); + ASSERT_TRUE(dbusRuntime != NULL); + + std::shared_ptr proxyFactory = runtime->createFactory(); + ASSERT_TRUE((bool)proxyFactory); + CommonAPI::DBus::DBusFactory* dbusProxyFactory = dynamic_cast(&(*proxyFactory)); + ASSERT_TRUE(dbusProxyFactory != NULL); +} + + +int main(int argc, char** argv) { + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/CommonAPI-DBus/src/test/DBusSerializableStructTest.cpp b/CommonAPI-DBus/src/test/DBusSerializableStructTest.cpp new file mode 100644 index 0000000..21a41dc --- /dev/null +++ b/CommonAPI-DBus/src/test/DBusSerializableStructTest.cpp @@ -0,0 +1,77 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include + +#include + +#include "TestDBusSerializableStruct.h" + + +#define COMMON_API_TEST_TEST_STRUCT_SIGNATURE "(ud)" +#define COMMON_API_TEST_TEST_STRUCT_ARRAY_SIGNATURE "a" COMMON_API_TEST_TEST_STRUCT_SIGNATURE + +#define COMMON_API_TEST_TEST_STRUCT_EXTENDED_SIGNATURE "(uds)" +#define COMMON_API_TEST_TEST_STRUCT_EXTENDED_ARRAY_SIGNATURE "a" COMMON_API_TEST_TEST_STRUCT_EXTENDED_SIGNATURE + + +namespace common { +namespace api { +namespace test { + + +TestStruct::TestStruct(const uint32_t& fromIntValue, const double& fromDoubleValue): + intValue(fromIntValue), + doubleValue(fromDoubleValue) { +} + +common::api::dbus::DBusInputMessageStream& TestStruct::readFromDBusInputMessageStream( + common::api::dbus::DBusInputMessageStream& inputMessageStream) { + return inputMessageStream >> intValue + >> doubleValue; +} + +common::api::dbus::DBusOutputMessageStream& TestStruct::writeToDBusOutputMessageStream( + common::api::dbus::DBusOutputMessageStream& outputMessageStream) const { + return outputMessageStream << intValue + << doubleValue; +} + + +TestStructExtended::TestStructExtended(const uint32_t& fromIntValue, const double& fromDoubleValue, const std::string& fromStringValue): + TestStruct(fromIntValue, fromDoubleValue), + stringValue(fromStringValue) { +} + +common::api::dbus::DBusInputMessageStream& TestStructExtended::readFromDBusInputMessageStream( + common::api::dbus::DBusInputMessageStream& inputMessageStream) { + return TestStruct::readFromDBusInputMessageStream(inputMessageStream) >> stringValue; +} + +common::api::dbus::DBusOutputMessageStream& TestStructExtended::writeToDBusOutputMessageStream( + common::api::dbus::DBusOutputMessageStream& outputMessageStream) const { + return TestStruct::writeToDBusOutputMessageStream(outputMessageStream) << stringValue; +} + +} //namespace test +} //namespace api +} //namespace common + + +int main(void) { + using namespace common::api::test; + + TestStructExtended testStructExtended(123, 456.789, "TestStructExtended"); + + common::api::dbus::DBusMessage message = common::api::dbus::DBusMessage::createMethodCall( + "com.bmw.test.TestStruct", + "/com/bmw/test/TestStruct", + "com.bmw.test.TestStruct", + "SingleTestStruct", + COMMON_API_TEST_TEST_STRUCT_EXTENDED_SIGNATURE); + + common::api::dbus::DBusOutputMessageStream outStream(message); + outStream << testStructExtended; + outStream.flush(); +} diff --git a/CommonAPI-DBus/src/test/DBusSerializableStructTest.h b/CommonAPI-DBus/src/test/DBusSerializableStructTest.h new file mode 100644 index 0000000..63b7233 --- /dev/null +++ b/CommonAPI-DBus/src/test/DBusSerializableStructTest.h @@ -0,0 +1,66 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef DEMO_POSITIONING_H_ +#define DEMO_POSITIONING_H_ + + +#include +#include + + +namespace common { +namespace api { +namespace test { + + +struct TestStruct: public common::api::dbus::SerializableStruct { + TestStruct() = default; + TestStruct(const uint32_t& fromIntValue, const double& fromDoubleValue); + + virtual common::api::dbus::DBusInputMessageStream& readFromDBusInputMessageStream( + common::api::dbus::DBusInputMessageStream& inputMessageStream); + + virtual common::api::dbus::DBusOutputMessageStream& writeToDBusOutputMessageStream( + common::api::dbus::DBusOutputMessageStream& outputMessageStream) const; + + uint32_t intValue; + double doubleValue; +}; + + +struct TestStructExtended: public TestStruct { + TestStructExtended() = default; + + TestStructExtended(const uint32_t& fromIntValue, const double& fromDoubleValue, const std::string& fromStringValue); + + virtual common::api::dbus::DBusInputMessageStream& readFromDBusInputMessageStream( + common::api::dbus::DBusInputMessageStream& inputMessageStream); + + virtual common::api::dbus::DBusOutputMessageStream& writeToDBusOutputMessageStream( + common::api::dbus::DBusOutputMessageStream& outputMessageStream) const; + + std::string stringValue; +}; + + +typedef std::vector TestStructArray; +typedef std::vector TestStructExtendedArray; + + +} //namespace test + +namespace dbus { + +template<> +struct Alignment: SizeConstant<8> { }; + +template<> +struct Alignment: SizeConstant<8> { }; + +} //namespace dbus +} //namespace api +} //namespace common + +#endif /* DEMO_POSITIONING_H_ */ diff --git a/CommonAPI-DBus/src/test/DBusServiceRegistryTest.cpp b/CommonAPI-DBus/src/test/DBusServiceRegistryTest.cpp new file mode 100644 index 0000000..f709631 --- /dev/null +++ b/CommonAPI-DBus/src/test/DBusServiceRegistryTest.cpp @@ -0,0 +1,40 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include + + +//#define ASSERT_DBUSMESSAGE_EQ(_dbusMessage1, _dbusMessage2) \ +// ASSERT_FALSE(_dbusMessage1.getSignatureString() == NULL); \ +// ASSERT_FALSE(_dbusMessage2.getSignatureString() == NULL); \ +// ASSERT_STREQ(_dbusMessage1.getSignatureString(), _dbusMessage2.getSignatureString()); \ +// ASSERT_EQ(_dbusMessage1.getBodyLength(), _dbusMessage2.getBodyLength()); \ +// ASSERT_FALSE(_dbusMessage1.getBodyData() == NULL); \ +// ASSERT_FALSE(_dbusMessage2.getBodyData() == NULL); \ +// ASSERT_EQ(memcmp(_dbusMessage1.getBodyData(), _dbusMessage2.getBodyData(), _dbusMessage1.getBodyLength()), 0) +// +// +//namespace { +// +//class DBusConnectionTest: public ::testing::Test { +// protected: +// virtual void SetUp() { +// } +// +// virtual void TearDown() { +// } +//}; +// +// +//TEST_F(DBusConnectionTest, CanBeConstructed) { +// std::shared_ptr runtime = CommonAPI::Runtime::load(""); +// std::shared_ptr proxyFactory_ = runtime->createProxyFactory(); +//} +// +//} + + +int main() { + +} diff --git a/CommonAPI-DBus/src/test/DBusStubAdapterTest.cpp b/CommonAPI-DBus/src/test/DBusStubAdapterTest.cpp new file mode 100644 index 0000000..20abe1d --- /dev/null +++ b/CommonAPI-DBus/src/test/DBusStubAdapterTest.cpp @@ -0,0 +1,221 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include +#include + +#include +#include +#include + +static uint32_t dispatchedMessageCount; + +class TestStubRemoteEventHandler { + public: + virtual ~TestStubRemoteEventHandler() { } + + virtual bool onRemoteSetTestAttribute(int32_t testValue) = 0; + + virtual void onRemoteTestAttributeChanged() = 0; +}; + +class TestStubAdapter: virtual public CommonAPI::StubAdapter { + public: + virtual void fireTestAttributeChanged(const int32_t& testValue) = 0; +}; + +class TestStub: public CommonAPI::Stub { + public: + TestStub(): remoteEventHandler_(this) { + } + + virtual TestStubRemoteEventHandler* initStubAdapter(const std::shared_ptr& stubAdapter) { + return &remoteEventHandler_; + } + + void getEmptyResponse() { + std::cout << "onGetEmptyResponse()\n"; + dispatchedMessageCount++; + } + + void getDeepCopy(int32_t inValue, int32_t& outValue) { + outValue = inValue; + std::cout << "getDeepCopy(inValue=" << inValue << ", outValue=" << outValue << ")\n"; + dispatchedMessageCount++; + } + + void getDeepCopies(std::vector inValues, std::vector& outValues) { + outValues = inValues; + std::cout << "getDeepCopies(inValues=" << inValues.size() << ", outValues=" << outValues.size() << ")\n"; + dispatchedMessageCount++; + } + + void getShallowCopy(int32_t inValue, int32_t& outValue) { + outValue = inValue; + std::cout << "getShallowCopy(inValue=" << inValue << ", outValue=" << outValue << ")\n"; + dispatchedMessageCount++; + } + + void getShallowCopies(std::vector inValues, std::vector& outValues) { + outValues = inValues; + std::cout << "getShallowCopies(inValues=" << inValues.size() << ", outValues=" << outValues.size() << ")\n"; + dispatchedMessageCount++; + } + + const int32_t& getTestAttribute() { + return testAttributeValue_; + } + + private: + class RemoteEventHandler: public TestStubRemoteEventHandler { + public: + RemoteEventHandler(TestStub* stub): stub_(stub) { + } + + virtual bool onRemoteSetTestAttribute(int32_t testValue) { + std::cout << "RemoteEventHandler::onRemoteSetTestAttribute(" << testValue << "): oldValue = " << stub_->testAttributeValue_ << "\n"; + const bool valueChanged = (stub_->testAttributeValue_ != testValue); + stub_->testAttributeValue_ = testValue; + return valueChanged; + } + + virtual void onRemoteTestAttributeChanged() { + std::cout << "RemoteEventHandler::onRemoteTestAttributeChanged()\n"; + } + + private: + TestStub* stub_; + }; + + RemoteEventHandler remoteEventHandler_; + int32_t testAttributeValue_; +}; + +typedef CommonAPI::DBus::DBusStubAdapterHelper TestStubAdapterHelper; + +class TestDBusStubAdapter: public TestStubAdapter, public TestStubAdapterHelper { + public: + TestDBusStubAdapter(const std::string& dbusBusName, + const std::string& dbusObjectPath, + const std::shared_ptr& dbusConnection, + const std::shared_ptr& testStub) : + TestStubAdapterHelper( + dbusBusName, + dbusObjectPath, + "org.genivi.CommonAPI.DBus.TestInterface", + dbusConnection, + testStub) { + } + + virtual void fireTestAttributeChanged(const int32_t& testValue) { + std::cout << "TestDBusStubAdapter::fireTestAttributeChanged(" << testValue << ")\n"; + } + + protected: + virtual const char* getMethodsDBusIntrospectionXmlData() const; +}; + +const char* TestDBusStubAdapter::getMethodsDBusIntrospectionXmlData() const { + return "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "" + "\n" + "\n" + "\n" + "" + ; +} + +namespace { +static CommonAPI::DBus::DBusMethodWithReplyStubDispatcher< + TestStub, + std::tuple<>, + std::tuple<> > getEmptyResponseStubDispatcher(&TestStub::getEmptyResponse, ""); +static CommonAPI::DBus::DBusMethodWithReplyStubDispatcher< + TestStub, + std::tuple, + std::tuple > getDeepCopyStubDispatcher(&TestStub::getDeepCopy, "i"); +static CommonAPI::DBus::DBusMethodWithReplyStubDispatcher< + TestStub, + std::tuple>, + std::tuple> > getDeepCopiesStubDispatcher(&TestStub::getDeepCopies, "ai"); +static CommonAPI::DBus::DBusMethodWithReplyStubDispatcher< + TestStub, + std::tuple, + std::tuple > getShallowCopyStubDispatcher(&TestStub::getShallowCopy, "i"); +static CommonAPI::DBus::DBusMethodWithReplyStubDispatcher< + TestStub, + std::tuple>, + std::tuple> > getShallowCopiesStubDispatcher(&TestStub::getShallowCopies, "ai"); +static CommonAPI::DBus::DBusSetObservableAttributeStubDispatcher setTestAttributeStubDispatcher( + &TestStub::getTestAttribute, + &TestStubRemoteEventHandler::onRemoteSetTestAttribute, + &TestStubRemoteEventHandler::onRemoteTestAttributeChanged, + &TestStubAdapter::fireTestAttributeChanged, + "i"); +} + +template<> +const TestStubAdapterHelper::StubDispatcherTable TestStubAdapterHelper::stubDispatcherTable_ = { + { {"GetEmptyResponse", ""}, &getEmptyResponseStubDispatcher }, + { {"GetDeepCopy", "i"}, &getDeepCopyStubDispatcher }, + { {"GetDeepCopies", "ai"}, &getDeepCopiesStubDispatcher }, + { {"GetShallowCopy", "i"}, &getShallowCopyStubDispatcher }, + { {"GetShallowCopies", "ai"}, &getShallowCopiesStubDispatcher }, + { {"SetTestAttribute", "i"}, &setTestAttributeStubDispatcher } +}; + +int main(void) { + auto dbusConnection = CommonAPI::DBus::DBusConnection::getSessionBus(); + + if (!dbusConnection->isConnected()) + dbusConnection->connect(); + + assert(dbusConnection->isConnected()); + + const bool serviceNameAcquired = dbusConnection->requestServiceNameAndBlock( + "org.genivi.CommonAPI.DBus.TestDBusInterfaceAdapter"); + assert(serviceNameAcquired); + + auto testStub = std::make_shared(); + auto testStubAdapter = std::make_shared( + "org.genivi.CommonAPI.DBus.TestDBusInterfaceAdapter", + "/common/api/dbus/TestDBusInterfaceAdapter", + dbusConnection, + testStub); + testStubAdapter->init(); + + auto dbusMessageCall = CommonAPI::DBus::DBusMessage::createMethodCall( + "org.genivi.CommonAPI.DBus.TestDBusInterfaceAdapter", + testStubAdapter->getObjectPath().c_str(), + testStubAdapter->getServiceId().c_str(), + "GetEmptyResponse"); + + const bool messageSent = dbusConnection->sendDBusMessage(dbusMessageCall); + assert(messageSent); + + for (int i = 0; i < 10; i++) + dbusConnection->readWriteDispatch(100); + +// while (dbusConnection->readWriteDispatch(100)) +// ; + + assert(dispatchedMessageCount > 0); + + return 0; +} diff --git a/CommonAPI-DBus/src/test/DBusVariantTest.cpp b/CommonAPI-DBus/src/test/DBusVariantTest.cpp new file mode 100644 index 0000000..7928b16 --- /dev/null +++ b/CommonAPI-DBus/src/test/DBusVariantTest.cpp @@ -0,0 +1,98 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include +#include +#include +#include + +template +struct VariantTypeSelector: VariantTypeSelector<_SearchType, _RestTypes...> { +}; + +template +struct VariantTypeSelector<_SearchType, _SearchType, _RestTypes...> { + typedef _SearchType type; +}; + +template +class Variant { + private: + typedef std::tuple_size> TypesTupleSize; + + public: + Variant(): valueType_(TypesTupleSize::value) { + } + + Variant(const Variant& fromVariant): + valueType_(fromVariant.valueType_), + valueStorage_(fromVariant.valueStorage_) { + } + + Variant(Variant&& fromVariant): + valueType_(std::move(fromVariant.valueType_)), + valueStorage_(std::move(fromVariant.valueStorage_)) { + fromVariant.valueType_ = TypesTupleSize::value; + } + + ~Variant() { + if (hasValue()) { + // TODO call value destructor + } + } + + Variant& operator=(const Variant& fromVariant) { + // TODO + return *this; + } + + Variant& operator=(Variant&& fromVariant) { + // TODO + return *this; + } + + // TODO use std::enable_if + template + Variant(const _Type& value) { + // TODO index by type + valueType_ = 0; + new (&valueStorage_) _Type(value); + } + + // TODO use std::enable_if + template + Variant(_Type && value) { + // TODO index by type + valueType_ = 0; + new (&valueStorage_) typename std::remove_reference<_Type>::type(std::move(value)); + } + + template + const typename VariantTypeSelector<_Type, _Types...>::type & get(bool& success) const { + // TODO assert _Type in _Types + success = true; + return *(reinterpret_cast(&valueStorage_)); + } + + private: + inline bool hasValue() const { + return valueType_ < TypesTupleSize::value; + } + + size_t valueType_; + // TODO calculate maximum storage + std::aligned_storage<80>::type valueStorage_; +}; + + + +int main(int argc, char** argv) { + int fromInt = 5; + Variant myVariant(fromInt); + bool success; + const int& myInt = myVariant.get(success); +// const float& myFloat = myVariant.get(success); + + std::cout << "myInt = " << myInt << " (" << std::boolalpha << success << ")\n"; + return 0; +} diff --git a/CommonAPI-DBus/src/test/commonapi/tests/DerivedTypeCollection.cpp b/CommonAPI-DBus/src/test/commonapi/tests/DerivedTypeCollection.cpp new file mode 100644 index 0000000..9087e4d --- /dev/null +++ b/CommonAPI-DBus/src/test/commonapi/tests/DerivedTypeCollection.cpp @@ -0,0 +1,63 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include "DerivedTypeCollection.h" + +namespace commonapi { +namespace tests { +namespace DerivedTypeCollection { + +TestStruct::TestStruct(const PredefinedTypeCollection::TestString& testStringValue, const uint16_t& uintValueValue): + testString(testStringValue), + uintValue(uintValueValue) +{ +} + +bool operator==(const TestStruct& lhs, const TestStruct& rhs) { + if (&lhs == &rhs) + return true; + + return + lhs.testString == rhs.testString && + lhs.uintValue == rhs.uintValue + ; +} + +void TestStruct::readFromInputStream(CommonAPI::InputStream& inputStream) { + inputStream >> testString; + inputStream >> uintValue; +} + +void TestStruct::writeToOutputStream(CommonAPI::OutputStream& outputStream) const { + outputStream << testString; + outputStream << uintValue; +} +TestStructExtended::TestStructExtended(const PredefinedTypeCollection::TestString& testStringValue, const uint16_t& uintValueValue, const TestEnumExtended2& testEnumExtended2Value): + TestStruct(testStringValue, uintValueValue), + testEnumExtended2(testEnumExtended2Value) +{ +} + +bool operator==(const TestStructExtended& lhs, const TestStructExtended& rhs) { + if (&lhs == &rhs) + return true; + + return + static_cast(lhs) == static_cast(rhs) && + lhs.testEnumExtended2 == rhs.testEnumExtended2 + ; +} + +void TestStructExtended::readFromInputStream(CommonAPI::InputStream& inputStream) { + TestStruct::readFromInputStream(inputStream); + inputStream >> testEnumExtended2; +} + +void TestStructExtended::writeToOutputStream(CommonAPI::OutputStream& outputStream) const { + TestStruct::writeToOutputStream(outputStream); + outputStream << testEnumExtended2; +} + +} // namespace DerivedTypeCollection +} // namespace tests +} // namespace commonapi diff --git a/CommonAPI-DBus/src/test/commonapi/tests/DerivedTypeCollection.h b/CommonAPI-DBus/src/test/commonapi/tests/DerivedTypeCollection.h new file mode 100644 index 0000000..40d4287 --- /dev/null +++ b/CommonAPI-DBus/src/test/commonapi/tests/DerivedTypeCollection.h @@ -0,0 +1,208 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#ifndef COMMONAPI_TESTS_DERIVED_TYPE_COLLECTION_H_ +#define COMMONAPI_TESTS_DERIVED_TYPE_COLLECTION_H_ + +#include +#include +#include +#include +#include "PredefinedTypeCollection.h" +#include +#include +#include + +namespace commonapi { +namespace tests { + +namespace DerivedTypeCollection { + +enum class TestEnum: int32_t { + E_UNKNOWN = 0, + E_OK = 1, + E_OUT_OF_RANGE = 2, + E_NOT_USED = 3 +}; + +// XXX Definition of a comparator still is necessary for GCC 4.4.1, topic is fixed since 4.5.1 +struct TestEnumComparator; + +enum class TestEnumMissingValue: int32_t { + E1 = 10, + E2, + E3 = 2 +}; + +// XXX Definition of a comparator still is necessary for GCC 4.4.1, topic is fixed since 4.5.1 +struct TestEnumMissingValueComparator; + +enum class TestEnumExtended: int32_t { + E_UNKNOWN = TestEnum::E_UNKNOWN, + E_OK = TestEnum::E_OK, + E_OUT_OF_RANGE = TestEnum::E_OUT_OF_RANGE, + E_NOT_USED = TestEnum::E_NOT_USED + , + E_NEW = 4 +}; + +// XXX Definition of a comparator still is necessary for GCC 4.4.1, topic is fixed since 4.5.1 +struct TestEnumExtendedComparator; + +enum class TestEnumExtended2: int32_t { + E_UNKNOWN = TestEnum::E_UNKNOWN, + E_OK = TestEnum::E_OK, + E_OUT_OF_RANGE = TestEnum::E_OUT_OF_RANGE, + E_NOT_USED = TestEnum::E_NOT_USED, + + E_NEW = TestEnumExtended::E_NEW + , + E_NEW2 = 5 +}; + +// XXX Definition of a comparator still is necessary for GCC 4.4.1, topic is fixed since 4.5.1 +struct TestEnumExtended2Comparator; + +struct TestStruct: CommonAPI::SerializableStruct { + PredefinedTypeCollection::TestString testString; + uint16_t uintValue; + + TestStruct() = default; + TestStruct(const PredefinedTypeCollection::TestString& testString, const uint16_t& uintValue); + + virtual void readFromInputStream(CommonAPI::InputStream& inputStream); + virtual void writeToOutputStream(CommonAPI::OutputStream& outputStream) const; +}; + +struct TestStructExtended: TestStruct { + TestEnumExtended2 testEnumExtended2; + + TestStructExtended() = default; + TestStructExtended(const PredefinedTypeCollection::TestString& testString, const uint16_t& uintValue, const TestEnumExtended2& testEnumExtended2); + + virtual void readFromInputStream(CommonAPI::InputStream& inputStream); + virtual void writeToOutputStream(CommonAPI::OutputStream& outputStream) const; +}; + +typedef std::vector TestArrayUInt64; + +typedef std::vector TestArrayTestStruct; + +typedef std::unordered_map TestMap; + +inline CommonAPI::InputStream& operator>>(CommonAPI::InputStream& inputStream, TestEnum& enumValue) { + return inputStream.readEnumValue(enumValue); +} + +inline CommonAPI::OutputStream& operator<<(CommonAPI::OutputStream& outputStream, const TestEnum& enumValue) { + return outputStream.writeEnumValue(static_cast(enumValue)); +} + +struct TestEnumComparator { + inline bool operator()(const TestEnum& lhs, const TestEnum& rhs) const { + return static_cast(lhs) < static_cast(rhs); + } +}; + +inline CommonAPI::InputStream& operator>>(CommonAPI::InputStream& inputStream, TestEnumMissingValue& enumValue) { + return inputStream.readEnumValue(enumValue); +} + +inline CommonAPI::OutputStream& operator<<(CommonAPI::OutputStream& outputStream, const TestEnumMissingValue& enumValue) { + return outputStream.writeEnumValue(static_cast(enumValue)); +} + +struct TestEnumMissingValueComparator { + inline bool operator()(const TestEnumMissingValue& lhs, const TestEnumMissingValue& rhs) const { + return static_cast(lhs) < static_cast(rhs); + } +}; + +inline CommonAPI::InputStream& operator>>(CommonAPI::InputStream& inputStream, TestEnumExtended& enumValue) { + return inputStream.readEnumValue(enumValue); +} + +inline CommonAPI::OutputStream& operator<<(CommonAPI::OutputStream& outputStream, const TestEnumExtended& enumValue) { + return outputStream.writeEnumValue(static_cast(enumValue)); +} + +struct TestEnumExtendedComparator { + inline bool operator()(const TestEnumExtended& lhs, const TestEnumExtended& rhs) const { + return static_cast(lhs) < static_cast(rhs); + } +}; + + +inline bool operator==(const TestEnumExtended& lhs, const TestEnum& rhs) { + return static_cast(lhs) == static_cast(rhs); +} +inline bool operator==(const TestEnum& lhs, const TestEnumExtended& rhs) { + return static_cast(lhs) == static_cast(rhs); +} +inline bool operator!=(const TestEnumExtended& lhs, const TestEnum& rhs) { + return static_cast(lhs) != static_cast(rhs); +} +inline bool operator!=(const TestEnum& lhs, const TestEnumExtended& rhs) { + return static_cast(lhs) != static_cast(rhs); +} +inline CommonAPI::InputStream& operator>>(CommonAPI::InputStream& inputStream, TestEnumExtended2& enumValue) { + return inputStream.readEnumValue(enumValue); +} + +inline CommonAPI::OutputStream& operator<<(CommonAPI::OutputStream& outputStream, const TestEnumExtended2& enumValue) { + return outputStream.writeEnumValue(static_cast(enumValue)); +} + +struct TestEnumExtended2Comparator { + inline bool operator()(const TestEnumExtended2& lhs, const TestEnumExtended2& rhs) const { + return static_cast(lhs) < static_cast(rhs); + } +}; + + +inline bool operator==(const TestEnumExtended2& lhs, const TestEnum& rhs) { + return static_cast(lhs) == static_cast(rhs); +} +inline bool operator==(const TestEnum& lhs, const TestEnumExtended2& rhs) { + return static_cast(lhs) == static_cast(rhs); +} +inline bool operator!=(const TestEnumExtended2& lhs, const TestEnum& rhs) { + return static_cast(lhs) != static_cast(rhs); +} +inline bool operator!=(const TestEnum& lhs, const TestEnumExtended2& rhs) { + return static_cast(lhs) != static_cast(rhs); +} + +inline bool operator==(const TestEnumExtended2& lhs, const TestEnumExtended& rhs) { + return static_cast(lhs) == static_cast(rhs); +} +inline bool operator==(const TestEnumExtended& lhs, const TestEnumExtended2& rhs) { + return static_cast(lhs) == static_cast(rhs); +} +inline bool operator!=(const TestEnumExtended2& lhs, const TestEnumExtended& rhs) { + return static_cast(lhs) != static_cast(rhs); +} +inline bool operator!=(const TestEnumExtended& lhs, const TestEnumExtended2& rhs) { + return static_cast(lhs) != static_cast(rhs); +} +bool operator==(const TestStruct& lhs, const TestStruct& rhs); +inline bool operator!=(const TestStruct& lhs, const TestStruct& rhs) { + return !(lhs == rhs); +} +bool operator==(const TestStructExtended& lhs, const TestStructExtended& rhs); +inline bool operator!=(const TestStructExtended& lhs, const TestStructExtended& rhs) { + return !(lhs == rhs); +} + + +static inline const char* getTypeCollectionName() { + return "commonapi.tests.DerivedTypeCollection"; +} + + +} // namespace DerivedTypeCollection + +} // namespace tests +} // namespace commonapi + +#endif // COMMONAPI_TESTS_DERIVED_TYPE_COLLECTION_H_ diff --git a/CommonAPI-DBus/src/test/commonapi/tests/PredefinedTypeCollection.h b/CommonAPI-DBus/src/test/commonapi/tests/PredefinedTypeCollection.h new file mode 100644 index 0000000..8b6493c --- /dev/null +++ b/CommonAPI-DBus/src/test/commonapi/tests/PredefinedTypeCollection.h @@ -0,0 +1,55 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#ifndef COMMONAPI_TESTS_PREDEFINED_TYPE_COLLECTION_H_ +#define COMMONAPI_TESTS_PREDEFINED_TYPE_COLLECTION_H_ + +#include +#include +#include +#include + +namespace commonapi { +namespace tests { + +namespace PredefinedTypeCollection { + +typedef uint8_t TestUInt8; + +typedef uint16_t TestUInt16; + +typedef uint32_t TestUInt32; + +typedef uint64_t TestUInt64; + +typedef int8_t TestInt8; + +typedef int16_t TestInt16; + +typedef int32_t TestInt32; + +typedef int64_t TestInt64; + +typedef bool TestBoolean; + +typedef CommonAPI::ByteBuffer TestByteBuffer; + +typedef double TestDouble; + +typedef float TestFloat; + +typedef std::string TestString; + + + +static inline const char* getTypeCollectionName() { + return "commonapi.tests.PredefinedTypeCollection"; +} + + +} // namespace PredefinedTypeCollection + +} // namespace tests +} // namespace commonapi + +#endif // COMMONAPI_TESTS_PREDEFINED_TYPE_COLLECTION_H_ diff --git a/CommonAPI-DBus/src/test/commonapi/tests/TestInterface.h b/CommonAPI-DBus/src/test/commonapi/tests/TestInterface.h new file mode 100644 index 0000000..2252237 --- /dev/null +++ b/CommonAPI-DBus/src/test/commonapi/tests/TestInterface.h @@ -0,0 +1,32 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#ifndef COMMONAPI_TESTS_TEST_INTERFACE_H_ +#define COMMONAPI_TESTS_TEST_INTERFACE_H_ + +#include + +namespace commonapi { +namespace tests { + +class TestInterface { + public: + virtual ~TestInterface() { } + + static inline const char* getInterfaceName(); + static inline CommonAPI::Version getInterfaceVersion(); +}; + +const char* TestInterface::getInterfaceName() { + return "commonapi.tests.TestInterface"; +} + +CommonAPI::Version TestInterface::getInterfaceVersion() { + return CommonAPI::Version(1, 0); +} + + +} // namespace tests +} // namespace commonapi + +#endif // COMMONAPI_TESTS_TEST_INTERFACE_H_ diff --git a/CommonAPI-DBus/src/test/commonapi/tests/TestInterfaceDBusProxy.cpp b/CommonAPI-DBus/src/test/commonapi/tests/TestInterfaceDBusProxy.cpp new file mode 100644 index 0000000..46bedeb --- /dev/null +++ b/CommonAPI-DBus/src/test/commonapi/tests/TestInterfaceDBusProxy.cpp @@ -0,0 +1,126 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include "TestInterfaceDBusProxy.h" + +namespace commonapi { +namespace tests { + +std::shared_ptr createTestInterfaceDBusProxy(const char* busName, + const char* objectPath, + std::shared_ptr dbusProxyConnection) { + return std::make_shared(busName, objectPath, dbusProxyConnection); +} + +__attribute__((constructor)) void registerTestInterfaceDBusProxy(void) { + CommonAPI::DBus::DBusFactory::registerProxyFactoryMethod(TestInterface::getInterfaceName(), + &createTestInterfaceDBusProxy); +} + +TestInterfaceDBusProxy::TestInterfaceDBusProxy(const std::string& busName, const std::string& objectPath, const std::shared_ptr& dbusProxyconnection): + CommonAPI::DBus::DBusProxy(busName, objectPath, TestInterface::getInterfaceName(), dbusProxyconnection) +, testPredefinedTypeAttribute_(*this, "onTestPredefinedTypeAttributeAttributeChanged", "setTestPredefinedTypeAttributeAttribute", "u", "getTestPredefinedTypeAttributeAttribute"), + testDerivedStructAttribute_(*this, "onTestDerivedStructAttributeAttributeChanged", "setTestDerivedStructAttributeAttribute", "(sqi)", "getTestDerivedStructAttributeAttribute"), + testDerivedArrayAttribute_(*this, "onTestDerivedArrayAttributeAttributeChanged", "setTestDerivedArrayAttributeAttribute", "at", "getTestDerivedArrayAttributeAttribute") +, testPredefinedTypeBroadcast_(*this, "TestPredefinedTypeBroadcast", "us") + { +} + +TestInterfaceDBusProxy::TestPredefinedTypeAttributeAttribute& TestInterfaceDBusProxy::getTestPredefinedTypeAttributeAttribute() { + return testPredefinedTypeAttribute_; +} +TestInterfaceDBusProxy::TestDerivedStructAttributeAttribute& TestInterfaceDBusProxy::getTestDerivedStructAttributeAttribute() { + return testDerivedStructAttribute_; +} +TestInterfaceDBusProxy::TestDerivedArrayAttributeAttribute& TestInterfaceDBusProxy::getTestDerivedArrayAttributeAttribute() { + return testDerivedArrayAttribute_; +} + +TestInterfaceDBusProxy::TestPredefinedTypeBroadcastEvent& TestInterfaceDBusProxy::getTestPredefinedTypeBroadcastEvent() { + return testPredefinedTypeBroadcast_; +} + +void TestInterfaceDBusProxy::testVoidPredefinedTypeMethod(const uint32_t& uint32Value, const std::string& stringValue, CommonAPI::CallStatus& callStatus) { + CommonAPI::DBus::DBusProxyHelper, + CommonAPI::DBus::DBusSerializableArguments<> >::callMethodWithReply( + *this, + "testVoidPredefinedTypeMethod", + "us", + uint32Value, stringValue, + callStatus + ); +} +std::future TestInterfaceDBusProxy::testVoidPredefinedTypeMethodAsync(const uint32_t& uint32Value, const std::string& stringValue, TestVoidPredefinedTypeMethodAsyncCallback callback) { + return CommonAPI::DBus::DBusProxyHelper, + CommonAPI::DBus::DBusSerializableArguments<> >::callMethodAsync( + *this, + "testVoidPredefinedTypeMethod", + "us", + uint32Value, stringValue, + std::move(callback)); +} +void TestInterfaceDBusProxy::testPredefinedTypeMethod(const uint32_t& uint32InValue, const std::string& stringInValue, CommonAPI::CallStatus& callStatus, uint32_t& uint32OutValue, std::string& stringOutValue) { + CommonAPI::DBus::DBusProxyHelper, + CommonAPI::DBus::DBusSerializableArguments >::callMethodWithReply( + *this, + "testPredefinedTypeMethod", + "us", + uint32InValue, stringInValue, + callStatus + , uint32OutValue, stringOutValue); +} +std::future TestInterfaceDBusProxy::testPredefinedTypeMethodAsync(const uint32_t& uint32InValue, const std::string& stringInValue, TestPredefinedTypeMethodAsyncCallback callback) { + return CommonAPI::DBus::DBusProxyHelper, + CommonAPI::DBus::DBusSerializableArguments >::callMethodAsync( + *this, + "testPredefinedTypeMethod", + "us", + uint32InValue, stringInValue, + std::move(callback)); +} +void TestInterfaceDBusProxy::testVoidDerivedTypeMethod(const DerivedTypeCollection::TestEnumExtended2& testEnumExtended2Value, const DerivedTypeCollection::TestMap& testMapValue, CommonAPI::CallStatus& callStatus) { + CommonAPI::DBus::DBusProxyHelper, + CommonAPI::DBus::DBusSerializableArguments<> >::callMethodWithReply( + *this, + "testVoidDerivedTypeMethod", + "ia{ua(sq)}", + testEnumExtended2Value, testMapValue, + callStatus + ); +} +std::future TestInterfaceDBusProxy::testVoidDerivedTypeMethodAsync(const DerivedTypeCollection::TestEnumExtended2& testEnumExtended2Value, const DerivedTypeCollection::TestMap& testMapValue, TestVoidDerivedTypeMethodAsyncCallback callback) { + return CommonAPI::DBus::DBusProxyHelper, + CommonAPI::DBus::DBusSerializableArguments<> >::callMethodAsync( + *this, + "testVoidDerivedTypeMethod", + "ia{ua(sq)}", + testEnumExtended2Value, testMapValue, + std::move(callback)); +} +void TestInterfaceDBusProxy::testDerivedTypeMethod(const DerivedTypeCollection::TestEnumExtended2& testEnumExtended2InValue, const DerivedTypeCollection::TestMap& testMapInValue, CommonAPI::CallStatus& callStatus, DerivedTypeCollection::TestEnumExtended2& testEnumExtended2OutValue, DerivedTypeCollection::TestMap& testMapOutValue) { + CommonAPI::DBus::DBusProxyHelper, + CommonAPI::DBus::DBusSerializableArguments >::callMethodWithReply( + *this, + "testDerivedTypeMethod", + "ia{ua(sq)}", + testEnumExtended2InValue, testMapInValue, + callStatus + , testEnumExtended2OutValue, testMapOutValue); +} +std::future TestInterfaceDBusProxy::testDerivedTypeMethodAsync(const DerivedTypeCollection::TestEnumExtended2& testEnumExtended2InValue, const DerivedTypeCollection::TestMap& testMapInValue, TestDerivedTypeMethodAsyncCallback callback) { + return CommonAPI::DBus::DBusProxyHelper, + CommonAPI::DBus::DBusSerializableArguments >::callMethodAsync( + *this, + "testDerivedTypeMethod", + "ia{ua(sq)}", + testEnumExtended2InValue, testMapInValue, + std::move(callback)); +} + +void TestInterfaceDBusProxy::getOwnVersion(uint16_t& ownVersionMajor, uint16_t& ownVersionMinor) const { + ownVersionMajor = 1; + ownVersionMinor = 0; +} + +} // namespace tests +} // namespace commonapi diff --git a/CommonAPI-DBus/src/test/commonapi/tests/TestInterfaceDBusProxy.h b/CommonAPI-DBus/src/test/commonapi/tests/TestInterfaceDBusProxy.h new file mode 100644 index 0000000..bf0981a --- /dev/null +++ b/CommonAPI-DBus/src/test/commonapi/tests/TestInterfaceDBusProxy.h @@ -0,0 +1,54 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#ifndef COMMONAPI_TESTS_TEST_INTERFACE_DBUS_PROXY_H_ +#define COMMONAPI_TESTS_TEST_INTERFACE_DBUS_PROXY_H_ + +#include "TestInterfaceProxyBase.h" +#include +#include +#include +#include + +#include + +namespace commonapi { +namespace tests { + +class TestInterfaceDBusProxy: virtual public TestInterfaceProxyBase, virtual public CommonAPI::DBus::DBusProxy { + public: + TestInterfaceDBusProxy(const std::string& busName, const std::string& objectPath, const std::shared_ptr& dbusProxyconnection); + + virtual TestPredefinedTypeAttributeAttribute& getTestPredefinedTypeAttributeAttribute(); + virtual TestDerivedStructAttributeAttribute& getTestDerivedStructAttributeAttribute(); + virtual TestDerivedArrayAttributeAttribute& getTestDerivedArrayAttributeAttribute(); + + virtual TestPredefinedTypeBroadcastEvent& getTestPredefinedTypeBroadcastEvent(); + + + virtual void testVoidPredefinedTypeMethod(const uint32_t& uint32Value, const std::string& stringValue, CommonAPI::CallStatus& callStatus); + virtual std::future testVoidPredefinedTypeMethodAsync(const uint32_t& uint32Value, const std::string& stringValue, TestVoidPredefinedTypeMethodAsyncCallback callback); + + virtual void testPredefinedTypeMethod(const uint32_t& uint32InValue, const std::string& stringInValue, CommonAPI::CallStatus& callStatus, uint32_t& uint32OutValue, std::string& stringOutValue); + virtual std::future testPredefinedTypeMethodAsync(const uint32_t& uint32InValue, const std::string& stringInValue, TestPredefinedTypeMethodAsyncCallback callback); + + virtual void testVoidDerivedTypeMethod(const DerivedTypeCollection::TestEnumExtended2& testEnumExtended2Value, const DerivedTypeCollection::TestMap& testMapValue, CommonAPI::CallStatus& callStatus); + virtual std::future testVoidDerivedTypeMethodAsync(const DerivedTypeCollection::TestEnumExtended2& testEnumExtended2Value, const DerivedTypeCollection::TestMap& testMapValue, TestVoidDerivedTypeMethodAsyncCallback callback); + + virtual void testDerivedTypeMethod(const DerivedTypeCollection::TestEnumExtended2& testEnumExtended2InValue, const DerivedTypeCollection::TestMap& testMapInValue, CommonAPI::CallStatus& callStatus, DerivedTypeCollection::TestEnumExtended2& testEnumExtended2OutValue, DerivedTypeCollection::TestMap& testMapOutValue); + virtual std::future testDerivedTypeMethodAsync(const DerivedTypeCollection::TestEnumExtended2& testEnumExtended2InValue, const DerivedTypeCollection::TestMap& testMapInValue, TestDerivedTypeMethodAsyncCallback callback); + + virtual void getOwnVersion(uint16_t& ownVersionMajor, uint16_t& ownVersionMinor) const; + + private: + CommonAPI::DBus::DBusObservableAttribute> testPredefinedTypeAttribute_; + CommonAPI::DBus::DBusObservableAttribute> testDerivedStructAttribute_; + CommonAPI::DBus::DBusObservableAttribute> testDerivedArrayAttribute_; + + CommonAPI::DBus::DBusEvent testPredefinedTypeBroadcast_; +}; + +} // namespace tests +} // namespace commonapi + +#endif // COMMONAPI_TESTS_TEST_INTERFACE_DBUS_PROXY_H_ diff --git a/CommonAPI-DBus/src/test/commonapi/tests/TestInterfaceDBusStubAdapter.cpp b/CommonAPI-DBus/src/test/commonapi/tests/TestInterfaceDBusStubAdapter.cpp new file mode 100644 index 0000000..6a9fd96 --- /dev/null +++ b/CommonAPI-DBus/src/test/commonapi/tests/TestInterfaceDBusStubAdapter.cpp @@ -0,0 +1,216 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include "TestInterfaceDBusStubAdapter.h" +#include "TestInterface.h" + +namespace commonapi { +namespace tests { + +std::shared_ptr createTestInterfaceDBusStubAdapter(std::string busName, + std::string objectPath, + std::shared_ptr dbusProxyConnection, + std::shared_ptr stubBase) { + return std::make_shared(busName, objectPath, dbusProxyConnection, stubBase); +} + +__attribute__((constructor)) void registerTestInterfaceDBusStubAdapter(void) { + CommonAPI::DBus::DBusFactory::registerAdapterFactoryMethod(TestInterface::getInterfaceName(), + &createTestInterfaceDBusStubAdapter); +} + +TestInterfaceDBusStubAdapter::TestInterfaceDBusStubAdapter( + const std::string& dbusBusName, + const std::string& dbusObjectPath, + const std::shared_ptr& dbusConnection, + const std::shared_ptr& stub): + TestInterfaceDBusStubAdapterHelper(dbusBusName, dbusObjectPath, TestInterface::getInterfaceName(), dbusConnection, std::dynamic_pointer_cast(stub)) { +} + +const char* TestInterfaceDBusStubAdapter::getMethodsDBusIntrospectionXmlData() const { + return + "\n" + "" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + ; +} + + +static CommonAPI::DBus::DBusGetAttributeStubDispatcher< + TestInterfaceStub, + uint32_t + > getTestPredefinedTypeAttributeAttributeStubDispatcher(&TestInterfaceStub::getTestPredefinedTypeAttributeAttribute, "u"); +static CommonAPI::DBus::DBusSetObservableAttributeStubDispatcher< + TestInterfaceStub, + uint32_t + > setTestPredefinedTypeAttributeAttributeStubDispatcher( + &TestInterfaceStub::getTestPredefinedTypeAttributeAttribute, + &TestInterfaceStubRemoteEvent::onRemoteSetTestPredefinedTypeAttributeAttribute, + &TestInterfaceStubRemoteEvent::onRemoteTestPredefinedTypeAttributeAttributeChanged, + &TestInterfaceStubAdapter::fireTestPredefinedTypeAttributeAttributeChanged, + "u"); + +static CommonAPI::DBus::DBusGetAttributeStubDispatcher< + TestInterfaceStub, + DerivedTypeCollection::TestStructExtended + > getTestDerivedStructAttributeAttributeStubDispatcher(&TestInterfaceStub::getTestDerivedStructAttributeAttribute, "(sqi)"); +static CommonAPI::DBus::DBusSetObservableAttributeStubDispatcher< + TestInterfaceStub, + DerivedTypeCollection::TestStructExtended + > setTestDerivedStructAttributeAttributeStubDispatcher( + &TestInterfaceStub::getTestDerivedStructAttributeAttribute, + &TestInterfaceStubRemoteEvent::onRemoteSetTestDerivedStructAttributeAttribute, + &TestInterfaceStubRemoteEvent::onRemoteTestDerivedStructAttributeAttributeChanged, + &TestInterfaceStubAdapter::fireTestDerivedStructAttributeAttributeChanged, + "(sqi)"); + +static CommonAPI::DBus::DBusGetAttributeStubDispatcher< + TestInterfaceStub, + DerivedTypeCollection::TestArrayUInt64 + > getTestDerivedArrayAttributeAttributeStubDispatcher(&TestInterfaceStub::getTestDerivedArrayAttributeAttribute, "at"); +static CommonAPI::DBus::DBusSetObservableAttributeStubDispatcher< + TestInterfaceStub, + DerivedTypeCollection::TestArrayUInt64 + > setTestDerivedArrayAttributeAttributeStubDispatcher( + &TestInterfaceStub::getTestDerivedArrayAttributeAttribute, + &TestInterfaceStubRemoteEvent::onRemoteSetTestDerivedArrayAttributeAttribute, + &TestInterfaceStubRemoteEvent::onRemoteTestDerivedArrayAttributeAttributeChanged, + &TestInterfaceStubAdapter::fireTestDerivedArrayAttributeAttributeChanged, + "at"); + + +static CommonAPI::DBus::DBusMethodWithReplyStubDispatcher< + TestInterfaceStub, + std::tuple, + std::tuple<> + > testVoidPredefinedTypeMethodStubDispatcher(&TestInterfaceStub::testVoidPredefinedTypeMethod, ""); + +static CommonAPI::DBus::DBusMethodWithReplyStubDispatcher< + TestInterfaceStub, + std::tuple, + std::tuple + > testPredefinedTypeMethodStubDispatcher(&TestInterfaceStub::testPredefinedTypeMethod, "us"); + +static CommonAPI::DBus::DBusMethodWithReplyStubDispatcher< + TestInterfaceStub, + std::tuple, + std::tuple<> + > testVoidDerivedTypeMethodStubDispatcher(&TestInterfaceStub::testVoidDerivedTypeMethod, ""); + +static CommonAPI::DBus::DBusMethodWithReplyStubDispatcher< + TestInterfaceStub, + std::tuple, + std::tuple + > testDerivedTypeMethodStubDispatcher(&TestInterfaceStub::testDerivedTypeMethod, "ia{ua(sq)}"); + + +template<> +const TestInterfaceDBusStubAdapterHelper::StubDispatcherTable TestInterfaceDBusStubAdapterHelper::stubDispatcherTable_ = { + { { "getTestPredefinedTypeAttributeAttribute", "" }, &commonapi::tests::getTestPredefinedTypeAttributeAttributeStubDispatcher } + , { { "setTestPredefinedTypeAttributeAttribute", "u" }, &commonapi::tests::setTestPredefinedTypeAttributeAttributeStubDispatcher }, + { { "getTestDerivedStructAttributeAttribute", "" }, &commonapi::tests::getTestDerivedStructAttributeAttributeStubDispatcher } + , { { "setTestDerivedStructAttributeAttribute", "(sqi)" }, &commonapi::tests::setTestDerivedStructAttributeAttributeStubDispatcher }, + { { "getTestDerivedArrayAttributeAttribute", "" }, &commonapi::tests::getTestDerivedArrayAttributeAttributeStubDispatcher } + , { { "setTestDerivedArrayAttributeAttribute", "at" }, &commonapi::tests::setTestDerivedArrayAttributeAttributeStubDispatcher } + , + { { "testVoidPredefinedTypeMethod", "us" }, &commonapi::tests::testVoidPredefinedTypeMethodStubDispatcher }, + { { "testPredefinedTypeMethod", "us" }, &commonapi::tests::testPredefinedTypeMethodStubDispatcher }, + { { "testVoidDerivedTypeMethod", "ia{ua(sq)}" }, &commonapi::tests::testVoidDerivedTypeMethodStubDispatcher }, + { { "testDerivedTypeMethod", "ia{ua(sq)}" }, &commonapi::tests::testDerivedTypeMethodStubDispatcher } +}; + +void TestInterfaceDBusStubAdapter::fireTestPredefinedTypeAttributeAttributeChanged(const uint32_t& value) { + CommonAPI::DBus::DBusStubSignalHelper> + ::sendSignal( + *this, + "onTestPredefinedTypeAttributeAttributeChanged", + "u", + value + ); +} +void TestInterfaceDBusStubAdapter::fireTestDerivedStructAttributeAttributeChanged(const DerivedTypeCollection::TestStructExtended& value) { + CommonAPI::DBus::DBusStubSignalHelper> + ::sendSignal( + *this, + "onTestDerivedStructAttributeAttributeChanged", + "(sqi)", + value + ); +} +void TestInterfaceDBusStubAdapter::fireTestDerivedArrayAttributeAttributeChanged(const DerivedTypeCollection::TestArrayUInt64& value) { + CommonAPI::DBus::DBusStubSignalHelper> + ::sendSignal( + *this, + "onTestDerivedArrayAttributeAttributeChanged", + "at", + value + ); +} + +void TestInterfaceDBusStubAdapter::fireTestPredefinedTypeBroadcastEvent(const uint32_t& uint32Value, const std::string& stringValue) { + CommonAPI::DBus::DBusStubSignalHelper> + ::sendSignal( + *this, + "TestPredefinedTypeBroadcast", + "us", + uint32Value, stringValue + ); +} + +} // namespace tests +} // namespace commonapi diff --git a/CommonAPI-DBus/src/test/commonapi/tests/TestInterfaceDBusStubAdapter.h b/CommonAPI-DBus/src/test/commonapi/tests/TestInterfaceDBusStubAdapter.h new file mode 100644 index 0000000..ef32fd2 --- /dev/null +++ b/CommonAPI-DBus/src/test/commonapi/tests/TestInterfaceDBusStubAdapter.h @@ -0,0 +1,38 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#ifndef COMMONAPI_TESTS_TEST_INTERFACE_DBUS_STUB_ADAPTER_H_ +#define COMMONAPI_TESTS_TEST_INTERFACE_DBUS_STUB_ADAPTER_H_ + +#include "TestInterfaceStub.h" + +#include +#include + +namespace commonapi { +namespace tests { + +typedef CommonAPI::DBus::DBusStubAdapterHelper TestInterfaceDBusStubAdapterHelper; + +class TestInterfaceDBusStubAdapter: public TestInterfaceStubAdapter, public TestInterfaceDBusStubAdapterHelper { + public: + TestInterfaceDBusStubAdapter( + const std::string& dbusBusName, + const std::string& dbusObjectPath, + const std::shared_ptr& dbusConnection, + const std::shared_ptr& stub); + + void fireTestPredefinedTypeAttributeAttributeChanged(const uint32_t& value); + void fireTestDerivedStructAttributeAttributeChanged(const DerivedTypeCollection::TestStructExtended& value); + void fireTestDerivedArrayAttributeAttributeChanged(const DerivedTypeCollection::TestArrayUInt64& value); + + void fireTestPredefinedTypeBroadcastEvent(const uint32_t& uint32Value, const std::string& stringValue); + + protected: + virtual const char* getMethodsDBusIntrospectionXmlData() const; +}; + +} // namespace tests +} // namespace commonapi + +#endif // COMMONAPI_TESTS_TEST_INTERFACE_DBUS_STUB_ADAPTER_H_ diff --git a/CommonAPI-DBus/src/test/commonapi/tests/TestInterfaceProxy.h b/CommonAPI-DBus/src/test/commonapi/tests/TestInterfaceProxy.h new file mode 100644 index 0000000..749d8d3 --- /dev/null +++ b/CommonAPI-DBus/src/test/commonapi/tests/TestInterfaceProxy.h @@ -0,0 +1,237 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#ifndef COMMONAPI_TESTS_TEST_INTERFACE_PROXY_H_ +#define COMMONAPI_TESTS_TEST_INTERFACE_PROXY_H_ + +#include "TestInterfaceProxyBase.h" +#include + +namespace commonapi { +namespace tests { + +template +class TestInterfaceProxy: virtual public TestInterface, virtual public TestInterfaceProxyBase, public _AttributeExtensions... { + public: + TestInterfaceProxy(std::shared_ptr delegate); + ~TestInterfaceProxy(); + + virtual TestPredefinedTypeAttributeAttribute& getTestPredefinedTypeAttributeAttribute(); + virtual TestDerivedStructAttributeAttribute& getTestDerivedStructAttributeAttribute(); + virtual TestDerivedArrayAttributeAttribute& getTestDerivedArrayAttributeAttribute(); + + virtual TestPredefinedTypeBroadcastEvent& getTestPredefinedTypeBroadcastEvent(); + + + virtual void testVoidPredefinedTypeMethod(const uint32_t& uint32Value, const std::string& stringValue, CommonAPI::CallStatus& callStatus); + virtual std::future testVoidPredefinedTypeMethodAsync(const uint32_t& uint32Value, const std::string& stringValue, TestVoidPredefinedTypeMethodAsyncCallback callback); + + virtual void testPredefinedTypeMethod(const uint32_t& uint32InValue, const std::string& stringInValue, CommonAPI::CallStatus& callStatus, uint32_t& uint32OutValue, std::string& stringOutValue); + virtual std::future testPredefinedTypeMethodAsync(const uint32_t& uint32InValue, const std::string& stringInValue, TestPredefinedTypeMethodAsyncCallback callback); + + virtual void testVoidDerivedTypeMethod(const DerivedTypeCollection::TestEnumExtended2& testEnumExtended2Value, const DerivedTypeCollection::TestMap& testMapValue, CommonAPI::CallStatus& callStatus); + virtual std::future testVoidDerivedTypeMethodAsync(const DerivedTypeCollection::TestEnumExtended2& testEnumExtended2Value, const DerivedTypeCollection::TestMap& testMapValue, TestVoidDerivedTypeMethodAsyncCallback callback); + + virtual void testDerivedTypeMethod(const DerivedTypeCollection::TestEnumExtended2& testEnumExtended2InValue, const DerivedTypeCollection::TestMap& testMapInValue, CommonAPI::CallStatus& callStatus, DerivedTypeCollection::TestEnumExtended2& testEnumExtended2OutValue, DerivedTypeCollection::TestMap& testMapOutValue); + virtual std::future testDerivedTypeMethodAsync(const DerivedTypeCollection::TestEnumExtended2& testEnumExtended2InValue, const DerivedTypeCollection::TestMap& testMapInValue, TestDerivedTypeMethodAsyncCallback callback); + + virtual std::string getAddress() const; + virtual const std::string& getDomain() const; + virtual const std::string& getServiceId() const; + virtual const std::string& getInstanceId() const; + virtual bool isAvailable() const; + virtual CommonAPI::ProxyStatusEvent& getProxyStatusEvent(); + virtual CommonAPI::InterfaceVersionAttribute& getInterfaceVersionAttribute(); + + private: + std::shared_ptr delegate_; +}; + +namespace TestInterfaceExtensions { + template