From fcead99a9c35abdb5dc042213d0567b799d1991f Mon Sep 17 00:00:00 2001 From: Juergen Gehring Date: Mon, 19 Jun 2017 07:55:26 -0700 Subject: [PATCH] CommonAPI-SomeIP 3.1.12 --- CHANGES | 5 + CMakeLists.txt | 8 +- include/CommonAPI/SomeIP/Address.hpp | 4 +- .../CommonAPI/SomeIP/AddressTranslator.hpp | 21 ++ include/CommonAPI/SomeIP/Attribute.hpp | 2 - include/CommonAPI/SomeIP/Connection.hpp | 55 ++- include/CommonAPI/SomeIP/Constants.hpp | 7 + include/CommonAPI/SomeIP/Event.hpp | 108 ++---- include/CommonAPI/SomeIP/InputStream.hpp | 4 +- include/CommonAPI/SomeIP/Message.hpp | 3 + include/CommonAPI/SomeIP/OutputStream.hpp | 2 +- include/CommonAPI/SomeIP/Proxy.hpp | 8 +- .../SomeIP/ProxyAsyncCallbackHandler.hpp | 12 +- include/CommonAPI/SomeIP/ProxyBase.hpp | 36 +- include/CommonAPI/SomeIP/ProxyConnection.hpp | 24 +- include/CommonAPI/SomeIP/ProxyHelper.hpp | 5 + include/CommonAPI/SomeIP/SelectiveEvent.hpp | 8 +- include/CommonAPI/SomeIP/StringEncoder.hpp | 20 +- .../SomeIP/SubscriptionStatusWrapper.hpp | 65 ++++ src/CommonAPI/SomeIP/Address.cpp | 24 +- src/CommonAPI/SomeIP/AddressTranslator.cpp | 331 +++++++++++++++--- src/CommonAPI/SomeIP/Connection.cpp | 249 ++++++------- src/CommonAPI/SomeIP/Message.cpp | 6 + src/CommonAPI/SomeIP/OutputStream.cpp | 21 +- src/CommonAPI/SomeIP/Proxy.cpp | 40 +-- src/CommonAPI/SomeIP/ProxyBase.cpp | 72 ++-- src/CommonAPI/SomeIP/StringEncoder.cpp | 18 +- src/CommonAPI/SomeIP/StubManager.cpp | 8 + .../SomeIP/SubscriptionStatusWrapper.cpp | 87 +++++ 29 files changed, 816 insertions(+), 437 deletions(-) create mode 100644 include/CommonAPI/SomeIP/SubscriptionStatusWrapper.hpp create mode 100644 src/CommonAPI/SomeIP/SubscriptionStatusWrapper.cpp diff --git a/CHANGES b/CHANGES index 398032e..cd5420b 100644 --- a/CHANGES +++ b/CHANGES @@ -1,5 +1,10 @@ Changes ======= +v3.1.12 +- set CommonAPI CallStatus if wrong CRC value was received +- consider version in address translation for SOME/IP +- added backwards compatibility for splitted / merged service inferfaces + v3.1.11.4 - Fixed potential busy loop for mainloop applications diff --git a/CMakeLists.txt b/CMakeLists.txt index aa30f96..d5a82ed 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 1) -set (LIBCOMMONAPI_SOMEIP_PATCH_VERSION 11) +set (LIBCOMMONAPI_SOMEIP_PATCH_VERSION 12) message(STATUS "Project name: ${PROJECT_NAME}") @@ -119,9 +119,9 @@ endforeach () ################################################################################################### if ("${USE_INSTALLED_COMMONAPI}" STREQUAL "ON") - FIND_PACKAGE(CommonAPI 3.1.11 REQUIRED CONFIG NO_CMAKE_PACKAGE_REGISTRY) + FIND_PACKAGE(CommonAPI 3.1.12 REQUIRED CONFIG NO_CMAKE_PACKAGE_REGISTRY) else() - FIND_PACKAGE(CommonAPI 3.1.11 REQUIRED CONFIG NO_SYSTEM_ENVIRONMENT_PATH NO_CMAKE_SYSTEM_PATH) + FIND_PACKAGE(CommonAPI 3.1.12 REQUIRED CONFIG NO_SYSTEM_ENVIRONMENT_PATH NO_CMAKE_SYSTEM_PATH) endif() message(STATUS "CommonAPI_CONSIDERED_CONFIGS: ${CommonAPI_CONSIDERED_CONFIGS}") @@ -132,7 +132,7 @@ message(STATUS "CommonAPI Version: ${CommonAPI_VERSION}") find_package( Boost 1.54 COMPONENTS system thread log REQUIRED ) include_directories( ${Boost_INCLUDE_DIR} ) -find_package (vsomeip 2.6.0 REQUIRED) +find_package (vsomeip 2.7.0 REQUIRED) message(STATUS "vsomeip version: ${vsomeip_VERSION}") include_directories ( diff --git a/include/CommonAPI/SomeIP/Address.hpp b/include/CommonAPI/SomeIP/Address.hpp index 0877e0d..c79961e 100644 --- a/include/CommonAPI/SomeIP/Address.hpp +++ b/include/CommonAPI/SomeIP/Address.hpp @@ -23,8 +23,8 @@ class COMMONAPI_EXPORT Address { public: Address(); Address(const service_id_t _service, const instance_id_t _instance, - major_version_t _major_version = DEFAULT_MAJOR_VERSION, - minor_version_t _minor_version = DEFAULT_MINOR_VERSION); + major_version_t _major_version = ANY_MAJOR_VERSION, + minor_version_t _minor_version = ANY_MINOR_VERSION); Address(const Address &_source); Address &operator=(const Address &_source); diff --git a/include/CommonAPI/SomeIP/AddressTranslator.hpp b/include/CommonAPI/SomeIP/AddressTranslator.hpp index 30b735a..8b67698 100644 --- a/include/CommonAPI/SomeIP/AddressTranslator.hpp +++ b/include/CommonAPI/SomeIP/AddressTranslator.hpp @@ -42,11 +42,27 @@ 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_; @@ -54,6 +70,11 @@ class AddressTranslator { std::map forwards_; std::map backwards_; + typedef std::map MethodAlias_t; + typedef std::map EventgroupAlias_t; + typedef std::tuple Alias_t; + std::map aliases_; + std::mutex mutex_; }; diff --git a/include/CommonAPI/SomeIP/Attribute.hpp b/include/CommonAPI/SomeIP/Attribute.hpp index 47255a6..65fdfcd 100644 --- a/include/CommonAPI/SomeIP/Attribute.hpp +++ b/include/CommonAPI/SomeIP/Attribute.hpp @@ -192,8 +192,6 @@ class ObservableAttribute: public AttributeType_ { _eventId, true, _isLittleEndian, - _getMethodId, - _getReliable, std::make_tuple(CommonAPI::Deployable(this->depl_))) { } diff --git a/include/CommonAPI/SomeIP/Connection.hpp b/include/CommonAPI/SomeIP/Connection.hpp index cdd3e16..3ec1823 100644 --- a/include/CommonAPI/SomeIP/Connection.hpp +++ b/include/CommonAPI/SomeIP/Connection.hpp @@ -22,6 +22,7 @@ #include #include #include +#include namespace CommonAPI { namespace SomeIP { @@ -76,13 +77,15 @@ struct ErrQueueEntry : QueueEntry { ErrQueueEntry(std::weak_ptr _eventHandler, uint16_t _errorCode, uint32_t _tag, service_id_t _service, instance_id_t _instance, - eventgroup_id_t _eventGroup) : + eventgroup_id_t _eventGroup, + event_id_t _event) : eventHandler_(_eventHandler), errorCode_(_errorCode), tag_(_tag), service_(_service), instance_(_instance), - eventGroup_(_eventGroup) {} + eventGroup_(_eventGroup), + event_(_event) {} virtual ~ErrQueueEntry() {} std::weak_ptr eventHandler_; @@ -91,6 +94,7 @@ struct ErrQueueEntry : QueueEntry { service_id_t service_; instance_id_t instance_; eventgroup_id_t eventGroup_; + event_id_t event_; void process(std::shared_ptr _connection); }; @@ -153,10 +157,6 @@ class Connection: eventgroup_id_t eventGroupId, event_id_t eventId, ProxyConnection::EventHandler* _eventHandler, major_version_t major, minor_version_t minor); - void subscribeForSelective(service_id_t serviceId, instance_id_t instanceId, - eventgroup_id_t eventGroupId, event_id_t eventId, - std::weak_ptr _eventHandler, uint32_t _tag, major_version_t major); - virtual bool attachMainLoopContext(std::weak_ptr); virtual bool isAvailable(const Address &_address); @@ -206,12 +206,6 @@ class Connection: virtual void queueSelectiveErrorHandler(service_id_t serviceId, instance_id_t instanceId); - virtual void subscribeForField(service_id_t serviceId, - instance_id_t instanceId, - eventgroup_id_t eventGroupId, - event_id_t eventId, - major_version_t major); - virtual void incrementConnection(); virtual void decrementConnection(); @@ -223,6 +217,11 @@ class Connection: virtual void getAvailableInstances(service_id_t _serviceId, std::vector *_instances); + void subscribe(service_id_t serviceId, instance_id_t instanceId, + eventgroup_id_t eventGroupId, event_id_t eventId, + std::weak_ptr _eventHandler, + uint32_t _tag, major_version_t major); + private: void receive(const std::shared_ptr &_message); void handleProxyReceive(const std::shared_ptr &_message); @@ -235,12 +234,21 @@ class Connection: void dispatch(); void cleanup(); - void addSelectiveErrorListener(service_id_t serviceId, + void addSubscriptionStatusListener(service_id_t serviceId, instance_id_t instanceId, - eventgroup_id_t eventGroupId); + eventgroup_id_t eventGroupId, + event_id_t _eventId); + + void queueSubscriptionStatusHandler(service_id_t serviceId, + instance_id_t instanceId); void doDisconnect(); + void insertSubscriptionStatusListener(service_id_t serviceId, instance_id_t instanceId, + eventgroup_id_t eventGroupId, event_id_t eventId, + std::weak_ptr eventHandler, + uint32_t _tag); + std::shared_ptr dispatchThread_; std::weak_ptr mainLoopContext_; @@ -284,13 +292,6 @@ class Connection: std::weak_ptr>>>> events_map_t; mutable events_map_t eventHandlers_; - typedef std::map>> subscription_counter_map_t; - - mutable subscription_counter_map_t subscriptionCounters_; - - mutable std::mutex availabilityMutex_; typedef std::map, std::set>>>>> selectiveErrorHandlers_; - - std::map, std::set>>>>> pendingSelectiveErrorHandlers_; + std::map, + std::shared_ptr> subscriptionStates_; std::mutex availabilityCalledMutex_; std::map> availabilityCalled_; diff --git a/include/CommonAPI/SomeIP/Constants.hpp b/include/CommonAPI/SomeIP/Constants.hpp index 373abaa..921bb68 100644 --- a/include/CommonAPI/SomeIP/Constants.hpp +++ b/include/CommonAPI/SomeIP/Constants.hpp @@ -23,6 +23,7 @@ namespace CommonAPI { namespace SomeIP { const method_id_t ANY_METHOD = vsomeip::ANY_METHOD; +const major_version_t ANY_MAJOR_VERSION = vsomeip::ANY_MAJOR; const minor_version_t ANY_MINOR_VERSION = vsomeip::ANY_MINOR; const major_version_t DEFAULT_MAJOR_VERSION = vsomeip::DEFAULT_MAJOR; @@ -37,6 +38,12 @@ const instance_id_t MAX_INSTANCE_ID = 0xFFFE; const ms_t ASYNC_MESSAGE_REPLY_TIMEOUT_MS = 5000; const ms_t ASYNC_MESSAGE_CLEANUP_INTERVAL_MS = 1000; +const method_id_t MIN_METHOD_ID = 0x0001; +const method_id_t MAX_METHOD_ID = 0xFFFE; + +const eventgroup_id_t MIN_EVENTGROUP_ID = 0x0001; +const eventgroup_id_t MAX_EVENTGROUP_ID = 0xFFFE; + static const CommonAPI::CallInfo defaultCallInfo(CommonAPI::DEFAULT_SEND_TIMEOUT_MS); } // namespace SomeIP diff --git a/include/CommonAPI/SomeIP/Event.hpp b/include/CommonAPI/SomeIP/Event.hpp index 666979a..b0b7c52 100644 --- a/include/CommonAPI/SomeIP/Event.hpp +++ b/include/CommonAPI/SomeIP/Event.hpp @@ -28,57 +28,30 @@ class Event: public Events_ { Event(ProxyBase &_proxy, const eventgroup_id_t _eventgroupId, const event_id_t _eventId, - bool _isField, - bool _isLittleEndian, - std::tuple _arguments) - : proxy_(_proxy), - handler_(std::make_shared(_proxy, this)), - serviceId_(_proxy.getSomeIpAddress().getService()), - instanceId_(_proxy.getSomeIpAddress().getInstance()), - eventId_(_eventId), - eventgroupId_(_eventgroupId), - isField_(_isField), - isLittleEndian_(_isLittleEndian), - getMethodId_(0), - getReliable_(false), - arguments_(_arguments) { - - proxy_.registerEvent(serviceId_, instanceId_, eventId_, eventgroupId_, isField_); - } - - Event(ProxyBase &_proxy, - const eventgroup_id_t _eventgroupId, - const event_id_t _eventId, - bool _isField, + const bool _isField, const bool _isLittleEndian, - const method_id_t _methodId, - const bool _getReliable, std::tuple _arguments) : proxy_(_proxy), - handler_(std::make_shared(_proxy, this)), - serviceId_(_proxy.getSomeIpAddress().getService()), - instanceId_(_proxy.getSomeIpAddress().getInstance()), + handler_(), + serviceId_(_proxy.getSomeIpAlias().getService()), + instanceId_(_proxy.getSomeIpAlias().getInstance()), eventId_(_eventId), eventgroupId_(_eventgroupId), isField_(_isField), isLittleEndian_(_isLittleEndian), - getMethodId_(_methodId), - getReliable_(_getReliable), arguments_(_arguments) { - proxy_.registerEvent(serviceId_, instanceId_, eventId_, eventgroupId_, isField_); } virtual ~Event() { - auto major = proxy_.getSomeIpAddress().getMajorVersion(); - auto minor = proxy_.getSomeIpAddress().getMinorVersion(); + auto major = proxy_.getSomeIpAlias().getMajorVersion(); + auto minor = proxy_.getSomeIpAlias().getMinorVersion(); proxy_.removeEventHandler(serviceId_, instanceId_, eventgroupId_, eventId_, handler_.get(), major, minor); proxy_.unregisterEvent(serviceId_, instanceId_, eventId_); } virtual void onError(const uint16_t _errorCode, const uint32_t _tag) { - (void) _errorCode; - (void) _tag; + this->notifySpecificError(_tag, static_cast(_errorCode)); } protected: @@ -88,35 +61,36 @@ class Event: public Events_ { public: Handler(ProxyBase&_proxy, Event* _event) : - proxy_(_proxy), + proxy_(_proxy.getWeakPtr()), event_(_event) { } virtual void onEventMessage(const Message &_message) { notificationMutex_.lock(); - event_->handleEventMessage(_message, typename make_sequence::type()); - notificationMutex_.unlock(); - } - - virtual void onInitialValueEventMessage(const Message&_message, const uint32_t tag) { - notificationMutex_.lock(); - event_->handleEventMessage(tag, _message, typename make_sequence::type()); + if (auto ptr = proxy_.lock()) { + event_->handleEventMessage(_message, typename make_sequence::type()); + } notificationMutex_.unlock(); } virtual void onError(const uint16_t _errorCode, const uint32_t _tag) { - event_->onError(_errorCode, _tag); + if (auto ptr = proxy_.lock()) { + event_->onError(_errorCode, _tag); + } } private : - ProxyBase& proxy_; + std::weak_ptr proxy_; Event* event_; std::mutex notificationMutex_; }; virtual void onFirstListenerAdded(const Listener&) { - auto major = proxy_.getSomeIpAddress().getMajorVersion(); + if (!handler_) { + handler_ = std::make_shared(proxy_, this); + } + auto major = proxy_.getSomeIpAlias().getMajorVersion(); proxy_.addEventHandler(serviceId_, instanceId_, eventgroupId_, eventId_, isField_, handler_, major); } @@ -127,15 +101,14 @@ class Event: public Events_ { listeners_.insert(_subscription); } - if (isField_) { - auto major = proxy_.getSomeIpAddress().getMajorVersion(); - proxy_.getInitialEvent(serviceId_, instanceId_, eventgroupId_, eventId_, major); - } + auto major = proxy_.getSomeIpAlias().getMajorVersion(); + proxy_.subscribe(serviceId_, instanceId_, eventgroupId_, eventId_, + handler_, _subscription, major); } virtual void onLastListenerRemoved(const Listener&) { - auto major = proxy_.getSomeIpAddress().getMajorVersion(); - auto minor = proxy_.getSomeIpAddress().getMinorVersion(); + auto major = proxy_.getSomeIpAlias().getMajorVersion(); + auto minor = proxy_.getSomeIpAlias().getMinorVersion(); proxy_.removeEventHandler(serviceId_, instanceId_, eventgroupId_, eventId_, handler_.get(), major, minor); } @@ -157,34 +130,29 @@ class Event: public Events_ { subscribers = listeners_; listeners_.clear(); } - for(auto const &subscription : subscribers) { - this->notifySpecificListener(subscription, std::get(arguments_)...); + if(!_message.isValidCRC()) { + this->notifySpecificError(subscription, CommonAPI::CallStatus::INVALID_VALUE); + } else { + this->notifySpecificListener(subscription, std::get(arguments_)...); + } } } else { - { - std::lock_guard itsLock(listeners_mutex_); - listeners_.clear(); + if(!_message.isValidCRC()) { + this->notifyErrorListeners(CommonAPI::CallStatus::INVALID_VALUE); + } else { + { + std::lock_guard itsLock(listeners_mutex_); + listeners_.clear(); + } + this->notifyListeners(std::get(arguments_)...); } - this->notifyListeners(std::get(arguments_)...); } } else { COMMONAPI_ERROR("CommonAPI::SomeIP::Event: deserialization failed!"); } } - template - inline void handleEventMessage(uint32_t _tag, const Message &_message, - index_sequence) { - InputStream InputStream(_message, isLittleEndian_); - if (SerializableArguments::deserialize( - InputStream, std::get(arguments_)...)) { - this->notifySpecificListener(_tag, std::get(arguments_)...); - } else { - COMMONAPI_ERROR("CommonAPI::SomeIP::Event: deserialization failed!"); - } - } - ProxyBase &proxy_; std::shared_ptr handler_; @@ -194,8 +162,6 @@ class Event: public Events_ { const eventgroup_id_t eventgroupId_; const bool isField_; const bool isLittleEndian_; - const method_id_t getMethodId_; - const bool getReliable_; std::tuple arguments_; std::mutex listeners_mutex_; std::set listeners_; diff --git a/include/CommonAPI/SomeIP/InputStream.hpp b/include/CommonAPI/SomeIP/InputStream.hpp index bee4c37..b1f1abd 100644 --- a/include/CommonAPI/SomeIP/InputStream.hpp +++ b/include/CommonAPI/SomeIP/InputStream.hpp @@ -480,10 +480,10 @@ class InputStream: public CommonAPI::InputStream { } value; std::memset(value.raw_, 0, sizeof(Type_)); - if (remaining_ < size_t(_bits >> 3)) { + if (_bits == 0 || remaining_ < size_t(((_bits - 1) >> 3) + 1)) { isError = true; } else { - if (currentBit_ == 0 && _bits == (sizeof(Type_) << 3)) { + if (currentBit_ == 0 && _bits == (sizeof(Type_) << 3) && current_ != NULL) { #if __BYTE_ORDER == __LITTLE_ENDIAN if (isLittleEndian) { std::memcpy(value.raw_, current_, sizeof(Type_)); diff --git a/include/CommonAPI/SomeIP/Message.hpp b/include/CommonAPI/SomeIP/Message.hpp index 4011dd0..1fbe8a8 100644 --- a/include/CommonAPI/SomeIP/Message.hpp +++ b/include/CommonAPI/SomeIP/Message.hpp @@ -66,6 +66,9 @@ class Message { COMMONAPI_EXPORT void setPayloadData(const byte_t *data, message_length_t length); + COMMONAPI_EXPORT bool isValidCRC() const; + + private: std::shared_ptr message_; diff --git a/include/CommonAPI/SomeIP/OutputStream.hpp b/include/CommonAPI/SomeIP/OutputStream.hpp index 76bfece..3fb891a 100644 --- a/include/CommonAPI/SomeIP/OutputStream.hpp +++ b/include/CommonAPI/SomeIP/OutputStream.hpp @@ -578,7 +578,7 @@ class OutputStream: public CommonAPI::OutputStream { Message message_; bool errorOccurred_; - std::stack positions_; + std::vector positions_; byte_t currentByte_; uint8_t currentBit_; diff --git a/include/CommonAPI/SomeIP/Proxy.hpp b/include/CommonAPI/SomeIP/Proxy.hpp index 86b6906..13734d9 100644 --- a/include/CommonAPI/SomeIP/Proxy.hpp +++ b/include/CommonAPI/SomeIP/Proxy.hpp @@ -64,15 +64,12 @@ class COMMONAPI_EXPORT_CLASS_EXPLICIT Proxy COMMONAPI_EXPORT virtual ProxyStatusEvent& getProxyStatusEvent(); COMMONAPI_EXPORT virtual InterfaceVersionAttribute& getInterfaceVersionAttribute(); - COMMONAPI_EXPORT virtual void getInitialEvent( - service_id_t serviceId, instance_id_t instanceId, - eventgroup_id_t eventGroupId, event_id_t eventId, - major_version_t major); - COMMONAPI_EXPORT static void notifySpecificListener(std::weak_ptr _proxy, const ProxyStatusEvent::Listener &_listener, const ProxyStatusEvent::Subscription _subscription); + COMMONAPI_EXPORT virtual const Address &getSomeIpAlias() const; + private: COMMONAPI_EXPORT Proxy(const Proxy&) = delete; @@ -86,6 +83,7 @@ class COMMONAPI_EXPORT_CLASS_EXPLICIT Proxy private: Address address_; + Address alias_; ProxyStatusEventHelper proxyStatusEvent_; diff --git a/include/CommonAPI/SomeIP/ProxyAsyncCallbackHandler.hpp b/include/CommonAPI/SomeIP/ProxyAsyncCallbackHandler.hpp index 2d686e4..4f20fa9 100644 --- a/include/CommonAPI/SomeIP/ProxyAsyncCallbackHandler.hpp +++ b/include/CommonAPI/SomeIP/ProxyAsyncCallbackHandler.hpp @@ -65,10 +65,14 @@ class ProxyAsyncCallbackHandler: public ProxyConnection::MessageReplyAsyncHandle CallStatus callStatus = _callStatus; if (callStatus == CallStatus::SUCCESS) { if (!message.isErrorType()) { - InputStream inputStream(message, isLittleEndian_); - const bool success = SerializableArguments< ArgTypes_... >::deserialize(inputStream, std::get< ArgIndices_ >(argTuple_)...); - if (!success) { - callStatus = CallStatus::REMOTE_ERROR; + if(!message.isValidCRC()) { + callStatus = CallStatus::INVALID_VALUE; + } else { + InputStream inputStream(message, isLittleEndian_); + const bool success = SerializableArguments< ArgTypes_... >::deserialize(inputStream, std::get< ArgIndices_ >(argTuple_)...); + if (!success) { + callStatus = CallStatus::REMOTE_ERROR; + } } } else { callStatus = CallStatus::REMOTE_ERROR; diff --git a/include/CommonAPI/SomeIP/ProxyBase.hpp b/include/CommonAPI/SomeIP/ProxyBase.hpp index ef56e04..16c321f 100644 --- a/include/CommonAPI/SomeIP/ProxyBase.hpp +++ b/include/CommonAPI/SomeIP/ProxyBase.hpp @@ -63,43 +63,33 @@ class COMMONAPI_EXPORT_CLASS_EXPLICIT ProxyBase major_version_t major, minor_version_t minor); - COMMONAPI_EXPORT virtual void getInitialEvent( + COMMONAPI_EXPORT virtual bool init() = 0; + + COMMONAPI_EXPORT void registerEvent( service_id_t serviceId, instance_id_t instanceId, - eventgroup_id_t eventGroupId, event_id_t eventId, - major_version_t major) = 0; + eventgroup_id_t eventGroupId, + bool isField); - COMMONAPI_EXPORT void subscribeForSelective( - service_id_t serviceId, - instance_id_t instanceId, - eventgroup_id_t eventGroupId, - event_id_t eventId, - std::weak_ptr eventHandler, - uint32_t _tag, - major_version_t major); + COMMONAPI_EXPORT void unregisterEvent( + service_id_t serviceId, + instance_id_t instanceId, + event_id_t eventId); - COMMONAPI_EXPORT void subscribeForSelective( + COMMONAPI_EXPORT void subscribe( service_id_t serviceId, instance_id_t instanceId, eventgroup_id_t eventGroupId, + event_id_t eventId, std::weak_ptr eventHandler, uint32_t _tag, major_version_t major); - COMMONAPI_EXPORT virtual bool init() = 0; + COMMONAPI_EXPORT std::weak_ptr getWeakPtr(); - COMMONAPI_EXPORT void registerEvent( - service_id_t serviceId, - instance_id_t instanceId, - event_id_t eventId, - eventgroup_id_t eventGroupId, - bool isField); + COMMONAPI_EXPORT virtual const Address &getSomeIpAlias() const = 0; - COMMONAPI_EXPORT void unregisterEvent( - service_id_t serviceId, - instance_id_t instanceId, - event_id_t eventId); protected: const std::string commonApiDomain_; diff --git a/include/CommonAPI/SomeIP/ProxyConnection.hpp b/include/CommonAPI/SomeIP/ProxyConnection.hpp index c78e95f..2582aa2 100644 --- a/include/CommonAPI/SomeIP/ProxyConnection.hpp +++ b/include/CommonAPI/SomeIP/ProxyConnection.hpp @@ -46,7 +46,6 @@ class ProxyConnection { public: virtual ~EventHandler() { } virtual void onEventMessage(const Message&) = 0; - virtual void onInitialValueEventMessage(const Message &, const uint32_t) {}; virtual void onError(const uint16_t, const uint32_t) {}; }; @@ -97,15 +96,6 @@ class ProxyConnection { major_version_t major, minor_version_t minor) = 0; - virtual void subscribeForSelective( - service_id_t serviceId, - instance_id_t instanceId, - eventgroup_id_t eventGroupId, - event_id_t eventId, - std::weak_ptr eventHandler, - uint32_t _tag, - major_version_t major) = 0; - virtual bool isAvailable(const Address &_address) = 0; virtual AvailabilityHandlerId_t registerAvailabilityHandler( @@ -144,12 +134,6 @@ class ProxyConnection { virtual void queueSelectiveErrorHandler(service_id_t serviceId, instance_id_t instanceId) = 0; - virtual void subscribeForField(service_id_t serviceId, - instance_id_t instanceId, - eventgroup_id_t eventGroupId, - event_id_t eventId, - major_version_t major) = 0; - virtual void proxyPushMessageToMainLoop(const Message &_message, std::unique_ptr messageReplyAsyncHandler) = 0; @@ -162,6 +146,14 @@ class ProxyConnection { virtual void getAvailableInstances(service_id_t _serviceId, std::vector *_instances) = 0; + virtual void subscribe( + service_id_t serviceId, + instance_id_t instanceId, + eventgroup_id_t eventGroupId, + event_id_t eventId, + std::weak_ptr _eventHandler, + uint32_t _tag, + major_version_t major) = 0; }; diff --git a/include/CommonAPI/SomeIP/ProxyHelper.hpp b/include/CommonAPI/SomeIP/ProxyHelper.hpp index a32453a..375dcb9 100644 --- a/include/CommonAPI/SomeIP/ProxyHelper.hpp +++ b/include/CommonAPI/SomeIP/ProxyHelper.hpp @@ -107,6 +107,11 @@ struct ProxyHelper, Out_> { return; } + if(!reply.isValidCRC()) { + _callStatus = CallStatus::INVALID_VALUE; + return; + } + if (sizeof...(OutArgs_) > 0) { InputStream inputStream(reply, _isLittleEndian); const bool success = SerializableArguments::deserialize(inputStream, _outArgs...); diff --git a/include/CommonAPI/SomeIP/SelectiveEvent.hpp b/include/CommonAPI/SomeIP/SelectiveEvent.hpp index d7a49ce..8410110 100644 --- a/include/CommonAPI/SomeIP/SelectiveEvent.hpp +++ b/include/CommonAPI/SomeIP/SelectiveEvent.hpp @@ -19,6 +19,7 @@ template class SelectiveEvent: public Event { public: typedef typename Event::Listener Listener; + typedef typename Event::Handler Handler; typedef Event EventBase; SelectiveEvent(ProxyBase &_proxy, @@ -38,6 +39,9 @@ class SelectiveEvent: public Event { protected: virtual void onFirstListenerAdded(const Listener&) { + if (!this->handler_) { + this->handler_ = std::make_shared(this->proxy_, this); + } auto major = this->proxy_.getSomeIpAddress().getMajorVersion(); this->proxy_.addEventHandler(this->serviceId_, this->instanceId_, this->eventgroupId_, this->eventId_, false, this->handler_, major, true); @@ -46,8 +50,8 @@ class SelectiveEvent: public Event { virtual void onListenerAdded(const Listener &_listener, const uint32_t _subscription) { (void) _listener; auto major = this->proxy_.getSomeIpAddress().getMajorVersion(); - this->proxy_.subscribeForSelective(this->serviceId_, this->instanceId_, - this->eventgroupId_, this->eventId_, this->handler_, _subscription, major); + this->proxy_.subscribe(this->serviceId_, this->instanceId_, this->eventgroupId_, + this->eventId_, this->handler_, _subscription, major); } virtual void onLastListenerRemoved(const Listener&) { diff --git a/include/CommonAPI/SomeIP/StringEncoder.hpp b/include/CommonAPI/SomeIP/StringEncoder.hpp index 77bd5aa..d165b49 100644 --- a/include/CommonAPI/SomeIP/StringEncoder.hpp +++ b/include/CommonAPI/SomeIP/StringEncoder.hpp @@ -41,27 +41,27 @@ class StringEncoder { public: bool checkBom(byte_t *&_data, uint32_t &_size, StringEncoding _encoding); - void utf16To8(byte_t *_utf16Str, int _endianess, size_t _size, EncodingStatus &_status, byte_t **_result, size_t &_length); - void utf8To16(byte_t *_utf8Str, int _endianess, EncodingStatus &_status, byte_t **_result, size_t &_length); + void utf16To8(const byte_t *_utf16Str, int _endianess, size_t _size, EncodingStatus &_status, byte_t **_result, size_t &_length); + void utf8To16(const byte_t *_utf8Str, int _endianess, EncodingStatus &_status, byte_t **_result, size_t &_length); - bool isUtf8Valid(byte_t *_utf8Str); + bool isUtf8Valid(const byte_t *_utf8Str); private: bool isNewSequence(byte_t _byte); bool isSurrogate(uint16_t _codePoint); bool isCodePointValid(uint32_t _codePoint); bool isSequenceTooLong(uint32_t _codePoint, int _size); - bool nextUtf8(byte_t **_bytes, EncodingStatus &_status); - bool nextUtf16(byte_t **_bytes, int &_index, size_t _length, EncodingStatus &_status); + bool nextUtf8(const byte_t **_bytes, EncodingStatus &_status); + bool nextUtf16(const byte_t **_bytes, int &_index, size_t _length, EncodingStatus &_status); - uint32_t getByteSequence1(byte_t _byte, EncodingStatus &_status); - uint32_t getByteSequence2(byte_t **_bytes, EncodingStatus &_status); - uint32_t getByteSequence3(byte_t **_bytes, EncodingStatus &_status); - uint32_t getByteSequence4(byte_t **_bytes, EncodingStatus &_status); + uint32_t getByteSequence1(const byte_t _byte, EncodingStatus &_status); + uint32_t getByteSequence2(const byte_t **_bytes, EncodingStatus &_status); + uint32_t getByteSequence3(const byte_t **_bytes, EncodingStatus &_status); + uint32_t getByteSequence4(const byte_t **_bytes, EncodingStatus &_status); int getSequenceLength(byte_t _byte); - uint32_t getNextBytes(byte_t **_bytes, EncodingStatus &_status); + uint32_t getNextBytes(const byte_t **_bytes, EncodingStatus &_status); bytes_t push(uint32_t _codePoint, EncodingStatus &_status); }; diff --git a/include/CommonAPI/SomeIP/SubscriptionStatusWrapper.hpp b/include/CommonAPI/SomeIP/SubscriptionStatusWrapper.hpp new file mode 100644 index 0000000..657b88b --- /dev/null +++ b/include/CommonAPI/SomeIP/SubscriptionStatusWrapper.hpp @@ -0,0 +1,65 @@ +// Copyright (C) 2014-2017 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/. + +#ifndef INCLUDE_COMMONAPI_SOMEIP_SUBSCRIPTIONSTATUSWRAPPER_HPP_ +#define INCLUDE_COMMONAPI_SOMEIP_SUBSCRIPTIONSTATUSWRAPPER_HPP_ + +#include +#include +#include + +#include "Types.hpp" +#include "ProxyConnection.hpp" + +namespace CommonAPI { +namespace SomeIP { + +class SubscriptionStatusWrapper { + public: + SubscriptionStatusWrapper(service_id_t serviceId, instance_id_t instanceId, + eventgroup_id_t eventgroupId, event_id_t eventId); + + virtual ~SubscriptionStatusWrapper(); + + void pushOnPendingHandlerQueue(); + + void addHandler(const std::weak_ptr _handler, + const uint32_t _tag); + + void removeHandler(ProxyConnection::EventHandler* _handler); + + bool hasHandler(ProxyConnection::EventHandler* _handler, uint32_t _tag); + + bool pendingHandlerQueueEmpty(); + + std::pair, uint32_t> popAndFrontPendingHandler(); + + inline service_id_t get_service() { + return serviceId_; + } + + inline service_id_t get_instance() { + return instanceId_; + } + + private: + void pushOnPendingHandlerQueue(const std::weak_ptr _handler, + const uint32_t _tag); + + service_id_t serviceId_; + instance_id_t instanceId_; + eventgroup_id_t eventgroupId_; + event_id_t eventId_; + + std::queue, + uint32_t> > pendingHandlerQueue_; + + std::map, std::set > > allHandlers_; +}; + +} +} +#endif /* INCLUDE_COMMONAPI_SOMEIP_SUBSCRIPTIONSTATUSWRAPPER_HPP_ */ diff --git a/src/CommonAPI/SomeIP/Address.cpp b/src/CommonAPI/SomeIP/Address.cpp index 222e435..ea4d82f 100644 --- a/src/CommonAPI/SomeIP/Address.cpp +++ b/src/CommonAPI/SomeIP/Address.cpp @@ -11,7 +11,7 @@ namespace SomeIP { Address::Address() : service_(0x0000), instance_(0x0000), - major_version_(0x00), minor_version_(0x00000000) { + major_version_(ANY_MAJOR_VERSION), minor_version_(ANY_MINOR_VERSION) { } Address::Address(const service_id_t _service, const instance_id_t _instance, @@ -37,18 +37,32 @@ Address::operator=(const Address &_source) { bool Address::operator==(const Address &_other) const { - return (service_ == _other.service_ && instance_ == _other.instance_); + return (service_ == _other.service_ + && instance_ == _other.instance_ + && (major_version_ == ANY_MAJOR_VERSION + || _other.major_version_ == ANY_MAJOR_VERSION + || major_version_ == _other.major_version_)); } bool Address::operator!=(const Address &_other) const { - return (service_ != _other.service_ || instance_ != _other.instance_); + return (service_ != _other.service_ + || instance_ != _other.instance_ + || (major_version_ != ANY_MAJOR_VERSION + && _other.major_version_ != ANY_MAJOR_VERSION + && major_version_ != _other.major_version_)); } bool Address::operator<(const Address &_other) const { - return (service_ < _other.service_ || - (service_ == _other.service_ && instance_ < _other.instance_)); + return (service_ < _other.service_ + || (service_ == _other.service_ + && instance_ < _other.instance_) + || (service_ == _other.service_ + && instance_ == _other.instance_ + && major_version_ != ANY_MAJOR_VERSION + && _other.major_version_ != ANY_MAJOR_VERSION + && major_version_ < _other.major_version_)); } const service_id_t & diff --git a/src/CommonAPI/SomeIP/AddressTranslator.cpp b/src/CommonAPI/SomeIP/AddressTranslator.cpp index 1894c44..5d57565 100644 --- a/src/CommonAPI/SomeIP/AddressTranslator.cpp +++ b/src/CommonAPI/SomeIP/AddressTranslator.cpp @@ -48,6 +48,11 @@ AddressTranslator::init() { 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_ += "/"; @@ -162,6 +167,7 @@ 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)) { @@ -175,54 +181,74 @@ AddressTranslator::readConfiguration() { struct stat s; if (stat(config.c_str(), &s) != 0) { config = defaultConfig_; + if (stat(config.c_str(), &s) != 0) { + tryLoadConfig = false; + } } } IniFileReader reader; - if (!reader.load(config)) + if (tryLoadConfig && !reader.load(config)) return false; - for (auto itsMapping : reader.getSections()) { - service_id_t service; - std::string serviceEntry = itsMapping.second->getValue("service"); - - std::stringstream converter; - if (0 == serviceEntry.find("0x")) { - converter << std::hex << serviceEntry.substr(2); + 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 { - converter << std::dec << serviceEntry; + 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); } - converter >> service; - - instance_id_t instance; - std::string instanceEntry = itsMapping.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 = itsMapping.second->getValue("major"); - converter.str(""); - converter.clear(); - converter << std::dec << majorEntry; - converter >> major_temp; - major_version = static_cast(major_temp); - - std::string minorEntry = itsMapping.second->getValue("minor"); - converter.str(""); - converter.clear(); - converter << std::dec << minorEntry; - converter >> minor_version; - - insert(itsMapping.first, service, instance, major_version, minor_version); } return true; @@ -250,5 +276,230 @@ 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/Connection.cpp b/src/CommonAPI/SomeIP/Connection.cpp index 2a51f4b..57e0db2 100644 --- a/src/CommonAPI/SomeIP/Connection.cpp +++ b/src/CommonAPI/SomeIP/Connection.cpp @@ -161,6 +161,14 @@ void Connection::onAvailabilityChange(service_id_t _service, instance_id_t _inst bool _is_available) { { std::lock_guard itsLock(availabilityCalledMutex_); + auto its_service = availabilityCalled_.find(_service); + if (its_service != availabilityCalled_.end()) { + auto its_instance = its_service->second.find(_instance); + if (its_instance != its_service->second.end() && + its_instance->second && !_is_available) { + queueSubscriptionStatusHandler(_service, _instance); + } + } availabilityCalled_[_service][_instance] = true; } if (auto lockedContext = mainLoopContext_.lock()) { @@ -288,7 +296,9 @@ void Connection::cleanup() { } Connection::Connection(const std::string &_name) - : connectionStatus_(state_type_e::ST_DEREGISTERED), + : dispatchSource_(NULL), + watch_(NULL), + connectionStatus_(state_type_e::ST_DEREGISTERED), application_(vsomeip::runtime::get()->create_application(_name)), asyncAnswersCleanupThread_(NULL), cleanupCancelled_(false), @@ -475,8 +485,8 @@ Message Connection::sendMessageWithReplyAndBlock( Message itsResult; - std::chrono::system_clock::time_point elapsed( - std::chrono::system_clock::now() + std::chrono::steady_clock::time_point elapsed( + std::chrono::steady_clock::now() + std::chrono::milliseconds(_info->timeout_)); // Wait until the answer was received. @@ -513,24 +523,17 @@ void Connection::addEventHandler( bool isField, bool isSelective) { + (void)major; + (void)isField; + (void)isSelective; std::unique_lock lock(eventHandlerMutex_); if(auto itsHandler = eventHandler.lock()) { eventHandlers_[serviceId][instanceId][eventId][itsHandler.get()] = eventHandler; const bool inserted(std::get<1>(subscriptions_[serviceId][instanceId][eventId].insert(eventGroupId))); - - if(!isField || isSelective) { - subscriptionCounters_[serviceId][instanceId][eventId]++; - } - if(inserted) { - if(isSelective) { - addSelectiveErrorListener(serviceId, instanceId, eventGroupId); - } else if(!isField) { - application_->subscribe(serviceId, instanceId, eventGroupId, major, - vsomeip::subscription_type_e::SU_RELIABLE_AND_UNRELIABLE, eventId); - } + addSubscriptionStatusListener(serviceId, instanceId, eventGroupId, + eventId); } - } } @@ -555,48 +558,23 @@ void Connection::removeEventHandler( foundEventId->second.erase(eventHandler); if (foundEventId->second.size() == 0) { foundInstance->second.erase(foundEventId); - } - // decrement subscription counter for given event - auto s = subscriptionCounters_.find(serviceId); - if (s != subscriptionCounters_.end()) { - auto i = s->second.find(instanceId); - if (i != s->second.end()) { - auto g = i->second.find(eventId); - if (g != i->second.end()) { - if (g->second > 0) - g->second--; - if(g->second == 0) { - lastSubscriber = true; - application_->unsubscribe(serviceId, instanceId, eventGroupId, eventId); - } - } - } + lastSubscriber = true; + application_->unsubscribe(serviceId, instanceId, + eventGroupId, eventId); } } } } - auto it_service = pendingSelectiveErrorHandlers_.find(serviceId); - if (it_service != pendingSelectiveErrorHandlers_.end()) { - auto it_instance = it_service->second.find(instanceId); - if (it_instance != it_service->second.end()) { - auto its_eventgroup = it_instance->second.find(eventGroupId); - if (its_eventgroup != it_instance->second.end()) { - its_eventgroup->second.erase(eventHandler); - if (its_eventgroup->second.size() == 0) { - it_instance->second.erase(eventGroupId); - if (it_instance->second.size() == 0) { - it_service->second.erase(instanceId); - if (it_service->second.size() == 0) { - pendingSelectiveErrorHandlers_.erase(serviceId); - } - } - } - } - } + auto its_tuple = std::make_tuple(serviceId, instanceId, eventGroupId, eventId); + auto its_wrapper = subscriptionStates_.find(its_tuple); + if (its_wrapper != subscriptionStates_.end()) { + its_wrapper->second->removeHandler(eventHandler); } if (lastSubscriber) { + subscriptionStates_.erase(its_tuple); + auto foundPendingService = subscriptions_.find(serviceId); if (foundPendingService != subscriptions_.end()) { auto foundPendingInstance = foundPendingService->second.find(instanceId); @@ -610,74 +588,61 @@ void Connection::removeEventHandler( } } - application_->unregister_subscription_error_handler(serviceId, instanceId, - eventGroupId); + application_->register_subscription_status_handler(serviceId, instanceId, + eventGroupId, eventId, nullptr); } } -void Connection::subscribeForSelective( - service_id_t serviceId, instance_id_t instanceId, - eventgroup_id_t eventGroupId, event_id_t eventId, - std::weak_ptr eventHandler, uint32_t _tag, - major_version_t major) { - std::set tags; - tags.insert(_tag); +void Connection::subscribe(service_id_t serviceId, instance_id_t instanceId, + eventgroup_id_t eventGroupId, event_id_t eventId, + std::weak_ptr eventHandler, + uint32_t _tag, major_version_t major) { - std::unique_lock lock(eventHandlerMutex_); - selectiveErrorHandlers_[serviceId][instanceId][eventGroupId].push(std::make_pair(eventHandler, tags)); - - if(auto itsHandler = eventHandler.lock()) { - auto itsTags = pendingSelectiveErrorHandlers_[serviceId][instanceId][eventGroupId][itsHandler.get()].second; - itsTags.insert(_tag); - pendingSelectiveErrorHandlers_[serviceId][instanceId][eventGroupId][itsHandler.get()] = std::make_pair(eventHandler, itsTags); - } + insertSubscriptionStatusListener(serviceId, instanceId, eventGroupId, eventId, + eventHandler, _tag); application_->subscribe(serviceId, instanceId, eventGroupId, major, - vsomeip::subscription_type_e::SU_RELIABLE_AND_UNRELIABLE, eventId); + vsomeip::subscription_type_e::SU_PREFER_RELIABLE, eventId); } -void Connection::addSelectiveErrorListener(service_id_t serviceId, +void Connection::addSubscriptionStatusListener(service_id_t serviceId, instance_id_t instanceId, - eventgroup_id_t eventGroupId) { + eventgroup_id_t eventGroupId, + event_id_t eventId) { + + auto statusHandler = [this] ( + const vsomeip::service_t _service, const vsomeip::instance_t _instance, + const vsomeip::eventgroup_t _eventgroup, const vsomeip::event_t _event, + const uint16_t errorCode) { - auto connection = shared_from_this(); - auto errorHandler = [serviceId, instanceId, eventGroupId, connection, this] ( - const uint16_t errorCode) { + // SubscriptionStatusListenerCalled! + auto its_tuple = std::make_tuple(_service, _instance, _eventgroup, _event); std::unique_lock lock(eventHandlerMutex_); - { - auto it_service = selectiveErrorHandlers_.find(serviceId); - if (it_service != selectiveErrorHandlers_.end()) { - auto it_instance = it_service->second.find(instanceId); - if (it_instance != it_service->second.end()) { - auto it_eventgroup = it_instance->second.find(eventGroupId); - if (it_eventgroup != it_instance->second.end()) { - if (!it_eventgroup->second.empty()) { - auto entry = it_eventgroup->second.front(); - it_eventgroup->second.pop(); - for (uint32_t tag : entry.second) { - std::weak_ptr handler = entry.first; - if (auto lockedContext = mainLoopContext_.lock()) { - std::shared_ptr err_queue_entry = - std::make_shared( - handler, errorCode, tag, - serviceId, instanceId, eventGroupId); - watch_->pushQueue(err_queue_entry); - } else { - if(auto itsHandler = handler.lock()) { - lock.unlock(); - itsHandler->onError(errorCode, tag); - lock.lock(); - } - } - } + SubscriptionStatusWrapper subscriptionStatus(_service, _instance, _eventgroup, _event); + auto its_wrapper = subscriptionStates_.find(its_tuple); + if (its_wrapper != subscriptionStates_.end()) { + while (!its_wrapper->second->pendingHandlerQueueEmpty()) { + auto entry = its_wrapper->second->popAndFrontPendingHandler(); + std::weak_ptr handler = entry.first; + if (auto lockedContext = mainLoopContext_.lock()) { + std::shared_ptr err_queue_entry = + std::make_shared( + handler, errorCode, entry.second, + _service, _instance, _eventgroup, _event); + watch_->pushQueue(err_queue_entry); + } else { + if(auto itsHandler = handler.lock()) { + lock.unlock(); + itsHandler->onError(errorCode, entry.second); + lock.lock(); } } - } } } }; - application_->register_subscription_error_handler(serviceId, instanceId, - eventGroupId, errorHandler); + application_->register_subscription_status_handler(serviceId, instanceId, + eventGroupId, eventId, statusHandler); + } bool @@ -1009,26 +974,14 @@ void Connection::processAvblQueueEntry(AvblQueueEntry &_avblQueueEntry) { } void Connection::processErrQueueEntry(ErrQueueEntry &_errQueueEntry) { + auto its_tuple = std::make_tuple(_errQueueEntry.service_, _errQueueEntry.instance_, + _errQueueEntry.eventGroup_, _errQueueEntry.event_); std::lock_guard lock(eventHandlerMutex_); - auto foundService = pendingSelectiveErrorHandlers_.find(_errQueueEntry.service_); - if (foundService != pendingSelectiveErrorHandlers_.end()) { - auto foundInstance = foundService->second.find( - _errQueueEntry.instance_); - if (foundInstance != foundService->second.end()) { - auto foundEventGroup = foundInstance->second.find( - _errQueueEntry.eventGroup_); - if (foundEventGroup != foundInstance->second.end()) { - if(auto itsHandler = _errQueueEntry.eventHandler_.lock()) { - auto foundEventHandlerPair = foundEventGroup->second.find(itsHandler.get()); - if (foundEventHandlerPair != foundEventGroup->second.end()) { - auto foundSubscriptionId = foundEventHandlerPair->second.second.find( - _errQueueEntry.tag_); - if (foundSubscriptionId - != foundEventHandlerPair->second.second.end()) { - itsHandler->onError(_errQueueEntry.errorCode_, *foundSubscriptionId); - } - } - } + auto its_wrapper = subscriptionStates_.find(its_tuple); + if (its_wrapper != subscriptionStates_.end()) { + if(auto itsHandler = _errQueueEntry.eventHandler_.lock()) { + if (its_wrapper->second->hasHandler(itsHandler.get(), _errQueueEntry.tag_)) { + itsHandler->onError(_errQueueEntry.errorCode_, _errQueueEntry.tag_); } } } @@ -1039,27 +992,24 @@ const ConnectionId_t& Connection::getConnectionId() { } void Connection::queueSelectiveErrorHandler(service_id_t serviceId, + instance_id_t instanceId) { + (void)serviceId; + (void)instanceId; + + // Keep only for compatibility reasons +} + +void Connection::queueSubscriptionStatusHandler(service_id_t serviceId, instance_id_t instanceId) { std::unique_lock lock(eventHandlerMutex_); auto findService = subscriptions_.find(serviceId); if (findService != subscriptions_.end()) { auto findInstance = findService->second.find(instanceId); if (findInstance != findService->second.end()) { - for (auto &e : findInstance->second) { - auto it_service = pendingSelectiveErrorHandlers_.find(serviceId); - if (it_service != pendingSelectiveErrorHandlers_.end()) { - auto it_instance = it_service->second.find(instanceId); - if (it_instance != it_service->second.end()) { - for (auto group : e.second) { - auto it_eventgroup = it_instance->second.find(group); - if (it_eventgroup != it_instance->second.end()) { - for (auto its_handler : it_eventgroup->second) { - selectiveErrorHandlers_[serviceId][instanceId][group].push( - std::make_pair(its_handler.second.first, its_handler.second.second)); - } - } - } - } + for (const auto& its_tuple : subscriptionStates_) { + if (serviceId == std::get<0>(its_tuple.first) && + instanceId == std::get<1>(its_tuple.first)) { + its_tuple.second->pushOnPendingHandlerQueue(); } } } @@ -1076,19 +1026,6 @@ void Connection::unregisterSubsciptionHandler(const Address &_address, application_->unregister_subscription_handler(_address.getService(), _address.getInstance(), _eventgroup); } -void Connection::subscribeForField(service_id_t serviceId, - instance_id_t instanceId, - eventgroup_id_t eventGroupId, - event_id_t eventId, - major_version_t major) { - { - std::lock_guard its_lock(eventHandlerMutex_); - subscriptionCounters_[serviceId][instanceId][eventId]++; - } - application_->subscribe(serviceId, instanceId, eventGroupId, major, - vsomeip::subscription_type_e::SU_RELIABLE_AND_UNRELIABLE, eventId); -} - void Connection::incrementConnection() { std::lock_guard < std::mutex > lock(activeConnectionsMutex_); activeConnections_++; @@ -1141,5 +1078,21 @@ void Connection::getAvailableInstances(service_id_t _serviceId, std::vector eventHandler, + uint32_t _tag) { + auto itsTuple = std::make_tuple(serviceId, instanceId, eventGroupId, eventId); + std::unique_lock lock(eventHandlerMutex_); + auto its_wrapper = subscriptionStates_.find(itsTuple); + if (its_wrapper != subscriptionStates_.end()) { + its_wrapper->second->addHandler(eventHandler, _tag); + } else { + auto subscriptionStatus = std::make_shared(serviceId, instanceId, eventGroupId, eventId); + subscriptionStatus->addHandler(eventHandler, _tag); + subscriptionStates_[itsTuple] = subscriptionStatus; + } +} + } // namespace SomeIP } // namespace CommonAPI diff --git a/src/CommonAPI/SomeIP/Message.cpp b/src/CommonAPI/SomeIP/Message.cpp index 86ebbd9..71a3ac6 100644 --- a/src/CommonAPI/SomeIP/Message.cpp +++ b/src/CommonAPI/SomeIP/Message.cpp @@ -179,5 +179,11 @@ Message::setPayloadData(const byte_t* data, message_length_t length) { payload->set_data(data, length); } + +bool Message::isValidCRC() const { + return message_->is_valid_crc(); +} + + } // namespace SomeIP } // namespace CommonAPI diff --git a/src/CommonAPI/SomeIP/OutputStream.cpp b/src/CommonAPI/SomeIP/OutputStream.cpp index d0f1d0c..3c92b1c 100644 --- a/src/CommonAPI/SomeIP/OutputStream.cpp +++ b/src/CommonAPI/SomeIP/OutputStream.cpp @@ -37,12 +37,12 @@ size_t OutputStream::getPosition() { } void OutputStream::pushPosition() { - positions_.push(payload_.size()); + positions_.push_back(payload_.size()); } size_t OutputStream::popPosition() { - size_t itsPosition = positions_.top(); - positions_.pop(); + size_t itsPosition = positions_.back(); + positions_.pop_back(); return itsPosition; } @@ -198,15 +198,15 @@ OutputStream& OutputStream::writeValue(const std::string &_value, const StringDe switch (_depl->stringEncoding_) { case StringEncoding::UTF16BE: - encoder->utf8To16((byte_t *)_value.c_str(), BIG_ENDIAN, status, &bytes, size); + encoder->utf8To16(reinterpret_cast(_value.c_str()), BIG_ENDIAN, status, &bytes, size); break; case StringEncoding::UTF16LE: - encoder->utf8To16((byte_t *)_value.c_str(), LITTLE_ENDIAN, status, &bytes, size); + encoder->utf8To16(reinterpret_cast(_value.c_str()), LITTLE_ENDIAN, status, &bytes, size); break; default: - bytes = (byte_t *)(_value.c_str()); + bytes = reinterpret_cast(const_cast(_value.c_str())); size = _value.size(); bomSize = 3; terminationSize = 1; @@ -215,12 +215,13 @@ OutputStream& OutputStream::writeValue(const std::string &_value, const StringDe if (status != EncodingStatus::SUCCESS) { - //TODO error handling + COMMONAPI_ERROR("OutputStream::writeValue(string):error, encoding status is: ", + static_cast(status)); } } else { - bytes = (byte_t *)(_value.c_str()); + bytes = reinterpret_cast(const_cast(_value.c_str())); size = _value.size(); bomSize = 3; terminationSize = 1; @@ -250,9 +251,11 @@ OutputStream& OutputStream::writeValue(const std::string &_value, const StringDe // Write termination const byte_t termination[] = { 0x00, 0x00 }; _writeRaw(termination, terminationSize); + } else { + COMMONAPI_ERROR("OutputStream::writeValue(string): error occurred"); } - if (bytes != (byte_t*)_value.c_str()) { + if (bytes != reinterpret_cast(const_cast(_value.c_str()))) { delete [] bytes; } diff --git a/src/CommonAPI/SomeIP/Proxy.cpp b/src/CommonAPI/SomeIP/Proxy.cpp index 5114ecf..059c859 100644 --- a/src/CommonAPI/SomeIP/Proxy.cpp +++ b/src/CommonAPI/SomeIP/Proxy.cpp @@ -11,10 +11,13 @@ #include #include #include +#include namespace CommonAPI { namespace SomeIP { +static std::weak_ptr factory__(Factory::get()); + ProxyStatusEventHelper::ProxyStatusEventHelper(Proxy* proxy) : proxy_(proxy) { } @@ -212,15 +215,12 @@ void Proxy::onServiceInstanceStatus(std::shared_ptr _proxy, void* _data) { (void)_proxy; (void)_data; - bool queueSelective(false); + (void) serviceId; + (void) instanceId; { std::lock_guard listenersLock(proxyStatusEvent_.listenersMutex_); { std::lock_guard itsLock(availabilityMutex_); - if (availabilityStatus_ == AvailabilityStatus::AVAILABLE && !isAvailable) { - // Only queue selective error handlers for implicitly re-subscribing! - queueSelective = true; - } const AvailabilityStatus itsStatus( isAvailable ? AvailabilityStatus::AVAILABLE : AvailabilityStatus::NOT_AVAILABLE); @@ -235,9 +235,6 @@ void Proxy::onServiceInstanceStatus(std::shared_ptr _proxy, availabilityTimeoutCondition_.notify_all(); availabilityTimeoutThreadMutex_.unlock(); - if (queueSelective) - getConnection()->queueSelectiveErrorHandler(serviceId, instanceId); - for(auto listenerIt : proxyStatusEvent_.listeners_) proxyStatusEvent_.notifySpecificListener(listenerIt.first, availabilityStatus_); } @@ -249,6 +246,7 @@ Proxy::Proxy(const Address &_address, bool hasSelective) : ProxyBase(connection), address_(_address), + alias_(AddressTranslator::get()->getAddressAlias(_address)), proxyStatusEvent_(this), availabilityStatus_(AvailabilityStatus::UNKNOWN), availabilityHandlerId_(0), @@ -261,9 +259,11 @@ Proxy::~Proxy() { if(availabilityTimeoutThread_->joinable()) availabilityTimeoutThread_->join(); } - getConnection()->releaseService(address_); - getConnection()->unregisterAvailabilityHandler(address_, availabilityHandlerId_); - Factory::get()->decrementConnection(getConnection()); + getConnection()->releaseService(alias_); + getConnection()->unregisterAvailabilityHandler(alias_, availabilityHandlerId_); + if (auto ptr = factory__.lock()) { + ptr->decrementConnection(getConnection()); + } } bool Proxy::init() { @@ -271,11 +271,11 @@ bool Proxy::init() { if (!connection) return false; - connection->requestService(address_, hasSelectiveEvents_); + connection->requestService(alias_, hasSelectiveEvents_); std::weak_ptr itsProxy = shared_from_this(); availabilityHandlerId_ = connection->registerAvailabilityHandler( - address_, + alias_, std::bind(&Proxy::onServiceInstanceStatus, this, std::placeholders::_1, @@ -285,7 +285,7 @@ bool Proxy::init() { std::placeholders::_5), itsProxy, NULL); - if (connection->isAvailable(address_)) { + if (connection->isAvailable(alias_)) { std::lock_guard itsLock(availabilityMutex_); availabilityStatus_ = AvailabilityStatus::AVAILABLE; } @@ -298,6 +298,11 @@ Proxy::getSomeIpAddress() const { return address_; } +const Address & +Proxy::getSomeIpAlias() const { + return alias_; +} + bool Proxy::isAvailable() const { std::lock_guard itsLock(availabilityMutex_); return (getConnection()->isConnected() @@ -380,12 +385,5 @@ InterfaceVersionAttribute& Proxy::getInterfaceVersionAttribute() { return interfaceVersionAttribute_; } -void Proxy::getInitialEvent(service_id_t serviceId, instance_id_t instanceId, - eventgroup_id_t eventGroupId, event_id_t eventId, - major_version_t major) { - getConnection()->subscribeForField(serviceId, instanceId, eventGroupId, - eventId, major); -} - } // namespace SomeIP } // namespace CommonAPI diff --git a/src/CommonAPI/SomeIP/ProxyBase.cpp b/src/CommonAPI/SomeIP/ProxyBase.cpp index 40c96b6..4ea04ea 100644 --- a/src/CommonAPI/SomeIP/ProxyBase.cpp +++ b/src/CommonAPI/SomeIP/ProxyBase.cpp @@ -6,6 +6,7 @@ #include #include #include +#include namespace CommonAPI { namespace SomeIP { @@ -17,7 +18,8 @@ ProxyBase::ProxyBase(const std::shared_ptr< ProxyConnection > &connection) } Message ProxyBase::createMethodCall(const method_id_t _method, bool _reliable) const { - return Message::createMethodCall(getSomeIpAddress(), _method, _reliable); + return Message::createMethodCall(getSomeIpAlias(), + AddressTranslator::get()->getMethodAlias(getSomeIpAddress(), _method), _reliable); } void ProxyBase::addEventHandler( @@ -29,14 +31,15 @@ void ProxyBase::addEventHandler( std::weak_ptr eventHandler, major_version_t major, bool _isSelective) { - + event_id_t itsEventId = AddressTranslator::get()->getMethodAlias(getSomeIpAddress(), eventId); { std::lock_guard itsLock(eventHandlerAddedMutex_); - eventHandlerAdded_.insert(eventId); + eventHandlerAdded_.insert(itsEventId); } - connection_->addEventHandler(serviceId, instanceId, eventGroupId, eventId, + eventgroup_id_t itsEventGroupId = AddressTranslator::get()->getEventgroupAlias(getSomeIpAddress(), eventGroupId); + connection_->addEventHandler(serviceId, instanceId, itsEventGroupId, itsEventId, eventHandler, major, isField, _isSelective); - connection_->requestEvent(serviceId, instanceId, eventId, eventGroupId, isField); + connection_->requestEvent(serviceId, instanceId, itsEventId, itsEventGroupId, isField); } void ProxyBase::removeEventHandler( @@ -48,54 +51,59 @@ void ProxyBase::removeEventHandler( major_version_t major, minor_version_t minor) { bool found(false); + event_id_t itsEventId = AddressTranslator::get()->getMethodAlias(getSomeIpAddress(), eventId); { std::lock_guard itsLock(eventHandlerAddedMutex_); - if (eventHandlerAdded_.find(eventId) != eventHandlerAdded_.end()) { + if (eventHandlerAdded_.find(itsEventId) != eventHandlerAdded_.end()) { found = true; - eventHandlerAdded_.erase(eventId); + eventHandlerAdded_.erase(itsEventId); } } if (found) { - connection_->releaseEvent(serviceId, instanceId, eventId); - connection_->removeEventHandler(serviceId, instanceId, eventGroupId, eventId, eventHandler, major, minor); + eventgroup_id_t itsEventGroupId = AddressTranslator::get()->getEventgroupAlias(getSomeIpAddress(), eventGroupId); + connection_->releaseEvent(serviceId, instanceId, itsEventId); + connection_->removeEventHandler(serviceId, instanceId, itsEventGroupId, itsEventId, eventHandler, major, minor); } } -void ProxyBase::subscribeForSelective( - service_id_t serviceId, - instance_id_t instanceId, - eventgroup_id_t eventGroupId, - event_id_t eventId, - std::weak_ptr eventHandler, - uint32_t _tag, - major_version_t major) { - connection_->subscribeForSelective(serviceId, instanceId, eventGroupId, eventId, eventHandler, _tag, major); -} - -void ProxyBase::subscribeForSelective( - service_id_t serviceId, - instance_id_t instanceId, - eventgroup_id_t eventGroupId, - std::weak_ptr eventHandler, - uint32_t _tag, - major_version_t major) { - connection_->subscribeForSelective(serviceId, instanceId, eventGroupId, vsomeip::ANY_EVENT, eventHandler, _tag, major); -} - void ProxyBase::registerEvent( service_id_t serviceId, instance_id_t instanceId, event_id_t eventId, eventgroup_id_t eventGroupId, bool isField) { - connection_->requestEvent(serviceId, instanceId, eventId, eventGroupId, isField); + event_id_t itsEventId = AddressTranslator::get()->getMethodAlias(getSomeIpAddress(), eventId); + eventgroup_id_t itsEventGroupId = AddressTranslator::get()->getEventgroupAlias(getSomeIpAddress(), eventGroupId); + connection_->requestEvent(serviceId, instanceId, itsEventId, itsEventGroupId, isField); } void ProxyBase::unregisterEvent( service_id_t serviceId, instance_id_t instanceId, event_id_t eventId) { - connection_->releaseEvent(serviceId, instanceId, eventId); + event_id_t itsEventId = AddressTranslator::get()->getMethodAlias(getSomeIpAddress(), eventId); + connection_->releaseEvent(serviceId, instanceId, itsEventId); +} + +void ProxyBase::subscribe( + service_id_t serviceId, + instance_id_t instanceId, + eventgroup_id_t eventGroupId, + event_id_t eventId, + 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); + connection_->subscribe(serviceId, instanceId, itsEventGroupId, itsEventId, + eventHandler, _tag, major); +} + +std::weak_ptr ProxyBase::getWeakPtr() { + if(auto p = dynamic_cast(this)) { + return p->shared_from_this(); + } + return std::weak_ptr(); } } // namespace SomeIP diff --git a/src/CommonAPI/SomeIP/StringEncoder.cpp b/src/CommonAPI/SomeIP/StringEncoder.cpp index d6acd91..3cf83e0 100644 --- a/src/CommonAPI/SomeIP/StringEncoder.cpp +++ b/src/CommonAPI/SomeIP/StringEncoder.cpp @@ -46,7 +46,7 @@ bool StringEncoder::checkBom(byte_t *&_data, uint32_t &_size, StringEncoding _en return result; } -void StringEncoder::utf16To8(byte_t *_utf16Str, int _endianess, size_t _size, EncodingStatus &_status, byte_t **_result, size_t &_length) +void StringEncoder::utf16To8(const byte_t *_utf16Str, int _endianess, size_t _size, EncodingStatus &_status, byte_t **_result, size_t &_length) { _status = EncodingStatus::SUCCESS; bytes_t bytes; @@ -137,7 +137,7 @@ void StringEncoder::utf16To8(byte_t *_utf16Str, int _endianess, size_t _size, En *_result = tmp; } -void StringEncoder::utf8To16(byte_t *_utf8Str, int _endianess, EncodingStatus &_status, byte_t **_result, size_t &_length) +void StringEncoder::utf8To16(const byte_t *_utf8Str, int _endianess, EncodingStatus &_status, byte_t **_result, size_t &_length) { _status = EncodingStatus::SUCCESS; @@ -201,7 +201,7 @@ void StringEncoder::utf8To16(byte_t *_utf8Str, int _endianess, EncodingStatus &_ *_result = tmp; } -bool StringEncoder::isUtf8Valid(byte_t *_utf8Str) +bool StringEncoder::isUtf8Valid(const byte_t *_utf8Str) { while (*_utf8Str != '\0') { @@ -247,7 +247,7 @@ bool StringEncoder::isSequenceTooLong(uint32_t _codePoint, int _size) return false; } -bool StringEncoder::nextUtf8(byte_t **_bytes, EncodingStatus &_status) +bool StringEncoder::nextUtf8(const byte_t **_bytes, EncodingStatus &_status) { (*_bytes)++; if (**_bytes == '\0') @@ -264,7 +264,7 @@ bool StringEncoder::nextUtf8(byte_t **_bytes, EncodingStatus &_status) return true; } -bool StringEncoder::nextUtf16(byte_t **_bytes, int &_index, size_t _length, EncodingStatus &_status) +bool StringEncoder::nextUtf16(const byte_t **_bytes, int &_index, size_t _length, EncodingStatus &_status) { (*_bytes)++; _index++; @@ -286,7 +286,7 @@ uint32_t StringEncoder::getByteSequence1(byte_t _byte, EncodingStatus &_status) return _byte; } -uint32_t StringEncoder::getByteSequence2(byte_t **_bytes, EncodingStatus &_status) +uint32_t StringEncoder::getByteSequence2(const byte_t **_bytes, EncodingStatus &_status) { // 2 bytes utf8 format: 110x xxxx 10xx xxxx @@ -306,7 +306,7 @@ uint32_t StringEncoder::getByteSequence2(byte_t **_bytes, EncodingStatus &_statu return codePoint; } -uint32_t StringEncoder::getByteSequence3(byte_t **_bytes, EncodingStatus &_status) +uint32_t StringEncoder::getByteSequence3(const byte_t **_bytes, EncodingStatus &_status) { // 3 bytes utf8 format: 1110 xxxx 10xx xxxx 10xx xxxx @@ -333,7 +333,7 @@ uint32_t StringEncoder::getByteSequence3(byte_t **_bytes, EncodingStatus &_statu return codePoint; } -uint32_t StringEncoder::getByteSequence4(byte_t **_bytes, EncodingStatus &_status) +uint32_t StringEncoder::getByteSequence4(const byte_t **_bytes, EncodingStatus &_status) { // 4 bytes utf8 format: 1111 0xxx 10xx xxxx 10xx xxxx 10xx xxxx @@ -380,7 +380,7 @@ int StringEncoder::getSequenceLength(byte_t _byte) return 0; } -uint32_t StringEncoder::getNextBytes(byte_t **_bytes, EncodingStatus &_status) +uint32_t StringEncoder::getNextBytes(const byte_t **_bytes, EncodingStatus &_status) { uint32_t codePoint = 0; int sequenceLength = getSequenceLength(**_bytes); diff --git a/src/CommonAPI/SomeIP/StubManager.cpp b/src/CommonAPI/SomeIP/StubManager.cpp index 3a2d8ab..f4e9fb0 100644 --- a/src/CommonAPI/SomeIP/StubManager.cpp +++ b/src/CommonAPI/SomeIP/StubManager.cpp @@ -23,6 +23,10 @@ StubManager::~StubManager() { void StubManager::registerStubAdapter(std::shared_ptr _adapter) { std::shared_ptr connection = connection_.lock(); + if (!connection) { + COMMONAPI_ERROR("StubManager::registerStubAdapter couldn't lock connection"); + return; + } Address itsAddress = _adapter->getSomeIpAddress(); service_id_t service = itsAddress.getService(); instance_id_t instance = itsAddress.getInstance(); @@ -36,6 +40,10 @@ void StubManager::registerStubAdapter(std::shared_ptr _adapter) { void StubManager::unregisterStubAdapter(std::shared_ptr _adapter) { std::shared_ptr connection = connection_.lock(); + if (!connection) { + COMMONAPI_ERROR("StubManager::unregisterStubAdapter couldn't lock connection"); + return; + } Address itsAddress = _adapter->getSomeIpAddress(); service_id_t service = itsAddress.getService(); instance_id_t instance = itsAddress.getInstance(); diff --git a/src/CommonAPI/SomeIP/SubscriptionStatusWrapper.cpp b/src/CommonAPI/SomeIP/SubscriptionStatusWrapper.cpp new file mode 100644 index 0000000..9786492 --- /dev/null +++ b/src/CommonAPI/SomeIP/SubscriptionStatusWrapper.cpp @@ -0,0 +1,87 @@ +// Copyright (C) 2014-2017 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/. + +#include +#include + +namespace CommonAPI { +namespace SomeIP { + +// Public + +SubscriptionStatusWrapper::SubscriptionStatusWrapper(service_id_t serviceId, instance_id_t instanceId, + eventgroup_id_t eventgroupId, event_id_t eventId) + : serviceId_(serviceId), instanceId_(instanceId), + eventgroupId_(eventgroupId), eventId_(eventId) { +} + +SubscriptionStatusWrapper::~SubscriptionStatusWrapper() { +} + +void SubscriptionStatusWrapper::pushOnPendingHandlerQueue() { + for (auto its_handler : allHandlers_) { + for (uint32_t its_tag : its_handler.second.second) { + auto its_pair = std::make_pair(its_handler.second.first, its_tag); + pendingHandlerQueue_.push(its_pair); + } + } +} + +bool SubscriptionStatusWrapper::pendingHandlerQueueEmpty() { + return pendingHandlerQueue_.size() == 0; +} + +std::pair, uint32_t > + SubscriptionStatusWrapper::popAndFrontPendingHandler() { + auto result = pendingHandlerQueue_.front(); + pendingHandlerQueue_.pop(); + return result; +} + +void SubscriptionStatusWrapper::addHandler(const std::weak_ptr _handler, + const uint32_t _tag) { + auto its_handler = _handler.lock(); + if (its_handler) { + auto found_handler = allHandlers_.find(its_handler.get()); + if (found_handler != allHandlers_.end()) { + found_handler->second.second.insert(_tag); + } else { + std::set tags; + tags.insert(_tag); + allHandlers_[its_handler.get()] = std::make_pair(_handler, tags); + } + pushOnPendingHandlerQueue(_handler, _tag); + } +} + +void SubscriptionStatusWrapper::removeHandler( + ProxyConnection::EventHandler* _handler) { + allHandlers_.erase(_handler); +} + +bool SubscriptionStatusWrapper::hasHandler(ProxyConnection::EventHandler* _handler, + uint32_t _tag) { + auto its_handler = allHandlers_.find(_handler); + if (its_handler != allHandlers_.end()) { + auto its_tag = its_handler->second.second.find(_tag); + if (its_tag != its_handler->second.second.end()) { + return true; + } + } + return false; +} + +// Private + +void SubscriptionStatusWrapper::pushOnPendingHandlerQueue( + const std::weak_ptr _handler, + const uint32_t _tag) { + pendingHandlerQueue_.push(std::make_pair(_handler, _tag)); +} + +} +} + +