From d346e0f4984e8529148ab859e8db4069140d2eeb Mon Sep 17 00:00:00 2001 From: dibpinto <131255173+dibpinto@users.noreply.github.com> Date: Mon, 23 Oct 2023 11:09:59 +0100 Subject: [PATCH] capicxx-someip-runtime 3.2.3-r8 (#30) * capicxx-someip-runtime 3.2.3-r8 - Changed level logs from warning to info when address_aliasing is activated - Fix incorrect timings in logs - vSomeIP Security: Update vsomeip_sec - Use steady_clock instead of high_resolution_clock - Extend SomeIP::ClientId interface to be more flexible when creating instances - Outputstream: Fix endianness issues when writing array lengths - Linux: avoid static initialization of std::mutex. - Changed the default width of a serialized enumeration from "backing type width" to 1 byte. - Updated the subscriptionMutex_ to a recursive_mutex. - Added OSS information for RSE. - Fixed open source compliance issues. - Ensure cleanup- and detach-thread do not attempt to join themself. - Removed GENIVI copyright line - Extended error message on event deserialization error. - Implemented correct sending/receiving of boolean values. - Initialize lastProcessing_ time - Update android build files - Array of uint8_t: Check remaining bytes before calling vector::assign. - Add method to convert from capi client to someipclient. - Fix Address overwriting - Adapt to CommonAPI 3.2.2 - Added main loop supervisor * Fix Copyright field and github link in README file --- AUTHORS | 2 +- Android.bp | 39 +- Android.mk | 56 +++ CHANGES | 32 ++ CMakeLists.txt | 28 +- README.md | 10 +- cmake/CommonAPI-SomeIPConfig.cmake.in | 14 +- .../CommonAPI/SomeIP/AddressTranslator.hpp | 25 -- include/CommonAPI/SomeIP/ClientId.hpp | 14 +- include/CommonAPI/SomeIP/Configuration.hpp | 45 +- include/CommonAPI/SomeIP/Connection.hpp | 4 +- include/CommonAPI/SomeIP/Defines.hpp | 10 + include/CommonAPI/SomeIP/Event.hpp | 6 +- include/CommonAPI/SomeIP/Helper.hpp | 12 + include/CommonAPI/SomeIP/InputStream.hpp | 2 + include/CommonAPI/SomeIP/Message.hpp | 3 + include/CommonAPI/SomeIP/OutputStream.hpp | 24 +- include/CommonAPI/SomeIP/ProxyBase.hpp | 4 +- .../CommonAPI/SomeIP/StubAdapterHelper.hpp | 269 ++++++----- include/CommonAPI/SomeIP/Types.hpp | 5 +- include/CommonAPI/SomeIP/Watch.hpp | 22 +- libcommonapi_someip.yaml | 6 + src/CommonAPI/SomeIP/AddressTranslator.cpp | 347 +-------------- src/CommonAPI/SomeIP/ClientId.cpp | 45 +- src/CommonAPI/SomeIP/Configuration.cpp | 419 ++++++++++++++++++ src/CommonAPI/SomeIP/Connection.cpp | 66 ++- src/CommonAPI/SomeIP/Factory.cpp | 5 +- src/CommonAPI/SomeIP/InputStream.cpp | 4 +- src/CommonAPI/SomeIP/Message.cpp | 18 +- src/CommonAPI/SomeIP/OutputStream.cpp | 2 +- src/CommonAPI/SomeIP/Proxy.cpp | 5 +- src/CommonAPI/SomeIP/ProxyBase.cpp | 26 +- src/CommonAPI/SomeIP/Watch.cpp | 103 ++++- 33 files changed, 1048 insertions(+), 624 deletions(-) create mode 100644 Android.mk create mode 100644 libcommonapi_someip.yaml create mode 100644 src/CommonAPI/SomeIP/Configuration.cpp diff --git a/AUTHORS b/AUTHORS index 632e479..cc7c126 100644 --- a/AUTHORS +++ b/AUTHORS @@ -1 +1 @@ -Bayerische Motoren Werke Aktiengesellschaft (BMW AG) \ No newline at end of file +Bayerische Motoren Werke Aktiengesellschaft (BMW AG) diff --git a/Android.bp b/Android.bp index 8654f6d..f2be7e9 100644 --- a/Android.bp +++ b/Android.bp @@ -1,29 +1,34 @@ -capi_someip_srcs = [ - "src/CommonAPI/SomeIP/**/*.cpp" -] - cc_library_shared { - name: "libCommonAPI-SomeIP", - vendor: true, - srcs: capi_someip_srcs, - defaults: [ - "capi_defaults" - ], + name: "libcommonapi_someip", + defaults: ["libcommonapi_defaults"], + cppflags: [ "-D_GLIBCXX_USE_NANOSLEEP", "-DBOOST_LOG_DYN_LINK", "-pthread", "-Wno-unused-private-field" ], + + local_include_dirs: [ - "include" - ], - export_include_dirs: [ - "include" + "include", + "internal", ], + shared_libs: [ - "libCommonAPI", - "libvsomeip3" + "libboost_log", + "libboost_system", + "libboost_thread", + "libvsomeip3", + "libcommonapi", + ], + + export_include_dirs: [ + "include", + ], + + srcs: [ + "src/CommonAPI/SomeIP/**/*.cpp" ], - rtti: true } + diff --git a/Android.mk b/Android.mk new file mode 100644 index 0000000..49fd2be --- /dev/null +++ b/Android.mk @@ -0,0 +1,56 @@ +# Cannot convert to Android.bp as resource copying has not +# yet implemented for soong as of 12/16/2016 + +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_MODULE := libcommonapi_someip_dlt +LOCAL_MODULE_TAGS := optional +LOCAL_CLANG := true +LOCAL_PROPRIETARY_MODULE := true + +LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include + +LOCAL_SRC_FILES += \ + src/CommonAPI/SomeIP/Address.cpp \ + src/CommonAPI/SomeIP/AddressTranslator.cpp \ + src/CommonAPI/SomeIP/ClientId.cpp \ + src/CommonAPI/SomeIP/Configuration.cpp \ + src/CommonAPI/SomeIP/Connection.cpp \ + src/CommonAPI/SomeIP/DispatchSource.cpp \ + src/CommonAPI/SomeIP/Factory.cpp \ + src/CommonAPI/SomeIP/InputStream.cpp \ + src/CommonAPI/SomeIP/InstanceAvailabilityStatusChangedEvent.cpp \ + src/CommonAPI/SomeIP/Message.cpp \ + src/CommonAPI/SomeIP/OutputStream.cpp \ + src/CommonAPI/SomeIP/Proxy.cpp \ + src/CommonAPI/SomeIP/ProxyBase.cpp \ + src/CommonAPI/SomeIP/ProxyManager.cpp \ + src/CommonAPI/SomeIP/StringEncoder.cpp \ + src/CommonAPI/SomeIP/StubAdapter.cpp \ + src/CommonAPI/SomeIP/StubManager.cpp \ + src/CommonAPI/SomeIP/SubscriptionStatusWrapper.cpp \ + src/CommonAPI/SomeIP/Watch.cpp \ + +LOCAL_C_INCLUDES := \ + $(LOCAL_PATH)/include \ + $(LOCAL_PATH)/internal + +LOCAL_SHARED_LIBRARIES := \ + libboost_log \ + libboost_system \ + libboost_thread \ + libvsomeip_dlt \ + libcommonapi_dlt \ + +LOCAL_CFLAGS := \ + -frtti -fexceptions \ + -Wno-ignored-attributes \ + -Wno-unused-private-field \ + -D_CRT_SECURE_NO_WARNINGS \ + -DCOMMONAPI_INTERNAL_COMPILATION \ + -DCOMMONAPI_LOGLEVEL=COMMONAPI_LOGLEVEL_VERBOSE \ + +include $(BUILD_SHARED_LIBRARY) + diff --git a/CHANGES b/CHANGES index 85ab4f6..14f5b90 100644 --- a/CHANGES +++ b/CHANGES @@ -1,6 +1,38 @@ Changes ======= +v3.2.3-r8 +- Changed level logs from warning to info when address_aliasing is activated +- Fix incorrect timings in logs +- vSomeIP Security: Update vsomeip_sec +- Use steady_clock instead of high_resolution_clock +- Extend SomeIP::ClientId interface to be more flexible when creating instances +- Outputstream: Fix endianness issues when writing array lengths + +v3.2.3-r7 +- Linux: avoid static initialization of std::mutex. +- Changed the default width of a serialized enumeration from + "backing type width" to 1 byte. + +v3.2.3 +- Updated the subscriptionMutex_ to a recursive_mutex. +- Added OSS information for RSE. +- Fixed open source compliance issues. +- Ensure cleanup- and detach-thread do not attempt to join + themself. +- Removed GENIVI copyright line +- Extended error message on event deserialization error. +- Implemented correct sending/receiving of boolean values. +- Initialize lastProcessing_ time +- Update android build files +- Array of uint8_t: Check remaining bytes before calling vector::assign. +- Add method to convert from capi client to someipclient. +- Fix Address overwriting + +v3.2.2 +- Adapt to CommonAPI 3.2.2 +- Added main loop supervisor + v3.2.0 - Adapt to CommonAPI v3.2.0 diff --git a/CMakeLists.txt b/CMakeLists.txt index ad72647..22fa95e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,7 +11,7 @@ set (CMAKE_VERBOSE_MAKEFILE off) set (LIBCOMMONAPI_SOMEIP_MAJOR_VERSION 3) set (LIBCOMMONAPI_SOMEIP_MINOR_VERSION 2) -set (LIBCOMMONAPI_SOMEIP_PATCH_VERSION 0) +set (LIBCOMMONAPI_SOMEIP_PATCH_VERSION 3) message(STATUS "Project name: ${PROJECT_NAME}") @@ -116,16 +116,16 @@ endforeach () ################################################################################################### if ("${USE_INSTALLED_COMMONAPI}" STREQUAL "ON") - FIND_PACKAGE(CommonAPI 3.2.0 REQUIRED CONFIG NO_CMAKE_PACKAGE_REGISTRY) + FIND_PACKAGE(CommonAPI 3.2 REQUIRED CONFIG NO_CMAKE_PACKAGE_REGISTRY) else() - FIND_PACKAGE(CommonAPI 3.2.0 REQUIRED CONFIG NO_SYSTEM_ENVIRONMENT_PATH NO_CMAKE_SYSTEM_PATH) + FIND_PACKAGE(CommonAPI 3.2 REQUIRED CONFIG NO_SYSTEM_ENVIRONMENT_PATH NO_CMAKE_SYSTEM_PATH) endif() message(STATUS "CommonAPI_CONSIDERED_CONFIGS: ${CommonAPI_CONSIDERED_CONFIGS}") message(STATUS "COMMONAPI_INCLUDE_DIRS: ${COMMONAPI_INCLUDE_DIRS}") message(STATUS "CommonAPI Version: ${CommonAPI_VERSION}") -find_package (vsomeip3 3.1.0 REQUIRED) +find_package (vsomeip3 3.2.0 REQUIRED) message(STATUS "Using vsomeip3 - v${vsomeip3_VERSION}") include_directories ( @@ -141,7 +141,10 @@ list (SORT CommonAPI-SomeIP_SRC) # CommonAPI add_library (CommonAPI-SomeIP SHARED ${CommonAPI-SomeIP_SRC}) set_target_properties (CommonAPI-SomeIP PROPERTIES VERSION ${COMPONENT_VERSION} SOVERSION ${COMPONENT_VERSION}) -target_link_libraries (CommonAPI-SomeIP CommonAPI ${VSOMEIP_LIBRARIES}) +target_include_directories(CommonAPI-SomeIP INTERFACE + $ + $) +target_link_libraries(CommonAPI-SomeIP PUBLIC CommonAPI ${VSOMEIP_LIBRARIES}) if (MSVC) target_link_libraries(CommonAPI-SomeIP ws2_32 Rpcrt4) @@ -178,24 +181,15 @@ export (PACKAGE CommonAPI-SomeIP) # Create the CommonAPI-SomeIPConfig.cmake and CommonAPI-SomeIPConfigVersion files file (RELATIVE_PATH REL_INCLUDE_DIR "${ABSOLUTE_INSTALL_CMAKE_DIR}" "${ABSOLUTE_INSTALL_INCLUDE_DIR}") -# ... for the build tree -set (CONF_INCLUDE_DIRS "${PROJECT_SOURCE_DIR}/include") configure_file (${CMAKE_CURRENT_SOURCE_DIR}/cmake/CommonAPI-SomeIPConfig.cmake.in "${PROJECT_BINARY_DIR}/CommonAPI-SomeIPConfig.cmake" @ONLY) - -# ... for the install tree -set (CONF_INCLUDE_DIRS "\${COMMONAPI_SOMEIP_CMAKE_DIR}/${REL_INCLUDE_DIR}") -configure_file (${CMAKE_CURRENT_SOURCE_DIR}/cmake/CommonAPI-SomeIPConfig.cmake.in - "${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CommonAPI-SomeIPConfig.cmake" @ONLY) - -# ... for both configure_file (${CMAKE_CURRENT_SOURCE_DIR}/cmake/CommonAPI-SomeIPConfigVersion.cmake.in "${PROJECT_BINARY_DIR}/CommonAPI-SomeIPConfigVersion.cmake" @ONLY) # Install the CommonAPI-SomeIPConfig.cmake and CommonAPI-SomeIPConfigVersion.cmake install ( FILES - "${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CommonAPI-SomeIPConfig.cmake" + "${PROJECT_BINARY_DIR}/CommonAPI-SomeIPConfig.cmake" "${PROJECT_BINARY_DIR}/CommonAPI-SomeIPConfigVersion.cmake" DESTINATION "${INSTALL_CMAKE_DIR}" ) @@ -211,6 +205,10 @@ install ( if(NOT WIN32) configure_file(CommonAPI-SomeIP.pc.in ${PROJECT_BINARY_DIR}/CommonAPI-SomeIP.pc @ONLY) install(FILES ${PROJECT_BINARY_DIR}/CommonAPI-SomeIP.pc DESTINATION lib/pkgconfig) + + # force all use of std::mutex and std::recursive_mutex to use runtime init + # instead of static initialization so mutexes can be hooked to enable PI as needed + add_definitions(-D_GTHREAD_USE_MUTEX_INIT_FUNC -D_GTHREAD_USE_RECURSIVE_MUTEX_INIT_FUNC) endif() ############################################################################## diff --git a/README.md b/README.md index 2aa5252..cfcd2ed 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,11 @@ ### CommonAPI C++ SOME/IP Runtime ##### Copyright -Copyright (C) 2016-2020, Bayerische Motoren Werke Aktiengesellschaft (BMW AG). -Copyright (C) 2016-2020, GENIVI Alliance, Inc. +Copyright (C) 2016-2023, Bayerische Motoren Werke Aktiengesellschaft (BMW AG). +Copyright (C) 2016-2023, COVESA -This file is part of GENIVI Project IPC Common API C++. -Contributions are licensed to the GENIVI Alliance under one or more Contribution License Agreements or MPL 2.0. +This file is part of COVESA Project IPC Common API C++. +Contributions are licensed to the COVESA under one or more Contribution License Agreements or MPL 2.0. ##### License 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/. @@ -14,7 +14,7 @@ This Source Code Form is subject to the terms of the Mozilla Public License, v. The user guide can be found in the documentation directory of the CommonAPI-SomeIP-Tools project as AsciiDoc document. A pdf version can be found at https://github.com/GENIVI/capicxx-someip-tools/releases. ##### Further information -https://genivi.github.io/capicxx-core-tools/ +https://covesa.github.io/capicxx-core-tools/ ##### Build Instructions for Linux diff --git a/cmake/CommonAPI-SomeIPConfig.cmake.in b/cmake/CommonAPI-SomeIPConfig.cmake.in index a172622..632d4f4 100644 --- a/cmake/CommonAPI-SomeIPConfig.cmake.in +++ b/cmake/CommonAPI-SomeIPConfig.cmake.in @@ -1,12 +1,20 @@ # Config file for the CommonAPI-SomeIP package -# It defines the following variables -# COMMONAPI_SOMEIP_INCLUDE_DIRS - include directories for CommonAPI-SomeIP +# Exports the follwing targets: +# CommonAPI-SomeIP - CMake target for CommonAPI SomeIP +# Additionally, the following variables are defined: +# COMMONAPI_SOMEIP_VERSION - The CommonAPI-SomeIP version number + +# Find dependencies +find_package(CommonAPI REQUIRED) +find_package(vsomeip3 REQUIRED) # Compute paths get_filename_component (COMMONAPI_SOMEIP_CMAKE_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH) -set (COMMONAPI_SOMEIP_INCLUDE_DIRS "@CONF_INCLUDE_DIRS@") include ("${COMMONAPI_SOMEIP_CMAKE_DIR}/CommonAPI-SomeIPTargets.cmake") +# Legacy variable, kept for compatibility +get_target_property(COMMONAPI_SOMEIP_INCLUDE_DIRS CommonAPI-SomeIP INTERFACE_INCLUDE_DIRECTORIES) + set(COMMONAPI_SOMEIP_VERSION @PACKAGE_VERSION@) set(COMMONAPI_SOMEIP_VERSION_STRING "@PACKAGE_VERSION@") \ No newline at end of file diff --git a/include/CommonAPI/SomeIP/AddressTranslator.hpp b/include/CommonAPI/SomeIP/AddressTranslator.hpp index 3925b54..8a8194c 100644 --- a/include/CommonAPI/SomeIP/AddressTranslator.hpp +++ b/include/CommonAPI/SomeIP/AddressTranslator.hpp @@ -42,38 +42,13 @@ class AddressTranslator { service_id_t _service, instance_id_t _instance, major_version_t _major, minor_version_t _minor); - COMMONAPI_EXPORT const Address & getAddressAlias(const Address &_address) const; - COMMONAPI_EXPORT method_id_t getMethodAlias(const Address &_address, - const method_id_t _method) const; - COMMONAPI_EXPORT eventgroup_id_t getEventgroupAlias(const Address &_address, - const eventgroup_id_t _eventgroup) const; - private: - COMMONAPI_EXPORT bool readConfiguration(); - COMMONAPI_EXPORT void readServiceAlias(const std::string &_source, - const std::string &_target); - COMMONAPI_EXPORT void readMethodAlias(const std::string &_source, - const std::string &_target); - COMMONAPI_EXPORT void readEventgroupAlias(const std::string &_source, - const std::string &_target); - COMMONAPI_EXPORT bool readValue(const std::string &_data, - Address &_sourceAddress, uint16_t &_id, bool _readId); - COMMONAPI_EXPORT bool isValidService(const service_id_t) const; COMMONAPI_EXPORT bool isValidInstance(const instance_id_t) const; - COMMONAPI_EXPORT bool isValidMethod(const method_id_t) const; - COMMONAPI_EXPORT bool isValidEventgroup(const eventgroup_id_t) const; - -private: - std::string defaultConfig_; std::map forwards_; std::map backwards_; - typedef std::map MethodAlias_t; - typedef std::map EventgroupAlias_t; - typedef std::tuple Alias_t; - std::map aliases_; #ifdef COMMONAPI_ENABLE_ADDRESS_ALIASES std::map others_; #endif // COMMONAPI_ENABLE_ADDRESS_ALIASES diff --git a/include/CommonAPI/SomeIP/ClientId.hpp b/include/CommonAPI/SomeIP/ClientId.hpp index 5d74984..0598016 100644 --- a/include/CommonAPI/SomeIP/ClientId.hpp +++ b/include/CommonAPI/SomeIP/ClientId.hpp @@ -30,7 +30,13 @@ class COMMONAPI_EXPORT_CLASS_EXPLICIT ClientId : public CommonAPI::ClientId{ friend struct std::hash< ClientId >; public: - COMMONAPI_EXPORT ClientId(client_id_t client_id, uid_t _uid, gid_t _gid); + COMMONAPI_EXPORT ClientId(); + COMMONAPI_EXPORT ClientId(client_id_t client_id, + const sec_client_t *_sec_client, + const std::string &_env); + COMMONAPI_EXPORT ClientId(client_id_t client_id, + const sec_client_t &_sec_client, + const std::string &_env); COMMONAPI_EXPORT virtual ~ClientId(); COMMONAPI_EXPORT bool operator==(CommonAPI::ClientId& clientIdToCompare); @@ -40,11 +46,17 @@ class COMMONAPI_EXPORT_CLASS_EXPLICIT ClientId : public CommonAPI::ClientId{ COMMONAPI_EXPORT client_id_t getClientId(); COMMONAPI_EXPORT uid_t getUid() const; COMMONAPI_EXPORT gid_t getGid() const; + COMMONAPI_EXPORT std::string getEnv() const; + COMMONAPI_EXPORT std::string getHostAddress() const; + + COMMONAPI_EXPORT static std::shared_ptr getSomeIPClient(const std::shared_ptr _client); protected: client_id_t client_id_; uid_t uid_; gid_t gid_; + std::string env_; + std::string hostAddress_; }; } // namespace SomeIP diff --git a/include/CommonAPI/SomeIP/Configuration.hpp b/include/CommonAPI/SomeIP/Configuration.hpp index 2836639..7368a81 100644 --- a/include/CommonAPI/SomeIP/Configuration.hpp +++ b/include/CommonAPI/SomeIP/Configuration.hpp @@ -10,11 +10,52 @@ #ifndef COMMONAPI_SOMEIP_CONFIGURATION_HPP_ #define COMMONAPI_SOMEIP_CONFIGURATION_HPP_ +#include +#include +#include + namespace CommonAPI { namespace SomeIP { -struct FactoryConfig { - bool useVirtualMode; +class Configuration { +public: + static std::shared_ptr get(); + static void load(); + + Configuration(); + ~Configuration() = default; + + COMMONAPI_EXPORT int64_t getMaxProcessingTime(const std::string &_name) const; + COMMONAPI_EXPORT std::size_t getMaxQueueSize(const std::string &_name) const; + + COMMONAPI_EXPORT const Address & getAddressAlias(const Address &_address) const; + COMMONAPI_EXPORT method_id_t getMethodAlias(const Address &_address, + const method_id_t _method) const; + COMMONAPI_EXPORT eventgroup_id_t getEventgroupAlias(const Address &_address, + const eventgroup_id_t _eventgroup) const; + +private: + COMMONAPI_EXPORT void readConfiguration(); + COMMONAPI_EXPORT void readServiceAlias(const std::string &_source, + const std::string &_target); + COMMONAPI_EXPORT void readMethodAlias(const std::string &_source, + const std::string &_target); + COMMONAPI_EXPORT void readEventgroupAlias(const std::string &_source, + const std::string &_target); + COMMONAPI_EXPORT bool readValue(const std::string &_data, + Address &_sourceAddress, uint16_t &_id, bool _readId); + + COMMONAPI_EXPORT bool isValidMethod(const method_id_t) const; + COMMONAPI_EXPORT bool isValidEventgroup(const eventgroup_id_t) const; + + std::string defaultConfig_; + + typedef std::map MethodAlias_t; + typedef std::map EventgroupAlias_t; + typedef std::tuple Alias_t; + std::map aliases_; + + std::map > watchLimits_; }; } // namespace SomeIP diff --git a/include/CommonAPI/SomeIP/Connection.hpp b/include/CommonAPI/SomeIP/Connection.hpp index 6147fb1..fd0554a 100644 --- a/include/CommonAPI/SomeIP/Connection.hpp +++ b/include/CommonAPI/SomeIP/Connection.hpp @@ -127,6 +127,8 @@ class Connection: bool connect(bool startDispatchThread = true); void disconnect(); + std::string getName() const; + virtual bool isConnected() const; virtual void waitUntilConnected(); @@ -328,7 +330,7 @@ class Connection: std::map>>> requestedEvents_; std::map>> subscription_; - std::mutex subscriptionMutex_; + std::recursive_mutex subscriptionMutex_; std::map, session_id_fake_t> errorResponses_; diff --git a/include/CommonAPI/SomeIP/Defines.hpp b/include/CommonAPI/SomeIP/Defines.hpp index 1f2f2f7..8342063 100644 --- a/include/CommonAPI/SomeIP/Defines.hpp +++ b/include/CommonAPI/SomeIP/Defines.hpp @@ -13,7 +13,17 @@ namespace CommonAPI { namespace SomeIP { +#ifndef COMMONAPI_SOMEIP_APPLICATION_NAME #define COMMONAPI_SOMEIP_APPLICATION_NAME "" +#endif + +#ifndef DEFAULT_MAX_PROCESSING_TIME +#define DEFAULT_MAX_PROCESSING_TIME 100 +#endif + +#ifndef DEFAULT_MAX_QUEUE_SIZE +#define DEFAULT_MAX_QUEUE_SIZE 25 +#endif } // namespace SomeIP } // namespace CommonAPI diff --git a/include/CommonAPI/SomeIP/Event.hpp b/include/CommonAPI/SomeIP/Event.hpp index b828d3e..dd2db98 100644 --- a/include/CommonAPI/SomeIP/Event.hpp +++ b/include/CommonAPI/SomeIP/Event.hpp @@ -115,8 +115,7 @@ class Event: public Events_ { proxy_.removeEventHandler(serviceId_, instanceId_, eventgroupId_, eventId_, handler_.get(), major, minor); } - virtual void onListenerRemoved(const Listener&) { - + virtual void onListenerRemoved(const Listener&, const Subscription) { } template @@ -152,7 +151,8 @@ class Event: public Events_ { } } } else { - COMMONAPI_ERROR("CommonAPI::SomeIP::Event: deserialization failed!"); + COMMONAPI_ERROR("CommonAPI::SomeIP::Event: deserialization failed! [", + std::hex, serviceId_, ".", instanceId_, ".", eventId_, "]"); } } diff --git a/include/CommonAPI/SomeIP/Helper.hpp b/include/CommonAPI/SomeIP/Helper.hpp index dfcce24..850d374 100644 --- a/include/CommonAPI/SomeIP/Helper.hpp +++ b/include/CommonAPI/SomeIP/Helper.hpp @@ -34,6 +34,18 @@ struct make_sequence_range<0, Offset_, S_...> { typedef index_sequence type; }; +static inline std::string +addressToString(vsomeip_sec_ip_addr_t _addr) { + + std::ostringstream itsConverter; + itsConverter << std::dec + << (_addr & 0xff) << '.' + << ((_addr >> 8) & 0xff) << '.' + << ((_addr >> 16) & 0xff) << '.' + << ((_addr >> 24) & 0xff); + return itsConverter.str(); +} + } // namespace SomeIP } // namespace CommonAPI diff --git a/include/CommonAPI/SomeIP/InputStream.hpp b/include/CommonAPI/SomeIP/InputStream.hpp index 90bda22..dd10c81 100644 --- a/include/CommonAPI/SomeIP/InputStream.hpp +++ b/include/CommonAPI/SomeIP/InputStream.hpp @@ -307,6 +307,8 @@ class InputStream: public CommonAPI::InputStream { } } else { itsSize = arrayMaxLength; + if (itsSize > remaining_) + errorOccurred_ = true; } // Reset target diff --git a/include/CommonAPI/SomeIP/Message.hpp b/include/CommonAPI/SomeIP/Message.hpp index 86034ac..389a55e 100644 --- a/include/CommonAPI/SomeIP/Message.hpp +++ b/include/CommonAPI/SomeIP/Message.hpp @@ -70,6 +70,9 @@ class Message { COMMONAPI_EXPORT uid_t getUid() const; COMMONAPI_EXPORT gid_t getGid() const; + COMMONAPI_EXPORT sec_client_t getSecClient() const; + COMMONAPI_EXPORT std::string getEnv() const; + COMMONAPI_EXPORT std::string getHostAddress() const; private: std::shared_ptr message_; diff --git a/include/CommonAPI/SomeIP/OutputStream.hpp b/include/CommonAPI/SomeIP/OutputStream.hpp index a8c79e4..54b5542 100644 --- a/include/CommonAPI/SomeIP/OutputStream.hpp +++ b/include/CommonAPI/SomeIP/OutputStream.hpp @@ -149,7 +149,9 @@ class OutputStream: public CommonAPI::OutputStream { break; } } else { - writeValue(_value.value_, static_cast(nullptr)); + // Default enumeration width is 1 Byte + uint8_t value = static_cast(_value); + writeValue(value, static_cast(nullptr)); } return (*this); } @@ -454,8 +456,8 @@ class OutputStream: public CommonAPI::OutputStream { // Initialize the source value value.typed_ = _value; - // sanity check bit count - if (_bits > (sizeof(Type_) << 3)) + // sanity check bit count + if (_bits > (sizeof(Type_) << 3)) _bits = (sizeof(Type_) << 3); if (currentBit_ == 0 && _bits == (sizeof(Type_) << 3)) { @@ -566,20 +568,7 @@ class OutputStream: public CommonAPI::OutputStream { byte_t raw[sizeof(Type_)]; } value; value.typed = _value; - #if __BYTE_ORDER == __LITTLE_ENDIAN - if (isLittleEndian_) { - _writeRawAt(value.raw, sizeof(Type_), _position); - } else { - byte_t reordered[sizeof(Type_)]; - byte_t *source = &value.raw[sizeof(Type_) - 1]; - byte_t *target = reordered; - for (size_t i = 0; i < sizeof(Type_); ++i) { - *target++ = *source--; - } - _writeRawAt(reordered, sizeof(Type_), _position); - } - #else - if (isLittleEndian_) { + if ((__BYTE_ORDER == __LITTLE_ENDIAN) != isLittleEndian_) { byte_t reordered[sizeof(Type_)]; byte_t *source = &value.raw[sizeof(Type_) - 1]; byte_t *target = reordered; @@ -590,7 +579,6 @@ class OutputStream: public CommonAPI::OutputStream { } else { _writeRawAt(value.raw, sizeof(Type_), _position); } - #endif } else { COMMONAPI_ERROR("SomeIP::OutputStream::_writeValueAt payload too small ", payload_.size(), " pos: ", _position, " value size", sizeof(Type_)); diff --git a/include/CommonAPI/SomeIP/ProxyBase.hpp b/include/CommonAPI/SomeIP/ProxyBase.hpp index d083917..3930b5e 100644 --- a/include/CommonAPI/SomeIP/ProxyBase.hpp +++ b/include/CommonAPI/SomeIP/ProxyBase.hpp @@ -25,7 +25,7 @@ namespace CommonAPI { namespace SomeIP { class Address; -class AddressTranslator; +class Configuration; class COMMONAPI_EXPORT_CLASS_EXPLICIT ProxyBase : public virtual CommonAPI::Proxy { @@ -101,7 +101,7 @@ class COMMONAPI_EXPORT_CLASS_EXPLICIT ProxyBase std::set eventHandlerAdded_; std::mutex eventHandlerAddedMutex_; - std::shared_ptr addressTranslator_; + std::shared_ptr configuration_; }; const std::shared_ptr< ProxyConnection >& ProxyBase::getConnection() const { diff --git a/include/CommonAPI/SomeIP/StubAdapterHelper.hpp b/include/CommonAPI/SomeIP/StubAdapterHelper.hpp index 2435ee6..8a366de 100644 --- a/include/CommonAPI/SomeIP/StubAdapterHelper.hpp +++ b/include/CommonAPI/SomeIP/StubAdapterHelper.hpp @@ -46,9 +46,9 @@ struct AttributeDispatcherStruct { StubDispatcher* getter; StubDispatcher* setter; - AttributeDispatcherStruct(StubDispatcher* g, StubDispatcher* s) { - getter = g; - setter = s; + AttributeDispatcherStruct(StubDispatcher *_getter, StubDispatcher *_setter) { + getter = _getter; + setter = _setter; } }; @@ -70,12 +70,11 @@ class StubAdapterHelper { (void) _remoteEventHandler; } protected: - bool findDispatcherAndHandle(const Message &message, const method_id_t &methodId) { - (void) message; - (void) methodId; - auto error = message.createErrorResponseMessage(return_code_e::E_UNKNOWN_METHOD); - proxyConnection_->sendMessage(error); - return false; + bool findDispatcherAndHandle(const Message &_message, const method_id_t &_method) { + (void) _method; + auto itsError = _message.createErrorResponseMessage(return_code_e::E_UNKNOWN_METHOD); + proxyConnection_->sendMessage(itsError); + return false; } std::shared_ptr< ProxyConnection > proxyConnection_; @@ -109,11 +108,11 @@ class StubAdapterHelper: stub_.reset(); } - virtual void init(std::shared_ptr instance) { - StubAdapter::init(instance); - std::shared_ptr stubAdapter - = std::dynamic_pointer_cast(instance); - remoteEventHandler_ = stub_->initStubAdapter(stubAdapter); + virtual void init(std::shared_ptr _instance) { + StubAdapter::init(_instance); + std::shared_ptr itsStubAdapter + = std::dynamic_pointer_cast(_instance); + remoteEventHandler_ = stub_->initStubAdapter(itsStubAdapter); StubAdapterHelper::setRemoteEventHandler(remoteEventHandler_); } @@ -133,35 +132,35 @@ class StubAdapterHelper: protected: - virtual bool onInterfaceMessage(const Message &message) { - const method_id_t methodId = message.getMethodId(); - return findDispatcherAndHandle(message, methodId); + virtual bool onInterfaceMessage(const Message &_message) { + const method_id_t itsMethod = _message.getMethodId(); + return findDispatcherAndHandle(_message, itsMethod); } - bool findDispatcherAndHandle(const Message &message, const method_id_t &methodId) { - auto findIterator = stubDispatcherTable_.find(methodId); + bool findDispatcherAndHandle(const Message &_message, const method_id_t &_method) { + auto findIterator = stubDispatcherTable_.find(_method); const bool foundInterfaceMemberHandler = (findIterator != stubDispatcherTable_.end()); bool isMessageHandled = false; // To prevent the destruction of the stub while still handling a message if (stub_ && foundInterfaceMemberHandler) { - StubDispatcher *stubDispatcher = findIterator->second; - isMessageHandled = stubDispatcher->dispatchMessage(message, stub_, getRemoteEventHandler(), getConnection()); + StubDispatcher *itsStubDispatcher = findIterator->second; + isMessageHandled = itsStubDispatcher->dispatchMessage(_message, stub_, getRemoteEventHandler(), getConnection()); if (!isMessageHandled) { - if (message.isRequestType()) { - auto error = message.createErrorResponseMessage(return_code_e::E_MALFORMED_MESSAGE); - connection_->sendMessage(error); + if (_message.isRequestType()) { + auto itsError = _message.createErrorResponseMessage(return_code_e::E_MALFORMED_MESSAGE); + connection_->sendMessage(itsError); } } return isMessageHandled; } - return StubAdapterHelper::findDispatcherAndHandle(message, methodId); + return StubAdapterHelper::findDispatcherAndHandle(_message, _method); } template - void addStubDispatcher(method_id_t methodId, + void addStubDispatcher(method_id_t _method, StubDispatcher* _stubDispatcher) { - addStubDispatcher(methodId, _stubDispatcher, identity()); + addStubDispatcher(_method, _stubDispatcher, identity()); } template @@ -178,17 +177,17 @@ class StubAdapterHelper: private: template - void addStubDispatcher(method_id_t methodId, + void addStubDispatcher(method_id_t _method, StubDispatcher* _stubDispatcher, identity) { - StubAdapterHelper::addStubDispatcher(methodId, _stubDispatcher); + StubAdapterHelper::addStubDispatcher(_method, _stubDispatcher); } - void addStubDispatcher(method_id_t methodId, + void addStubDispatcher(method_id_t _method, StubDispatcher* _stubDispatcher, identity) { - stubDispatcherTable_.insert({methodId, _stubDispatcher}); + stubDispatcherTable_.insert({_method, _stubDispatcher}); } @@ -221,20 +220,20 @@ struct StubEventHelper> { const std::shared_ptr &_connection, const InArgs_&... _in) { - Message message = Message::createNotificationMessage(_address, _event, false); + Message itsMessage = Message::createNotificationMessage(_address, _event, false); if (sizeof...(InArgs_) > 0) { - OutputStream output(message, _isLittleEndian); + OutputStream output(itsMessage, _isLittleEndian); if (!SerializableArguments::serialize(output, _in...)) { COMMONAPI_ERROR("StubEventHelper (someip): serialization failed! [", - message.getServiceId(), ".", - message.getInstanceId(), ".", - message.getMethodId()); + itsMessage.getServiceId(), ".", + itsMessage.getInstanceId(), ".", + itsMessage.getMethodId()); return false; } output.flush(); } - return _connection->sendEvent(message); + return _connection->sendEvent(itsMessage); } template @@ -255,21 +254,21 @@ struct StubEventHelper> { const event_id_t &_event, const bool _isLittleEndian, const InArgs_&... _in) { - Message message = Message::createNotificationMessage( + Message itsMessage = Message::createNotificationMessage( _stub.getSomeIpAddress(), _event, false); if (sizeof...(InArgs_) > 0) { - OutputStream output(message, _isLittleEndian); + OutputStream output(itsMessage, _isLittleEndian); if (!SerializableArguments::serialize(output, _in...)) { COMMONAPI_ERROR("StubEventHelper (someip) 2: serialization failed! [", - message.getServiceId(), ".", - message.getInstanceId(), ".", - message.getMethodId()); + itsMessage.getServiceId(), ".", + itsMessage.getInstanceId(), ".", + itsMessage.getMethodId()); return false; } output.flush(); } - return _stub.getConnection()->sendEvent(message, _client); + return _stub.getConnection()->sendEvent(itsMessage, _client); } }; @@ -313,9 +312,9 @@ class MethodStubDispatcher, DeplIn_> template inline bool dispatchMessageHelper(const Message &_message, - const std::shared_ptr &_stub, - RemoteEventHandlerType* _remoteEventHandler, - std::shared_ptr _connection, + const std::shared_ptr &_stub, + RemoteEventHandlerType* _remoteEventHandler, + std::shared_ptr _connection, index_sequence) { (void)_remoteEventHandler; (void)_connection; @@ -334,11 +333,11 @@ class MethodStubDispatcher, DeplIn_> } } - std::shared_ptr client - = std::make_shared(_message.getClientId(), _message.getUid(), _message.getGid()); + std::shared_ptr itsClientId + = std::make_shared(_message.getClientId(), _message.getSecClient(), _message.getEnv()); (_stub.get()->*stubFunctor_)( - client, + itsClientId, std::move(std::get(in))... ); @@ -368,7 +367,7 @@ class MethodWithReplyStubDispatcher< Out_, DeplIn_, DeplOut_> : - public StubDispatcher { + public StubDispatcher { public: typedef typename StubClass_::RemoteEventHandlerType RemoteEventHandlerType; typedef std::function ReplyType_t; @@ -405,10 +404,10 @@ class MethodWithReplyStubDispatcher< const std::tuple...> _args = std::make_tuple()) { { std::lock_guard lock(mutex_); - auto message = pending_.find(_call); - if(message != pending_.end()) { - Message reply = message->second.createResponseMessage(); - pending_[_call] = reply; + auto itsMessage = pending_.find(_call); + if (itsMessage != pending_.end()) { + Message itsReply = itsMessage->second.createResponseMessage(); + pending_[_call] = itsReply; } else { return false; } @@ -443,8 +442,8 @@ class MethodWithReplyStubDispatcher< (void) _remoteEventHandler; if (!_message.isRequestType()) { - auto error = _message.createErrorResponseMessage(return_code_e::E_WRONG_MESSAGE_TYPE); - _connection->sendMessage(error); + auto itsError = _message.createErrorResponseMessage(return_code_e::E_WRONG_MESSAGE_TYPE); + _connection->sendMessage(itsError); return true; } @@ -462,14 +461,14 @@ class MethodWithReplyStubDispatcher< } } - std::shared_ptr client - = std::make_shared(_message.getClientId(), _message.getUid(), _message.getGid()); + std::shared_ptr itsClientId + = std::make_shared(_message.getClientId(), _message.getSecClient(), _message.getEnv()); - CommonAPI::CallId_t call; + CommonAPI::CallId_t itsCall; { std::lock_guard lock(mutex_); - call = currentCall_++; - pending_[call] = _message; + itsCall = currentCall_++; + pending_[itsCall] = _message; } // Call the stub function with the list of deserialized in-Parameters @@ -478,11 +477,11 @@ class MethodWithReplyStubDispatcher< // calling the send function. std::weak_ptr itsConnection = _connection; (_stub.get()->*stubFunctor_)( - client, + itsClientId, std::move(std::get(in).getValue())..., - [call, itsConnection, this](OutArgs_... _args) { + [itsCall, itsConnection, this](OutArgs_... _args) { this->sendReplyMessage( - call, + itsCall, itsConnection, std::make_tuple( CommonAPI::Deployable( @@ -524,7 +523,7 @@ class MethodWithReplyStubDispatcher< return false; } bool isSuccessful = false; - if(auto itsConnection = _connection.lock()) { + if (auto itsConnection = _connection.lock()) { isSuccessful = itsConnection->sendMessage(reply->second); } pending_.erase(_call); @@ -600,11 +599,11 @@ class MethodWithReplyStubDispatcher< const std::tuple...>& _args) { { std::lock_guard lock(this->mutex_); - auto message = this->pending_.find(_call); - if(message != this->pending_.end()) { + auto itsMessage = this->pending_.find(_call); + if (itsMessage != this->pending_.end()) { // TODO create error response message - Message reply = message->second.createResponseMessage(); - this->pending_[_call] = reply; + Message itsReply = itsMessage->second.createResponseMessage(); + this->pending_[_call] = itsReply; } else { return false; } @@ -645,14 +644,14 @@ class MethodWithReplyStubDispatcher< } } - std::shared_ptr client - = std::make_shared(_message.getClientId(), _message.getUid(), _message.getGid()); + std::shared_ptr itsClientId + = std::make_shared(_message.getClientId(), _message.getSecClient(), _message.getEnv()); - CommonAPI::CallId_t call; + CommonAPI::CallId_t itsCall; { std::lock_guard lock(this->mutex_); - call = this->currentCall_++; - this->pending_[call] = _message; + itsCall = this->currentCall_++; + this->pending_[itsCall] = _message; } // Call the stub function with the list of deserialized in-Parameters @@ -661,12 +660,12 @@ class MethodWithReplyStubDispatcher< // calling the send function. std::weak_ptr itsConnection = _connection; (_stub.get()->*stubFunctor_)( - client, - call, + itsClientId, + itsCall, std::move(std::get(in).getValue())..., - [call, itsConnection, this](OutArgs_... _args) { + [itsCall, itsConnection, this](OutArgs_... _args) { this->sendReplyMessage( - call, + itsCall, itsConnection, std::make_tuple( CommonAPI::Deployable( @@ -689,17 +688,17 @@ class MethodWithReplyStubDispatcher< (void)_args; std::lock_guard lock(this->mutex_); - auto reply = this->pending_.find(_call); - if (reply != this->pending_.end()) { + auto itsReply = this->pending_.find(_call); + if (itsReply != this->pending_.end()) { if (sizeof...(DeplOutArgs_) > 0) { - OutputStream output(reply->second, this->isLittleEndian_); + OutputStream output(itsReply->second, this->isLittleEndian_); if (!SerializableArguments...>::serialize( output, std::get(_args)...)) { COMMONAPI_ERROR("MethodWithReplyStubDispatcher w/ error replies" "(someip): serialization failed! [", - reply.getServiceId(), ".", - reply.getInstanceId(), ".", - reply.getMethodId(), "]"); + itsReply.getServiceId(), ".", + itsReply.getInstanceId(), ".", + itsReply.getMethodId(), "]"); this->pending_.erase(_call); return false; } @@ -710,7 +709,7 @@ class MethodWithReplyStubDispatcher< } bool isSuccessful = false; if(auto itsConnection = _connection.lock()) { - isSuccessful = itsConnection->sendMessage(reply->second); + isSuccessful = itsConnection->sendMessage(itsReply->second); } this->pending_.erase(_call); return isSuccessful; @@ -736,8 +735,8 @@ class MethodWithReplyAdapterDispatcher, InArgs_..., OutArgs_&...); typedef typename CommonAPI::Stub StubType; - MethodWithReplyAdapterDispatcher(StubFunctor_ stubFunctor, const bool _isLittleEndian, const bool _isImplemented) - : stubFunctor_(stubFunctor), isLittleEndian_(_isLittleEndian), isImplemented_(_isImplemented) { + MethodWithReplyAdapterDispatcher(StubFunctor_ _stubFunctor, const bool _isLittleEndian, const bool _isImplemented) + : stubFunctor_(_stubFunctor), isLittleEndian_(_isLittleEndian), isImplemented_(_isImplemented) { } bool dispatchMessage(const Message &_message, @@ -787,27 +786,27 @@ class MethodWithReplyAdapterDispatcher client - = std::make_shared(_message.getClientId(), _message.getUid(), _message.getGid()); + std::shared_ptr itsClientId + = std::make_shared(_message.getClientId(), _message.getSecClient(), _message.getEnv()); - (_stub->StubType::getStubAdapter().get()->*stubFunctor_)(client, std::move(std::get(_argTuple))..., std::get(_argTuple)...); - Message reply = _message.createResponseMessage(); + (_stub->StubType::getStubAdapter().get()->*stubFunctor_)(itsClientId, std::move(std::get(_argTuple))..., std::get(_argTuple)...); + Message itsReply = _message.createResponseMessage(); if (sizeof...(OutArgs_) > 0) { - OutputStream outputStream(reply, isLittleEndian_); + OutputStream outputStream(itsReply, isLittleEndian_); if (!SerializableArguments::serialize(outputStream, std::get(_argTuple)...)) { COMMONAPI_ERROR("MethodWithReplyAdapterDispatcher (someip) " " serialization failed! [", - reply.getServiceId(), ".", - reply.getInstanceId(), ".", - reply.getMethodId(), "]"); + itsReply.getServiceId(), ".", + itsReply.getInstanceId(), ".", + itsReply.getMethodId(), "]"); return false; } outputStream.flush(); } - return _connection->sendMessage(reply); + return _connection->sendMessage(itsReply); } StubFunctor_ stubFunctor_; @@ -833,34 +832,34 @@ class GetAttributeStubDispatcher: public StubDispatcher { depl_(_depl) { } - bool dispatchMessage(const Message &message, const std::shared_ptr &stub, - RemoteEventHandlerType* _remoteEventHandler, - std::shared_ptr _connection) { + bool dispatchMessage(const Message &_message, const std::shared_ptr &_stub, + RemoteEventHandlerType* _remoteEventHandler, + std::shared_ptr _connection) { if (!this->isImplemented_) return false; (void) _remoteEventHandler; - return sendAttributeValueReply(message, stub, _connection); + return sendAttributeValueReply(_message, _stub, _connection); } protected: - inline bool sendAttributeValueReply(const Message &message, const std::shared_ptr& stub, - std::shared_ptr _connection) { + inline bool sendAttributeValueReply(const Message &_message, const std::shared_ptr &_stub, + std::shared_ptr _connection) { - Message reply = message.createResponseMessage(); - OutputStream outputStream(reply, isLittleEndian_); + Message itsReply = _message.createResponseMessage(); + OutputStream outputStream(itsReply, isLittleEndian_); - std::shared_ptr clientId - = std::make_shared(message.getClientId(), message.getUid(), message.getGid()); + std::shared_ptr itsClientId + = std::make_shared(_message.getClientId(), _message.getSecClient(), _message.getEnv()); - (stub.get()->*lockStubFunctor_)(true); - auto deployable = CommonAPI::Deployable((stub.get()->*getStubFunctor_)(clientId), depl_); - (stub.get()->*lockStubFunctor_)(false); + (_stub.get()->*lockStubFunctor_)(true); + auto deployable = CommonAPI::Deployable((_stub.get()->*getStubFunctor_)(itsClientId), depl_); + (_stub.get()->*lockStubFunctor_)(false); outputStream << deployable; outputStream.flush(); - return _connection->sendMessage(reply); + return _connection->sendMessage(itsReply); } LockStubFunctor lockStubFunctor_; @@ -891,13 +890,13 @@ class SetAttributeStubDispatcher: public GetAttributeStubDispatcher &stub, + bool dispatchMessage(const Message &_message, const std::shared_ptr &_stub, RemoteEventHandlerType* _remoteEventHandler, std::shared_ptr _connection) { if (!this->isImplemented_) return false; bool attributeValueChanged; - if (!setAttributeValue(message, stub, _remoteEventHandler, _connection, attributeValueChanged)) { + if (!setAttributeValue(_message, _stub, _remoteEventHandler, _connection, attributeValueChanged)) { return false; } @@ -909,38 +908,38 @@ class SetAttributeStubDispatcher: public GetAttributeStubDispatcher& stub, + inline bool setAttributeValue(const Message &_message, + const std::shared_ptr &_stub, RemoteEventHandlerType* _remoteEventHandler, std::shared_ptr _connection, - bool &attributeValueChanged) { - InputStream inputStream(message, this->isLittleEndian_); - CommonAPI::Deployable attributeValue(this->depl_); - inputStream >> attributeValue; + bool &_hasChanged) { + InputStream inputStream(_message, this->isLittleEndian_); + CommonAPI::Deployable itsValue(this->depl_); + inputStream >> itsValue; if (inputStream.hasError()) { COMMONAPI_ERROR("CommonAPI::SomeIP::SetAttributeStubDispatcher" " deserialization failed! [", - message.getServiceId(), ".", - message.getInstanceId(), ".", - message.getMethodId(), ".", - message.getSessionId(), "]"); + _message.getServiceId(), ".", + _message.getInstanceId(), ".", + _message.getMethodId(), ".", + _message.getSessionId(), "]"); return false; } - std::shared_ptr clientId - = std::make_shared(message.getClientId(), message.getUid(), message.getGid()); + std::shared_ptr itsClientId + = std::make_shared(_message.getClientId(), _message.getSecClient(), _message.getEnv()); - attributeValueChanged = (_remoteEventHandler->*onRemoteSetFunctor_)(clientId, std::move(attributeValue.getValue())); + _hasChanged = (_remoteEventHandler->*onRemoteSetFunctor_)(itsClientId, std::move(itsValue.getValue())); - return this->sendAttributeValueReply(message, stub, _connection); + return this->sendAttributeValueReply(_message, _stub, _connection); } inline void notifyOnRemoteChanged(RemoteEventHandlerType* _remoteEventHandler) { (_remoteEventHandler->*onRemoteChangedFunctor_)(); } - inline const AttributeType_& getAttributeValue(std::shared_ptr clientId, const std::shared_ptr &stub) { - return (stub.get()->*(this->getStubFunctor_))(clientId); + inline const AttributeType_& getAttributeValue(std::shared_ptr _clientId, const std::shared_ptr &_stub) { + return (_stub.get()->*(this->getStubFunctor_))(_clientId); } const OnRemoteSetFunctor onRemoteSetFunctor_; @@ -974,21 +973,21 @@ class SetObservableAttributeStubDispatcher: public SetAttributeStubDispatcher &stub, + bool dispatchMessage(const Message &_message, const std::shared_ptr &_stub, RemoteEventHandlerType* _remoteEventHandler, std::shared_ptr _connection) { if (!this->isImplemented_) return false; - bool attributeValueChanged; - if (!this->setAttributeValue(message, stub, _remoteEventHandler, _connection, attributeValueChanged)) { + bool hasChanged; + if (!this->setAttributeValue(_message, _stub, _remoteEventHandler, _connection, hasChanged)) { return false; } - if (attributeValueChanged) { - std::shared_ptr clientId - = std::make_shared(message.getClientId(), message.getUid(), message.getGid()); - fireAttributeValueChanged(clientId, stub); + if (hasChanged) { + std::shared_ptr itsClientId + = std::make_shared(_message.getClientId(), _message.getSecClient(), _message.getEnv()); + fireAttributeValueChanged(itsClientId, _stub); this->notifyOnRemoteChanged(_remoteEventHandler); } return true; diff --git a/include/CommonAPI/SomeIP/Types.hpp b/include/CommonAPI/SomeIP/Types.hpp index 72d6ba4..39aa438 100644 --- a/include/CommonAPI/SomeIP/Types.hpp +++ b/include/CommonAPI/SomeIP/Types.hpp @@ -44,12 +44,13 @@ typedef int64_t ms_t; typedef vsomeip::uid_t uid_t; typedef vsomeip::gid_t gid_t; +typedef vsomeip_sec_client_t sec_client_t; typedef uint32_t AvailabilityHandlerId_t; typedef std::function, service_id_t, instance_id_t, bool, void*)> AvailabilityHandler_t; -typedef std::function SubscriptionHandler_t; +typedef std::function SubscriptionHandler_t; typedef std::function SubscriptionAcceptedHandler_t; -typedef std::function AsyncSubscriptionHandler_t; +typedef std::function AsyncSubscriptionHandler_t; typedef std::uint32_t session_id_fake_t; diff --git a/include/CommonAPI/SomeIP/Watch.hpp b/include/CommonAPI/SomeIP/Watch.hpp index 1ba7201..7fc2cae 100644 --- a/include/CommonAPI/SomeIP/Watch.hpp +++ b/include/CommonAPI/SomeIP/Watch.hpp @@ -10,10 +10,11 @@ #ifndef COMMONAPI_SOMEIP_WATCH_HPP_ #define COMMONAPI_SOMEIP_WATCH_HPP_ +#include +#include #include -#include #include -#include +#include #include @@ -27,8 +28,9 @@ namespace SomeIP { class Connection; struct QueueEntry; -class Watch : public CommonAPI::Watch { - public: +class Watch + : public CommonAPI::Watch { +public: Watch(const std::shared_ptr& _connection); @@ -64,6 +66,7 @@ class Watch : public CommonAPI::Watch { #else int eventFd_; #endif + void supervise(); pollfd pollFileDescriptor_; std::vector dependentDispatchSources_; @@ -81,6 +84,17 @@ class Watch : public CommonAPI::Watch { const std::uint64_t eventFdValue_; #endif + + std::mutex lastProcessingMutex_; + std::chrono::steady_clock::time_point lastProcessing_; + + std::shared_ptr supervisor_; + bool is_supervising_; + std::mutex superviseMutex_; + std::condition_variable superviseCondition_; + + std::int64_t max_processing_time_; + std::size_t max_queue_size_; }; } // namespace IntraP diff --git a/libcommonapi_someip.yaml b/libcommonapi_someip.yaml new file mode 100644 index 0000000..899a772 --- /dev/null +++ b/libcommonapi_someip.yaml @@ -0,0 +1,6 @@ +- name: libcommonapi_someip + version: 3.2.3 + vendor: Lynx Team + license: + concluded: CLOSED and MPLv2 + declared: MPLv2 diff --git a/src/CommonAPI/SomeIP/AddressTranslator.cpp b/src/CommonAPI/SomeIP/AddressTranslator.cpp index c0e3ded..97adeed 100644 --- a/src/CommonAPI/SomeIP/AddressTranslator.cpp +++ b/src/CommonAPI/SomeIP/AddressTranslator.cpp @@ -14,17 +14,14 @@ #include #include -#include #include #include +#include #include namespace CommonAPI { namespace SomeIP { -const char *COMMONAPI_SOMEIP_DEFAULT_CONFIG_FILE = "commonapi-someip.ini"; -const char *COMMONAPI_SOMEIP_DEFAULT_CONFIG_FOLDER = "/etc/"; - #ifdef _WIN32 CRITICAL_SECTION critSec; #endif @@ -44,22 +41,6 @@ AddressTranslator::init() { #ifdef _WIN32 InitializeCriticalSection(&critSec); #endif - // Determine default configuration file - const char *config = getenv("COMMONAPI_SOMEIP_CONFIG"); - if (config) { - defaultConfig_ = config; - struct stat s; - if (stat(defaultConfig_.c_str(), &s) != 0) { - COMMONAPI_ERROR("Failed to load ini file passed via " - "COMMONAPI_SOMEIP_CONFIG environment: ", defaultConfig_); - } - } else { - defaultConfig_ = COMMONAPI_SOMEIP_DEFAULT_CONFIG_FOLDER; - defaultConfig_ += "/"; - defaultConfig_ += COMMONAPI_SOMEIP_DEFAULT_CONFIG_FILE; - } - - (void)readConfiguration(); } AddressTranslator::~AddressTranslator() @@ -161,17 +142,17 @@ AddressTranslator::insert( "Added address mapping: ", address, " <--> ", someipAddress); } else if(bw != backwards_.end() && bw->second != _address) { #ifdef COMMONAPI_ENABLE_ADDRESS_ALIASES - COMMONAPI_WARNING("Trying to overwrite existing SomeIP address: ", someipAddress); - COMMONAPI_WARNING("Existing CommonAPI address: ", _address); - COMMONAPI_WARNING("Setting alias: ", _address, " --> ", bw->second); + COMMONAPI_INFO("Trying to overwrite existing SomeIP address: ", someipAddress); + COMMONAPI_INFO("Existing CommonAPI address: ", _address); + COMMONAPI_INFO("Setting alias: ", _address, " --> ", bw->second); others_[_address] = bw->second; #else - COMMONAPI_ERROR("Trying to overwrite existing SomeIP address which is " + COMMONAPI_WARNING("Trying to overwrite existing SomeIP address which is " "already mapped to a CommonAPI address: ", someipAddress, " <--> ", _address); #endif // COMMONAPI_ENABLE_ADDRESS_ALIASES } else if(fw != forwards_.end() && fw->second != someipAddress) { - COMMONAPI_ERROR("Trying to overwrite existing CommonAPI address which is " + COMMONAPI_WARNING("Trying to overwrite existing CommonAPI address which is " "already mapped to a SomeIP address: ", _address, " <--> ", someipAddress); } @@ -181,97 +162,6 @@ AddressTranslator::insert( } } -bool -AddressTranslator::readConfiguration() { -#define MAX_PATH_LEN 255 - std::string config; - bool tryLoadConfig(true); - char currentDirectory[MAX_PATH_LEN]; -#ifdef _WIN32 - if (GetCurrentDirectory(MAX_PATH_LEN, currentDirectory)) { -#else - if (getcwd(currentDirectory, MAX_PATH_LEN)) { -#endif - config = currentDirectory; - config += "/"; - config += COMMONAPI_SOMEIP_DEFAULT_CONFIG_FILE; - - struct stat s; - if (stat(config.c_str(), &s) != 0) { - config = defaultConfig_; - if (stat(config.c_str(), &s) != 0) { - tryLoadConfig = false; - } - } - } - - IniFileReader reader; - if (tryLoadConfig && !reader.load(config)) - return false; - - for (auto itsSection : reader.getSections()) { - if (itsSection.first == "aliases") { - for (auto itsMapping : itsSection.second->getMappings()) { - if (itsMapping.first.find("service:") == 0) { - readServiceAlias(itsMapping.first.substr(8), itsMapping.second); - } else if (itsMapping.first.find("method:") == 0) { - readMethodAlias(itsMapping.first.substr(7), itsMapping.second); - } else if (itsMapping.first.find("event:") == 0) { - readMethodAlias(itsMapping.first.substr(6), itsMapping.second); - } else if (itsMapping.first.find("eventgroup:") == 0) { - readEventgroupAlias(itsMapping.first.substr(11), itsMapping.second); - } else { - COMMONAPI_ERROR("Found invalid alias configuration entry: ", itsMapping.first); - } - } - } else { - service_id_t service; - std::string serviceEntry = itsSection.second->getValue("service"); - - std::stringstream converter; - if (0 == serviceEntry.find("0x")) { - converter << std::hex << serviceEntry.substr(2); - } else { - converter << std::dec << serviceEntry; - } - converter >> service; - - instance_id_t instance; - std::string instanceEntry = itsSection.second->getValue("instance"); - - converter.str(""); - converter.clear(); - if (0 == instanceEntry.find("0x")) { - converter << std::hex << instanceEntry.substr(2); - } else { - converter << std::dec << instanceEntry; - } - converter >> instance; - - major_version_t major_version(0); - std::uint32_t major_temp(0); - minor_version_t minor_version(0); - - std::string majorEntry = itsSection.second->getValue("major"); - converter.str(""); - converter.clear(); - converter << std::dec << majorEntry; - converter >> major_temp; - major_version = static_cast(major_temp); - - std::string minorEntry = itsSection.second->getValue("minor"); - converter.str(""); - converter.clear(); - converter << std::dec << minorEntry; - converter >> minor_version; - - insert(itsSection.first, service, instance, major_version, minor_version); - } - } - - return true; -} - bool AddressTranslator::isValidService(const service_id_t _service) const { if (_service < MIN_SERVICE_ID || _service > MAX_SERVICE_ID) { @@ -294,230 +184,5 @@ AddressTranslator::isValidInstance(const instance_id_t _instance) const { return true; } -bool -AddressTranslator::isValidMethod(const method_id_t _method) const { - if (_method < MIN_METHOD_ID || _method > MAX_METHOD_ID) { - COMMONAPI_ERROR( - "Found invalid method identifier (", _method, ")"); - return false; - } - - return true; -} - -bool -AddressTranslator::isValidEventgroup(const eventgroup_id_t _eventgroup) const { - if (_eventgroup < MIN_EVENTGROUP_ID || _eventgroup > MAX_EVENTGROUP_ID) { - COMMONAPI_ERROR( - "Found invalid eventgroup identifier (", _eventgroup, ")"); - return false; - } - - return true; -} - -const Address & -AddressTranslator::getAddressAlias(const Address &_address) const { - auto foundAddress = aliases_.find(_address); - if (foundAddress != aliases_.end()) - return std::get<0>(foundAddress->second); - return _address; -} - -method_id_t -AddressTranslator::getMethodAlias(const Address &_address, const method_id_t _method) const { - auto foundAddress = aliases_.find(_address); - if (foundAddress != aliases_.end()) { - auto foundMethod = std::get<1>(foundAddress->second).find(_method); - if (foundMethod != std::get<1>(foundAddress->second).end()) - return foundMethod->second; - } - return _method; -} - -eventgroup_id_t -AddressTranslator::getEventgroupAlias(const Address &_address, const eventgroup_id_t _eventgroup) const { - auto foundAddress = aliases_.find(_address); - if (foundAddress != aliases_.end()) { - auto foundEventgroup = std::get<2>(foundAddress->second).find(_eventgroup); - if (foundEventgroup != std::get<2>(foundAddress->second).end()) - return foundEventgroup->second; - } - return _eventgroup; -} - -void -AddressTranslator::readServiceAlias(const std::string &_source, const std::string &_target) { - Address itsSourceAddress, itsTargetAddress; - method_id_t itsDummy; - - if (readValue(_source, itsSourceAddress, itsDummy, false) && - readValue(_target, itsTargetAddress, itsDummy, false)) { - - auto findService = aliases_.find(itsSourceAddress); - if (findService == aliases_.end()) { - Alias_t itsTarget = std::make_tuple(itsTargetAddress, MethodAlias_t(), EventgroupAlias_t()); - aliases_.insert(std::make_pair(itsSourceAddress, itsTarget)); - } else { - if (itsTargetAddress != std::get<0>(findService->second)) { - COMMONAPI_ERROR("Found multiple aliases for address ", itsSourceAddress); - } - } - } -} - -void -AddressTranslator::readMethodAlias(const std::string &_source, const std::string &_target) { - Address itsSourceAddress, itsTargetAddress; - method_id_t itsSourceMethod, itsTargetMethod; - - if (readValue(_source, itsSourceAddress, itsSourceMethod, true) && - readValue(_target, itsTargetAddress, itsTargetMethod, true)) { - if (isValidMethod(itsSourceMethod) && isValidMethod(itsTargetMethod)) { - auto findService = aliases_.find(itsSourceAddress); - if (findService == aliases_.end()) { - MethodAlias_t itsMethods; - itsMethods.insert(std::make_pair(itsSourceMethod, itsTargetMethod)); - Alias_t itsTarget = std::make_tuple(itsTargetAddress, itsMethods, EventgroupAlias_t()); - aliases_.insert(std::make_pair(itsSourceAddress, itsTarget)); - } else { - if (itsTargetAddress == std::get<0>(findService->second)) { - auto findMethod = std::get<1>(findService->second).find(itsSourceMethod); - if (findMethod == std::get<1>(findService->second).end()) { - std::get<1>(findService->second).insert(std::make_pair(itsSourceMethod, itsTargetMethod)); - } else { - if (findMethod->second != itsTargetMethod) { - COMMONAPI_ERROR("Found multiple aliases for method ", itsSourceAddress, ".", itsSourceMethod); - } - } - } else { - COMMONAPI_ERROR("Found multiple aliases for address ", itsSourceAddress); - } - } - } - } -} - -void -AddressTranslator::readEventgroupAlias(const std::string &_source, const std::string &_target) { - Address itsSourceAddress, itsTargetAddress; - method_id_t itsSourceEventgroup, itsTargetEventgroup; - - if (readValue(_source, itsSourceAddress, itsSourceEventgroup, true) && - readValue(_target, itsTargetAddress, itsTargetEventgroup, true)) { - if (isValidEventgroup(itsSourceEventgroup) && isValidEventgroup(itsTargetEventgroup)) { - auto findService = aliases_.find(itsSourceAddress); - if (findService == aliases_.end()) { - EventgroupAlias_t itsEventgroups; - itsEventgroups.insert(std::make_pair(itsSourceEventgroup, itsTargetEventgroup)); - Alias_t itsTarget = std::make_tuple(itsTargetAddress, MethodAlias_t(), itsEventgroups); - aliases_.insert(std::make_pair(itsSourceAddress, itsTarget)); - } else { - if (itsTargetAddress == std::get<0>(findService->second)) { - auto findEventgroup = std::get<2>(findService->second).find(itsSourceEventgroup); - if (findEventgroup == std::get<2>(findService->second).end()) { - std::get<2>(findService->second).insert(std::make_pair(itsSourceEventgroup, itsTargetEventgroup)); - } else { - if (findEventgroup->second != itsTargetEventgroup) { - COMMONAPI_ERROR("Found multiple aliases for method ", itsSourceAddress, ".", itsSourceEventgroup); - } - } - } else { - COMMONAPI_ERROR("Found multiple aliases for address ", itsSourceAddress); - } - } - } - } -} - -bool -AddressTranslator::readValue(const std::string &_data, - Address &_address, uint16_t &_id, bool _readId) { - - std::string itsServiceStr, itsInstanceStr, itsMajorStr("1"), itsMinorStr("0"); - std::string itsIdStr("0xFFFF"), itsTempStr; - - auto foundService = _data.find(':'); - if (foundService == std::string::npos) { - return false; - } - - itsServiceStr = _data.substr(0, foundService); - - auto foundInstance = _data.find(':', foundService+1); - itsInstanceStr = _data.substr(foundService+1, foundInstance-foundService-1); - - if (foundService != std::string::npos) { - auto foundMajor = _data.find(':', foundInstance+1); - itsTempStr = _data.substr(foundInstance+1, foundMajor-foundInstance-1); - - if (foundMajor != std::string::npos) { - itsMajorStr = itsTempStr; - - auto foundMinor = _data.find(':', foundMajor+1); - itsMinorStr = _data.substr(foundMajor+1, foundMinor-foundMajor-1); - - if (foundMinor != std::string::npos) { - itsIdStr = _data.substr(foundMinor+1); - } - } else { - if (_readId) { - itsIdStr = itsTempStr; - } - } - } else if (_readId) { - return false; - } - - service_id_t itsService(0); - instance_id_t itsInstance(0); - major_version_t itsMajor(0); - minor_version_t itsMinor(0); - - { - std::stringstream itsConverter; - if (itsServiceStr.find("0x") == 0) itsConverter << std::hex; - itsConverter << itsServiceStr; - itsConverter >> itsService; - } - - { - std::stringstream itsConverter; - if (itsInstanceStr.find("0x") == 0) itsConverter << std::hex; - itsConverter << itsInstanceStr; - itsConverter >> itsInstance; - } - - { - std::stringstream itsConverter; - if (itsMajorStr.find("0x") == 0) itsConverter << std::hex; - itsConverter << itsMajorStr; - int itsTempMajor(0); - itsConverter >> itsTempMajor; - itsMajor = major_version_t(itsTempMajor); - } - - { - std::stringstream itsConverter; - if (itsMinorStr.find("0x") == 0) itsConverter << std::hex; - itsConverter << itsMinorStr; - itsConverter >> itsMinor; - } - - { - std::stringstream itsConverter; - if (itsIdStr.find("0x") == 0) itsConverter << std::hex; - itsConverter << itsIdStr; - itsConverter >> _id; - } - - _address.setService(itsService); - _address.setInstance(itsInstance); - _address.setMajorVersion(itsMajor); - _address.setMinorVersion(itsMinor); - - return true; -} - } // namespace SomeIP } // namespace CommonAPI diff --git a/src/CommonAPI/SomeIP/ClientId.cpp b/src/CommonAPI/SomeIP/ClientId.cpp index e116bb4..dd3084a 100644 --- a/src/CommonAPI/SomeIP/ClientId.cpp +++ b/src/CommonAPI/SomeIP/ClientId.cpp @@ -5,7 +5,9 @@ #include +#include #include +#include #include namespace std { @@ -23,8 +25,26 @@ struct hash { namespace CommonAPI { namespace SomeIP { -ClientId::ClientId(client_id_t client_id, uid_t _uid, gid_t _gid) - : client_id_(client_id), uid_(_uid), gid_(_gid) { +ClientId::ClientId() + : client_id_ {0xffff}, + uid_ {0xffffffff}, + gid_ {0xffffffff} { +} + +ClientId::ClientId(client_id_t _client, + const vsomeip_sec_client_t *_sec_client, const std::string &_env) + : client_id_ {_client}, + uid_ {_sec_client ? _sec_client->user : 0xffffffff}, + gid_ {_sec_client ? _sec_client->group : 0xffffffff}, + env_(_env) { + + if (_sec_client) + hostAddress_ = addressToString(_sec_client->host); +} + +ClientId::ClientId(client_id_t _client, + const vsomeip_sec_client_t &_sec_client, const std::string &_env) + : ClientId(_client, &_sec_client, _env) { } ClientId::~ClientId() { @@ -60,5 +80,26 @@ gid_t ClientId::getGid() const { return gid_; } +std::string ClientId::getHostAddress() const { + return hostAddress_; +} + +std::string ClientId::getEnv() const { + return env_; +} + +std::shared_ptr +ClientId::getSomeIPClient(const std::shared_ptr _client) { + + std::shared_ptr client = std::dynamic_pointer_cast(_client); + + if (client == nullptr) + { + COMMONAPI_ERROR("CommonAPI::SomeIP::getSomeIPClient dynamic_pointer_cast returning nullptr."); + } + + return client; +} + } // namespace SomeIP } // namespace CommonAPI diff --git a/src/CommonAPI/SomeIP/Configuration.cpp b/src/CommonAPI/SomeIP/Configuration.cpp new file mode 100644 index 0000000..e6f2b2e --- /dev/null +++ b/src/CommonAPI/SomeIP/Configuration.cpp @@ -0,0 +1,419 @@ +// Copyright (C) 2014-2020 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// 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/. + +#ifdef _WIN32 +#include +#else +#include +#endif + +#include + +#include +#include +#include +#include +#include +#include +#include + +const char *COMMONAPI_SOMEIP_DEFAULT_CONFIG_FILE = "commonapi-someip.ini"; +const char *COMMONAPI_SOMEIP_DEFAULT_CONFIG_FOLDER = "/etc/"; + +namespace CommonAPI { +namespace SomeIP { + +std::shared_ptr Configuration::get() { + static auto itsConfiguration = std::make_shared(); + return itsConfiguration; +} + +void Configuration::load() { + Configuration::get()->readConfiguration(); +} + +Configuration::Configuration() { + // Determine default configuration file + const char *config = getenv("COMMONAPI_SOMEIP_CONFIG"); + if (config) { + defaultConfig_ = config; + struct stat s; + if (stat(defaultConfig_.c_str(), &s) != 0) { + COMMONAPI_ERROR("Failed to load ini file passed via " + "COMMONAPI_SOMEIP_CONFIG environment: ", defaultConfig_); + } + } else { + defaultConfig_ = COMMONAPI_SOMEIP_DEFAULT_CONFIG_FOLDER; + defaultConfig_ += "/"; + defaultConfig_ += COMMONAPI_SOMEIP_DEFAULT_CONFIG_FILE; + } +} + +const Address & +Configuration::getAddressAlias(const Address &_address) const { + auto foundAddress = aliases_.find(_address); + if (foundAddress != aliases_.end()) + return std::get<0>(foundAddress->second); + return _address; +} + +method_id_t +Configuration::getMethodAlias(const Address &_address, const method_id_t _method) const { + auto foundAddress = aliases_.find(_address); + if (foundAddress != aliases_.end()) { + auto foundMethod = std::get<1>(foundAddress->second).find(_method); + if (foundMethod != std::get<1>(foundAddress->second).end()) + return foundMethod->second; + } + return _method; +} + +eventgroup_id_t +Configuration::getEventgroupAlias(const Address &_address, const eventgroup_id_t _eventgroup) const { + auto foundAddress = aliases_.find(_address); + if (foundAddress != aliases_.end()) { + auto foundEventgroup = std::get<2>(foundAddress->second).find(_eventgroup); + if (foundEventgroup != std::get<2>(foundAddress->second).end()) + return foundEventgroup->second; + } + return _eventgroup; +} + +int64_t +Configuration::getMaxProcessingTime(const std::string &_name) const { + + const auto foundConnection = watchLimits_.find(_name); + if (foundConnection == watchLimits_.end()) + return DEFAULT_MAX_PROCESSING_TIME; + + + return foundConnection->second.first; +} + +std::size_t +Configuration::getMaxQueueSize(const std::string &_name) const { + + const auto foundConnection = watchLimits_.find(_name); + if (foundConnection == watchLimits_.end()) + return DEFAULT_MAX_QUEUE_SIZE; + + return foundConnection->second.second; +} + + +void +Configuration::readConfiguration() { +#define MAX_PATH_LEN 4095 + std::string config; + bool tryLoadConfig(true); + char currentDirectory[MAX_PATH_LEN]; +#ifdef _WIN32 + if (GetCurrentDirectory(MAX_PATH_LEN, currentDirectory)) { +#else + if (getcwd(currentDirectory, MAX_PATH_LEN)) { +#endif + config = currentDirectory; + config += "/"; + config += COMMONAPI_SOMEIP_DEFAULT_CONFIG_FILE; + + struct stat s; + if (stat(config.c_str(), &s) != 0) { + config = defaultConfig_; + if (stat(config.c_str(), &s) != 0) { + tryLoadConfig = false; + } + } + } + + IniFileReader reader; + if (tryLoadConfig && !reader.load(config)) + return; + + COMMONAPI_INFO("Loading configuration file ", config); + + auto itsAddressTranslator = AddressTranslator::get(); + + for (auto itsSection : reader.getSections()) { + if (itsSection.first == "aliases") { + for (auto itsMapping : itsSection.second->getMappings()) { + if (itsMapping.first.find("service:") == 0) { + readServiceAlias(itsMapping.first.substr(8), itsMapping.second); + } else if (itsMapping.first.find("method:") == 0) { + readMethodAlias(itsMapping.first.substr(7), itsMapping.second); + } else if (itsMapping.first.find("event:") == 0) { + readMethodAlias(itsMapping.first.substr(6), itsMapping.second); + } else if (itsMapping.first.find("eventgroup:") == 0) { + readEventgroupAlias(itsMapping.first.substr(11), itsMapping.second); + } else { + COMMONAPI_ERROR("Found invalid alias configuration entry: ", itsMapping.first); + } + } + } else if (itsSection.first.find("connection:") == 0) { + auto i = itsSection.first.find(":"); + std::string itsConnectionName(itsSection.first.substr(i+1, itsSection.first.length())); + std::int64_t itsMaxProcessingTime; + std::size_t itsMaxQueueSize; + + std::string itsValue = itsSection.second->getValue("max-processing-time"); + if (itsValue.empty()) { + itsMaxProcessingTime = DEFAULT_MAX_PROCESSING_TIME; + } else { + std::stringstream itsConverter; + itsConverter << itsValue; + itsConverter >> std::dec >> itsMaxProcessingTime; + } + + itsValue = itsSection.second->getValue("max-queue-size"); + if (itsValue.empty()) { + itsMaxQueueSize = DEFAULT_MAX_QUEUE_SIZE; + } else { + std::stringstream itsConverter; + itsConverter << itsValue; + itsConverter >> std::dec >> itsMaxQueueSize; + } + watchLimits_[itsConnectionName] = std::make_pair(itsMaxProcessingTime, itsMaxQueueSize); + } else { + service_id_t service; + std::string serviceEntry = itsSection.second->getValue("service"); + + std::stringstream converter; + if (0 == serviceEntry.find("0x")) { + converter << std::hex << serviceEntry.substr(2); + } else { + converter << std::dec << serviceEntry; + } + converter >> service; + + instance_id_t instance; + std::string instanceEntry = itsSection.second->getValue("instance"); + + converter.str(""); + converter.clear(); + if (0 == instanceEntry.find("0x")) { + converter << std::hex << instanceEntry.substr(2); + } else { + converter << std::dec << instanceEntry; + } + converter >> instance; + + major_version_t major_version(0); + std::uint32_t major_temp(0); + minor_version_t minor_version(0); + + std::string majorEntry = itsSection.second->getValue("major"); + converter.str(""); + converter.clear(); + converter << std::dec << majorEntry; + converter >> major_temp; + major_version = static_cast(major_temp); + + std::string minorEntry = itsSection.second->getValue("minor"); + converter.str(""); + converter.clear(); + converter << std::dec << minorEntry; + converter >> minor_version; + + itsAddressTranslator->insert(itsSection.first, service, instance, major_version, minor_version); + } + } +} + +void +Configuration::readServiceAlias(const std::string &_source, const std::string &_target) { + Address itsSourceAddress, itsTargetAddress; + method_id_t itsDummy; + + if (readValue(_source, itsSourceAddress, itsDummy, false) && + readValue(_target, itsTargetAddress, itsDummy, false)) { + + auto findService = aliases_.find(itsSourceAddress); + if (findService == aliases_.end()) { + Alias_t itsTarget = std::make_tuple(itsTargetAddress, MethodAlias_t(), EventgroupAlias_t()); + aliases_.insert(std::make_pair(itsSourceAddress, itsTarget)); + } else { + if (itsTargetAddress != std::get<0>(findService->second)) { + COMMONAPI_ERROR("Found multiple aliases for address ", itsSourceAddress); + } + } + } +} + +void +Configuration::readMethodAlias(const std::string &_source, const std::string &_target) { + Address itsSourceAddress, itsTargetAddress; + method_id_t itsSourceMethod, itsTargetMethod; + + if (readValue(_source, itsSourceAddress, itsSourceMethod, true) && + readValue(_target, itsTargetAddress, itsTargetMethod, true)) { + if (isValidMethod(itsSourceMethod) && isValidMethod(itsTargetMethod)) { + auto findService = aliases_.find(itsSourceAddress); + if (findService == aliases_.end()) { + MethodAlias_t itsMethods; + itsMethods.insert(std::make_pair(itsSourceMethod, itsTargetMethod)); + Alias_t itsTarget = std::make_tuple(itsTargetAddress, itsMethods, EventgroupAlias_t()); + aliases_.insert(std::make_pair(itsSourceAddress, itsTarget)); + } else { + if (itsTargetAddress == std::get<0>(findService->second)) { + auto findMethod = std::get<1>(findService->second).find(itsSourceMethod); + if (findMethod == std::get<1>(findService->second).end()) { + std::get<1>(findService->second).insert(std::make_pair(itsSourceMethod, itsTargetMethod)); + } else { + if (findMethod->second != itsTargetMethod) { + COMMONAPI_ERROR("Found multiple aliases for method ", itsSourceAddress, ".", itsSourceMethod); + } + } + } else { + COMMONAPI_ERROR("Found multiple aliases for address ", itsSourceAddress); + } + } + } + } +} + +void +Configuration::readEventgroupAlias(const std::string &_source, const std::string &_target) { + Address itsSourceAddress, itsTargetAddress; + method_id_t itsSourceEventgroup, itsTargetEventgroup; + + if (readValue(_source, itsSourceAddress, itsSourceEventgroup, true) && + readValue(_target, itsTargetAddress, itsTargetEventgroup, true)) { + if (isValidEventgroup(itsSourceEventgroup) && isValidEventgroup(itsTargetEventgroup)) { + auto findService = aliases_.find(itsSourceAddress); + if (findService == aliases_.end()) { + EventgroupAlias_t itsEventgroups; + itsEventgroups.insert(std::make_pair(itsSourceEventgroup, itsTargetEventgroup)); + Alias_t itsTarget = std::make_tuple(itsTargetAddress, MethodAlias_t(), itsEventgroups); + aliases_.insert(std::make_pair(itsSourceAddress, itsTarget)); + } else { + if (itsTargetAddress == std::get<0>(findService->second)) { + auto findEventgroup = std::get<2>(findService->second).find(itsSourceEventgroup); + if (findEventgroup == std::get<2>(findService->second).end()) { + std::get<2>(findService->second).insert(std::make_pair(itsSourceEventgroup, itsTargetEventgroup)); + } else { + if (findEventgroup->second != itsTargetEventgroup) { + COMMONAPI_ERROR("Found multiple aliases for method ", itsSourceAddress, ".", itsSourceEventgroup); + } + } + } else { + COMMONAPI_ERROR("Found multiple aliases for address ", itsSourceAddress); + } + } + } + } +} + +bool +Configuration::readValue(const std::string &_data, + Address &_address, uint16_t &_id, bool _readId) { + + std::string itsServiceStr, itsInstanceStr, itsMajorStr("1"), itsMinorStr("0"); + std::string itsIdStr("0xFFFF"), itsTempStr; + + auto foundService = _data.find(':'); + if (foundService == std::string::npos) { + return false; + } + + itsServiceStr = _data.substr(0, foundService); + + auto foundInstance = _data.find(':', foundService+1); + itsInstanceStr = _data.substr(foundService+1, foundInstance-foundService-1); + + if (foundService != std::string::npos) { + auto foundMajor = _data.find(':', foundInstance+1); + itsTempStr = _data.substr(foundInstance+1, foundMajor-foundInstance-1); + + if (foundMajor != std::string::npos) { + itsMajorStr = itsTempStr; + + auto foundMinor = _data.find(':', foundMajor+1); + itsMinorStr = _data.substr(foundMajor+1, foundMinor-foundMajor-1); + + if (foundMinor != std::string::npos) { + itsIdStr = _data.substr(foundMinor+1); + } + } else { + if (_readId) { + itsIdStr = itsTempStr; + } + } + } else if (_readId) { + return false; + } + + service_id_t itsService(0); + instance_id_t itsInstance(0); + major_version_t itsMajor(0); + minor_version_t itsMinor(0); + + { + std::stringstream itsConverter; + if (itsServiceStr.find("0x") == 0) itsConverter << std::hex; + itsConverter << itsServiceStr; + itsConverter >> itsService; + } + + { + std::stringstream itsConverter; + if (itsInstanceStr.find("0x") == 0) itsConverter << std::hex; + itsConverter << itsInstanceStr; + itsConverter >> itsInstance; + } + + { + std::stringstream itsConverter; + if (itsMajorStr.find("0x") == 0) itsConverter << std::hex; + itsConverter << itsMajorStr; + int itsTempMajor(0); + itsConverter >> itsTempMajor; + itsMajor = major_version_t(itsTempMajor); + } + + { + std::stringstream itsConverter; + if (itsMinorStr.find("0x") == 0) itsConverter << std::hex; + itsConverter << itsMinorStr; + itsConverter >> itsMinor; + } + + { + std::stringstream itsConverter; + if (itsIdStr.find("0x") == 0) itsConverter << std::hex; + itsConverter << itsIdStr; + itsConverter >> _id; + } + + _address.setService(itsService); + _address.setInstance(itsInstance); + _address.setMajorVersion(itsMajor); + _address.setMinorVersion(itsMinor); + + return true; +} + +bool +Configuration::isValidMethod(const method_id_t _method) const { + if (_method < MIN_METHOD_ID || _method > MAX_METHOD_ID) { + COMMONAPI_ERROR( + "Found invalid method identifier (", _method, ")"); + return false; + } + + return true; +} + +bool +Configuration::isValidEventgroup(const eventgroup_id_t _eventgroup) const { + if (_eventgroup < MIN_EVENTGROUP_ID || _eventgroup > MAX_EVENTGROUP_ID) { + COMMONAPI_ERROR( + "Found invalid eventgroup identifier (", _eventgroup, ")"); + return false; + } + + return true; +} + +} // namespace SomeIP +} // namespace CommonAPI diff --git a/src/CommonAPI/SomeIP/Connection.cpp b/src/CommonAPI/SomeIP/Connection.cpp index 9ff0b75..caad05f 100644 --- a/src/CommonAPI/SomeIP/Connection.cpp +++ b/src/CommonAPI/SomeIP/Connection.cpp @@ -412,6 +412,11 @@ Connection::~Connection() { } } +std::string +Connection::getName() const { + return application_->get_name(); +} + bool Connection::attachMainLoopContext(std::weak_ptr mainLoopContext) { if (mainLoopContext_.lock() == mainLoopContext.lock()) return true; @@ -436,35 +441,57 @@ bool Connection::attachMainLoopContext(std::weak_ptr mainLoopCo } bool Connection::connect(bool) { + if (!application_->init()) - return false; + return (false); - std::function connectionHandler = std::bind(&Connection::onConnectionEvent, - shared_from_this(), - std::placeholders::_1); + std::function connectionHandler + = std::bind(&Connection::onConnectionEvent, shared_from_this(), + std::placeholders::_1); application_->register_state_handler(connectionHandler); - asyncAnswersCleanupThread_ = std::make_shared(&Connection::cleanup, this); - dispatchThread_ = std::make_shared(&Connection::dispatch, this); - return true; + asyncAnswersCleanupThread_ = std::make_shared( + &Connection::cleanup, shared_from_this()); + dispatchThread_ = std::make_shared( + &Connection::dispatch, shared_from_this()); + + return (true); } void Connection::doDisconnect() { if (asyncAnswersCleanupThread_) { + bool isCleanupThread(std::this_thread::get_id() + == asyncAnswersCleanupThread_->get_id()); + + if (isCleanupThread) + asyncAnswersCleanupThread_->detach(); + { std::lock_guard lg(cleanupMutex_); cleanupCancelled_ = true; cleanupCondition_.notify_one(); } - if (asyncAnswersCleanupThread_->joinable()) - asyncAnswersCleanupThread_->join(); + + if (!isCleanupThread) { + if (asyncAnswersCleanupThread_->joinable()) + asyncAnswersCleanupThread_->join(); + } } application_->stop(); - if(dispatchThread_) { - if (dispatchThread_->joinable()) - dispatchThread_->join(); + + if (dispatchThread_) { + bool isDispatchThread(std::this_thread::get_id() + == dispatchThread_->get_id()); + + if (isDispatchThread) { + dispatchThread_->detach(); + } else { + if (dispatchThread_->joinable()) + dispatchThread_->join(); + } } + application_->clear_all_handler(); { @@ -1181,7 +1208,7 @@ void Connection::queueSubscriptionStatusHandler(service_id_t serviceId, void Connection::registerSubscriptionHandler(const Address &_address, const eventgroup_id_t _eventgroup, AsyncSubscriptionHandler_t _handler) { - std::lock_guard itsLock(subscriptionMutex_); + std::lock_guard itsLock(subscriptionMutex_); subscription_[_address.getService()][_address.getInstance()][_eventgroup] = _handler; if (auto lockedContext = mainLoopContext_.lock()) { @@ -1192,15 +1219,16 @@ void Connection::registerSubscriptionHandler(const Address &_address, auto self = shared_from_this(); auto itsAsyncSubscriptionHandler = [this, self, _address, _eventgroup]( client_id_t _client, - uid_t _uid, gid_t _gid, + const vsomeip_sec_client_t *_sec_client, + const std::string &_env, bool _subscribe, SubscriptionAcceptedHandler_t _acceptedHandler) { // hooks must be called by the mainloop - proxyPushFunctionToMainLoop([this, _client, _uid, _gid, _subscribe, _acceptedHandler, _address, _eventgroup]() { + proxyPushFunctionToMainLoop([this, _client, _sec_client, _env, _subscribe, _acceptedHandler, _address, _eventgroup]() { AsyncSubscriptionHandler_t itsHandler; { - std::lock_guard itsLock(subscriptionMutex_); + std::lock_guard itsLock(subscriptionMutex_); auto foundService = subscription_.find(_address.getService()); if (foundService != subscription_.end()) { auto foundInstance = foundService->second.find(_address.getInstance()); @@ -1212,8 +1240,8 @@ void Connection::registerSubscriptionHandler(const Address &_address, } } } - if(itsHandler) { - itsHandler(_client, _uid, _gid, _subscribe, _acceptedHandler); + if (itsHandler) { + itsHandler(_client, _sec_client, _env, _subscribe, _acceptedHandler); } else { _acceptedHandler(true); } @@ -1228,7 +1256,7 @@ void Connection::registerSubscriptionHandler(const Address &_address, void Connection::unregisterSubscriptionHandler(const Address &_address, const eventgroup_id_t _eventgroup) { - std::lock_guard itsLock(subscriptionMutex_); + std::lock_guard itsLock(subscriptionMutex_); { auto foundService = subscription_.find(_address.getService()); if (foundService != subscription_.end()) { diff --git a/src/CommonAPI/SomeIP/Factory.cpp b/src/CommonAPI/SomeIP/Factory.cpp index 8dbbc87..2c128d1 100644 --- a/src/CommonAPI/SomeIP/Factory.cpp +++ b/src/CommonAPI/SomeIP/Factory.cpp @@ -18,6 +18,7 @@ namespace SomeIP { INITIALIZER(FactoryInit) { Factory::runtime_ = Runtime::get(); Factory::runtime_.lock()->registerFactory("someip", Factory::get()); + Configuration::load(); } DEINITIALIZER(FactoryDeinit) { @@ -297,8 +298,8 @@ Factory::unregisterStub(const std::string &_domain, if (adapterResult == services_.end()) { servicesMutex_.unlock(); - COMMONAPI_INFO("Deregistering stub for \"", _domain, ":", _interface, - ":", _instance, "\" failed (Not registered)."); + COMMONAPI_WARNING("Deregistering stub for \"", _domain, ":", _interface, + ":", _instance, "\" failed (Not registered or already unregistered)."); return false; } diff --git a/src/CommonAPI/SomeIP/InputStream.cpp b/src/CommonAPI/SomeIP/InputStream.cpp index 46e0457..99edb52 100644 --- a/src/CommonAPI/SomeIP/InputStream.cpp +++ b/src/CommonAPI/SomeIP/InputStream.cpp @@ -52,7 +52,9 @@ byte_t *InputStream::_readRaw(const size_t _size) { } InputStream& InputStream::readValue(bool &_value, const EmptyDeployment *) { - errorOccurred_ = _readBitValue(_value, 8, false); + uint8_t itsValue; + errorOccurred_ = _readBitValue(itsValue, 8, false); + _value = ((itsValue & 0x1u) == 0x1u); // SIP_RPC_817 return (*this); } diff --git a/src/CommonAPI/SomeIP/Message.cpp b/src/CommonAPI/SomeIP/Message.cpp index 1062415..d109157 100644 --- a/src/CommonAPI/SomeIP/Message.cpp +++ b/src/CommonAPI/SomeIP/Message.cpp @@ -3,8 +3,10 @@ // 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 namespace CommonAPI { namespace SomeIP { @@ -184,6 +186,12 @@ bool Message::isValidCRC() const { return message_->is_valid_crc(); } +std::string Message::getHostAddress() const { + + return addressToString( + message_->get_sec_client().host); +} + uid_t Message::getUid() const { return message_->get_uid(); } @@ -192,5 +200,13 @@ gid_t Message::getGid() const { return message_->get_gid(); } +sec_client_t Message::getSecClient() const { + return message_->get_sec_client(); +} + +std::string Message::getEnv() const { + return message_->get_env(); +} + } // namespace SomeIP } // namespace CommonAPI diff --git a/src/CommonAPI/SomeIP/OutputStream.cpp b/src/CommonAPI/SomeIP/OutputStream.cpp index 9499d32..c7969b6 100644 --- a/src/CommonAPI/SomeIP/OutputStream.cpp +++ b/src/CommonAPI/SomeIP/OutputStream.cpp @@ -49,7 +49,7 @@ size_t OutputStream::popPosition() { } OutputStream& OutputStream::writeValue(const bool &_value, const EmptyDeployment *) { - return _writeBitValue(_value, 8, false); + return _writeBitValue(_value ? 0x1u : 0x0u, 8, false); } OutputStream& OutputStream::writeValue(const int8_t &_value, const EmptyDeployment *) { diff --git a/src/CommonAPI/SomeIP/Proxy.cpp b/src/CommonAPI/SomeIP/Proxy.cpp index 27a84a4..22e6091 100644 --- a/src/CommonAPI/SomeIP/Proxy.cpp +++ b/src/CommonAPI/SomeIP/Proxy.cpp @@ -9,9 +9,10 @@ #include #include #include +#include #include #include -#include +//#include namespace CommonAPI { namespace SomeIP { @@ -253,7 +254,7 @@ Proxy::Proxy(const Address &_address, const std::shared_ptr &connection) : ProxyBase(connection), address_(_address), - alias_(AddressTranslator::get()->getAddressAlias(_address)), + alias_(Configuration::get()->getAddressAlias(_address)), proxyStatusEvent_(this), availabilityStatus_(AvailabilityStatus::UNKNOWN), availabilityHandlerId_(0), diff --git a/src/CommonAPI/SomeIP/ProxyBase.cpp b/src/CommonAPI/SomeIP/ProxyBase.cpp index b1508e8..a215620 100644 --- a/src/CommonAPI/SomeIP/ProxyBase.cpp +++ b/src/CommonAPI/SomeIP/ProxyBase.cpp @@ -3,9 +3,9 @@ // 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 namespace CommonAPI { @@ -14,12 +14,12 @@ namespace SomeIP { ProxyBase::ProxyBase(const std::shared_ptr< ProxyConnection > &connection) : commonApiDomain_("local"), connection_(connection), - addressTranslator_(AddressTranslator::get()) { + configuration_(Configuration::get()) { } Message ProxyBase::createMethodCall(const method_id_t _method, bool _reliable) const { return Message::createMethodCall(getSomeIpAlias(), - AddressTranslator::get()->getMethodAlias(getSomeIpAddress(), _method), _reliable); + configuration_->getMethodAlias(getSomeIpAddress(), _method), _reliable); } void ProxyBase::addEventHandler( @@ -31,12 +31,12 @@ void ProxyBase::addEventHandler( reliability_type_e reliabilityType, std::weak_ptr eventHandler, major_version_t major) { - event_id_t itsEventId = AddressTranslator::get()->getMethodAlias(getSomeIpAddress(), eventId); + event_id_t itsEventId = configuration_->getMethodAlias(getSomeIpAddress(), eventId); { std::lock_guard itsLock(eventHandlerAddedMutex_); eventHandlerAdded_.insert(itsEventId); } - eventgroup_id_t itsEventGroupId = AddressTranslator::get()->getEventgroupAlias(getSomeIpAddress(), eventGroupId); + eventgroup_id_t itsEventGroupId = configuration_->getEventgroupAlias(getSomeIpAddress(), eventGroupId); connection_->addEventHandler(serviceId, instanceId, itsEventGroupId, itsEventId, eventHandler, major, eventType); connection_->requestEvent(serviceId, instanceId, itsEventId, itsEventGroupId, @@ -52,7 +52,7 @@ void ProxyBase::removeEventHandler( major_version_t major, minor_version_t minor) { bool found(false); - event_id_t itsEventId = AddressTranslator::get()->getMethodAlias(getSomeIpAddress(), eventId); + event_id_t itsEventId = configuration_->getMethodAlias(getSomeIpAddress(), eventId); { std::lock_guard itsLock(eventHandlerAddedMutex_); if (eventHandlerAdded_.find(itsEventId) != eventHandlerAdded_.end()) { @@ -61,7 +61,7 @@ void ProxyBase::removeEventHandler( } } if (found) { - eventgroup_id_t itsEventGroupId = AddressTranslator::get()->getEventgroupAlias(getSomeIpAddress(), eventGroupId); + eventgroup_id_t itsEventGroupId = configuration_->getEventgroupAlias(getSomeIpAddress(), eventGroupId); connection_->releaseEvent(serviceId, instanceId, itsEventId); connection_->removeEventHandler(serviceId, instanceId, itsEventGroupId, itsEventId, eventHandler, major, minor); } @@ -74,8 +74,8 @@ void ProxyBase::registerEvent( eventgroup_id_t eventGroupId, event_type_e eventType, reliability_type_e reliabilityType) { - event_id_t itsEventId = AddressTranslator::get()->getMethodAlias(getSomeIpAddress(), eventId); - eventgroup_id_t itsEventGroupId = AddressTranslator::get()->getEventgroupAlias(getSomeIpAddress(), eventGroupId); + event_id_t itsEventId = configuration_->getMethodAlias(getSomeIpAddress(), eventId); + eventgroup_id_t itsEventGroupId = configuration_->getEventgroupAlias(getSomeIpAddress(), eventGroupId); connection_->requestEvent(serviceId, instanceId, itsEventId, itsEventGroupId, eventType, reliabilityType); } @@ -84,7 +84,7 @@ void ProxyBase::unregisterEvent( service_id_t serviceId, instance_id_t instanceId, event_id_t eventId) { - event_id_t itsEventId = AddressTranslator::get()->getMethodAlias(getSomeIpAddress(), eventId); + event_id_t itsEventId = configuration_->getMethodAlias(getSomeIpAddress(), eventId); connection_->releaseEvent(serviceId, instanceId, itsEventId); } @@ -96,8 +96,8 @@ void ProxyBase::subscribe( std::weak_ptr eventHandler, uint32_t tag, major_version_t major) { - event_id_t itsEventId = AddressTranslator::get()->getMethodAlias(getSomeIpAddress(), eventId); - eventgroup_id_t itsEventGroupId = AddressTranslator::get()->getEventgroupAlias(getSomeIpAddress(), eventGroupId); + event_id_t itsEventId = configuration_->getMethodAlias(getSomeIpAddress(), eventId); + eventgroup_id_t itsEventGroupId = configuration_->getEventgroupAlias(getSomeIpAddress(), eventGroupId); connection_->subscribe(serviceId, instanceId, itsEventGroupId, itsEventId, eventHandler, tag, major); } diff --git a/src/CommonAPI/SomeIP/Watch.cpp b/src/CommonAPI/SomeIP/Watch.cpp index 09c5a06..af0376b 100644 --- a/src/CommonAPI/SomeIP/Watch.cpp +++ b/src/CommonAPI/SomeIP/Watch.cpp @@ -3,10 +3,13 @@ // 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 #ifdef _WIN32 #include @@ -27,13 +30,14 @@ namespace CommonAPI { namespace SomeIP { -Watch::Watch(const std::shared_ptr& _connection) : +Watch::Watch(const std::shared_ptr &_connection) : #ifdef _WIN32 - pipeValue_(4) + pipeValue_(4), #else eventFd_(0), - eventFdValue_(1) + eventFdValue_(1), #endif + lastProcessing_() { #ifdef _WIN32 WSADATA wsaData; @@ -169,9 +173,25 @@ Watch::Watch(const std::shared_ptr& _connection) : pollFileDescriptor_.events = POLLIN; connection_ = _connection; + + auto itsConfiguration = Configuration::get(); + max_processing_time_ = itsConfiguration->getMaxProcessingTime(_connection->getName()); + max_queue_size_ = itsConfiguration->getMaxQueueSize(_connection->getName()); + + is_supervising_ = (max_processing_time_ > 0 || max_queue_size_ > 0); + supervisor_ = std::make_shared( + std::bind(&Watch::supervise, this)); } Watch::~Watch() { + { + std::lock_guard itsLock(superviseMutex_); + is_supervising_ = false; + superviseCondition_.notify_one(); + } + if (supervisor_ && supervisor_->joinable()) + supervisor_->join(); + #ifdef _WIN32 // shutdown the connection since no more data will be sent int iResult = shutdown(pipeFileDescriptors_[0], SD_SEND); @@ -226,7 +246,16 @@ void Watch::removeDependentDispatchSource(CommonAPI::DispatchSource* _dispatchSo void Watch::pushQueue(std::shared_ptr _queueEntry) { { - std::unique_lock itsLock(queueMutex_); + std::lock_guard itsLock(lastProcessingMutex_); + // Record the time when the first entry is queued so that the supervisor can detect + // when the main loop becomes blocked. + if (!lastProcessing_.time_since_epoch().count()) { + lastProcessing_ = std::chrono::steady_clock::now(); + } + } + + { + std::lock_guard itsLock(queueMutex_); queue_.push(_queueEntry); } @@ -282,26 +311,84 @@ void Watch::popQueue() { #endif { - std::unique_lock itsLock(queueMutex_); + std::lock_guard itsLock(queueMutex_); queue_.pop(); } } std::shared_ptr Watch::frontQueue() { - std::unique_lock itsLock(queueMutex_); + std::lock_guard itsLock(queueMutex_); return queue_.front(); } bool Watch::emptyQueue() { - std::unique_lock itsLock(queueMutex_); + std::lock_guard itsLock(queueMutex_); return queue_.empty(); } void Watch::processQueueEntry(std::shared_ptr _queueEntry) { - if(auto connection = connection_.lock()) + if (auto connection = connection_.lock()) { _queueEntry->process(connection); + + std::lock_guard itsLock(lastProcessingMutex_); + lastProcessing_ = std::chrono::steady_clock::now(); + } +} + +void Watch::supervise() { + { + auto itsConnection = connection_.lock(); + if (itsConnection) { + COMMONAPI_INFO("Supervising watch[", itsConnection->getName(), "] --> (", + max_processing_time_, ", ", max_queue_size_, ")"); + } else { + COMMONAPI_WARNING("Supervising watch[] --> (", + max_processing_time_, ", ", max_queue_size_, ")"); + } + } + + std::unique_lock itsSuperviseLock(superviseMutex_); + while (is_supervising_) { + if (!emptyQueue()) { + std::chrono::milliseconds itsDuration; + std::size_t itsQueueSize; + + { + std::lock_guard itsLock(lastProcessingMutex_); + itsDuration = std::chrono::duration_cast( + std::chrono::steady_clock::now() - lastProcessing_); + } + { + std::lock_guard itsLock(queueMutex_); + itsQueueSize = queue_.size(); + } + + if (0 < max_processing_time_ + && itsDuration.count() > max_processing_time_) { + + std::stringstream itsMessage; + itsMessage << "Mainloop did not process a message for " + << itsDuration.count() << "ms (#elements=" + << itsQueueSize << ")"; + + COMMONAPI_WARNING(itsMessage.str()); + } else if (0 < max_queue_size_ + && itsQueueSize > max_queue_size_) { + + std::stringstream itsMessage; + itsMessage << "Mainloop watch contains " + << itsQueueSize << " elements." + << " Maybe processing is too slow."; + + COMMONAPI_WARNING(itsMessage.str()); + } + } + + if (is_supervising_) + superviseCondition_.wait_for(itsSuperviseLock, std::chrono::seconds(1)); + } } } // namespace SomeIP