summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJuergen Gehring <juergen.gehring@bmw.de>2017-06-20 02:54:31 -0700
committerJuergen Gehring <juergen.gehring@bmw.de>2017-06-20 02:54:31 -0700
commitfdf86239b4a6867e0a961a307649a6d5eb3a2f93 (patch)
treeb25be00a044a41135d11ddd3f15c1adce3a6411b
parent27698301f8bb528c2f618af5995865523de7e0d6 (diff)
downloadvSomeIP-2.7.0.tar.gz
vSomeIP 2.7.02.7.0
-rw-r--r--.gitignore3
-rw-r--r--CHANGES23
-rw-r--r--CMakeLists.txt20
-rw-r--r--daemon/vsomeipd.cpp15
-rw-r--r--documentation/vsomeipUserGuide21
-rw-r--r--exportmap.gcc5
-rw-r--r--implementation/configuration/include/configuration.hpp14
-rw-r--r--implementation/configuration/include/configuration_impl.hpp28
-rw-r--r--implementation/configuration/include/e2e.hpp12
-rw-r--r--implementation/configuration/include/internal.hpp.in22
-rw-r--r--implementation/configuration/src/configuration.cpp36
-rw-r--r--implementation/configuration/src/configuration_impl.cpp128
-rw-r--r--implementation/e2e_protection/include/e2e/profile/profile01/profile_01.hpp6
-rw-r--r--implementation/e2e_protection/include/e2e/profile/profile01/protector.hpp10
-rw-r--r--implementation/e2e_protection/src/e2e/profile/profile01/profile_01.cpp5
-rw-r--r--implementation/e2e_protection/src/e2e/profile/profile01/protector.cpp38
-rw-r--r--implementation/endpoints/include/local_server_endpoint_impl.hpp14
-rw-r--r--implementation/endpoints/include/netlink_connector.hpp4
-rw-r--r--implementation/endpoints/include/server_endpoint_impl.hpp2
-rw-r--r--implementation/endpoints/include/tcp_server_endpoint_impl.hpp20
-rw-r--r--implementation/endpoints/include/udp_server_endpoint_impl.hpp1
-rw-r--r--implementation/endpoints/src/endpoint_impl.cpp73
-rw-r--r--implementation/endpoints/src/local_client_endpoint_impl.cpp2
-rw-r--r--implementation/endpoints/src/local_server_endpoint_impl.cpp35
-rw-r--r--implementation/endpoints/src/netlink_connector.cpp6
-rw-r--r--implementation/endpoints/src/server_endpoint_impl.cpp10
-rw-r--r--implementation/endpoints/src/tcp_client_endpoint_impl.cpp4
-rw-r--r--implementation/endpoints/src/tcp_server_endpoint_impl.cpp91
-rw-r--r--implementation/endpoints/src/udp_server_endpoint_impl.cpp21
-rw-r--r--implementation/logging/include/dlt_sink_backend.hpp2
-rw-r--r--implementation/message/include/message_base_impl.hpp4
-rw-r--r--implementation/message/src/message_base_impl.cpp12
-rw-r--r--implementation/plugin/include/plugin_manager.hpp56
-rw-r--r--implementation/plugin/src/plugin_manager.cpp212
-rw-r--r--implementation/routing/include/event.hpp2
-rw-r--r--implementation/routing/include/eventgroupinfo.hpp3
-rw-r--r--implementation/routing/include/routing_manager.hpp5
-rw-r--r--implementation/routing/include/routing_manager_base.hpp12
-rw-r--r--implementation/routing/include/routing_manager_host.hpp2
-rw-r--r--implementation/routing/include/routing_manager_impl.hpp32
-rw-r--r--implementation/routing/include/routing_manager_proxy.hpp16
-rw-r--r--implementation/routing/include/routing_manager_stub.hpp2
-rw-r--r--implementation/routing/include/routing_manager_stub_host.hpp2
-rw-r--r--implementation/routing/src/event.cpp10
-rw-r--r--implementation/routing/src/eventgroupinfo.cpp4
-rw-r--r--implementation/routing/src/routing_manager_base.cpp61
-rw-r--r--implementation/routing/src/routing_manager_impl.cpp663
-rw-r--r--implementation/routing/src/routing_manager_proxy.cpp230
-rw-r--r--implementation/routing/src/routing_manager_stub.cpp120
-rw-r--r--implementation/runtime/include/application_impl.hpp19
-rw-r--r--implementation/runtime/src/application_impl.cpp296
-rw-r--r--implementation/service_discovery/include/runtime.hpp1
-rw-r--r--implementation/service_discovery/include/runtime_impl.hpp7
-rw-r--r--implementation/service_discovery/include/service_discovery.hpp2
-rw-r--r--implementation/service_discovery/include/service_discovery_host.hpp3
-rw-r--r--implementation/service_discovery/include/service_discovery_impl.hpp4
-rw-r--r--implementation/service_discovery/src/ipv4_option_impl.cpp2
-rwxr-xr-ximplementation/service_discovery/src/ipv6_option_impl.cpp2
-rw-r--r--implementation/service_discovery/src/runtime.cpp40
-rw-r--r--implementation/service_discovery/src/runtime_impl.cpp8
-rw-r--r--implementation/service_discovery/src/service_discovery_impl.cpp102
-rw-r--r--implementation/tracing/include/trace_header.hpp11
-rw-r--r--implementation/tracing/src/trace_connector.cpp4
-rw-r--r--implementation/tracing/src/trace_header.cpp15
-rw-r--r--implementation/utility/include/utility.hpp12
-rw-r--r--implementation/utility/src/utility.cpp98
-rw-r--r--interface/vsomeip/application.hpp24
-rw-r--r--interface/vsomeip/enumeration_types.hpp1
-rw-r--r--interface/vsomeip/handler.hpp2
-rw-r--r--interface/vsomeip/message_base.hpp11
-rw-r--r--interface/vsomeip/plugin.hpp89
-rw-r--r--interface/vsomeip/plugins/application_plugin.hpp42
-rw-r--r--interface/vsomeip/plugins/pre_configuration_plugin.hpp29
-rw-r--r--plugins/CMakeLists.txt8
-rw-r--r--plugins/mgu/CMakeLists.txt58
-rw-r--r--plugins/mgu/include/diagnosis_plugin_mgu.hpp53
-rw-r--r--plugins/mgu/src/diagnosis_plugin_mgu.cpp144
-rw-r--r--test/CMakeLists.txt90
-rw-r--r--test/client_id_tests/client_id_test_utility.cpp23
-rw-r--r--test/configuration_tests/configuration-test-deprecated.json199
-rw-r--r--test/configuration_tests/configuration-test.cpp388
-rw-r--r--test/configuration_tests/configuration-test.json199
-rw-r--r--test/initial_event_tests/initial_event_test_client.cpp60
-rw-r--r--test/readme.txt6
-rw-r--r--test/subscribe_notify_one_tests/subscribe_notify_one_test_service.cpp66
-rw-r--r--test/subscribe_notify_tests/conf/subscribe_notify_test_one_event_two_eventgroups_master.json.in31
-rw-r--r--test/subscribe_notify_tests/conf/subscribe_notify_test_one_event_two_eventgroups_tcp_slave.json.in39
-rw-r--r--test/subscribe_notify_tests/conf/subscribe_notify_test_one_event_two_eventgroups_udp_slave.json.in39
-rw-r--r--test/subscribe_notify_tests/subscribe_notify_test_globals.hpp7
-rw-r--r--test/subscribe_notify_tests/subscribe_notify_test_one_event_two_eventgroups_client.cpp370
-rwxr-xr-xtest/subscribe_notify_tests/subscribe_notify_test_one_event_two_eventgroups_master_starter.sh88
-rw-r--r--test/subscribe_notify_tests/subscribe_notify_test_one_event_two_eventgroups_service.cpp212
-rwxr-xr-xtest/subscribe_notify_tests/subscribe_notify_test_one_event_two_eventgroups_slave_starter.sh45
-rw-r--r--test/subscribe_notify_tests/subscribe_notify_test_service.cpp63
-rw-r--r--tools/vsomeip_ctrl.cpp14
95 files changed, 4114 insertions, 1031 deletions
diff --git a/.gitignore b/.gitignore
index 696f1e5..2d955fc 100644
--- a/.gitignore
+++ b/.gitignore
@@ -44,6 +44,9 @@
/test/subscribe_notify_tests/subscribe_notify_test_same_client_ids_diff_ports_slave.json
/test/subscribe_notify_tests/subscribe_notify_test_same_client_ids_same_ports_master.json
/test/subscribe_notify_tests/subscribe_notify_test_same_client_ids_same_ports_slave.json
+/test/subscribe_notify_tests/subscribe_notify_test_one_event_two_eventgroups_master.json
+/test/subscribe_notify_tests/subscribe_notify_test_one_event_two_eventgroups_udp_slave.json
+/test/subscribe_notify_tests/subscribe_notify_test_one_event_two_eventgroups_tcp_slave.json
/test/subscribe_notify_one_tests/subscribe_notify_one_test_diff_client_ids_diff_ports_master.json
/test/subscribe_notify_one_tests/subscribe_notify_one_test_diff_client_ids_diff_ports_slave.json
/test/subscribe_notify_tests/subscribe_notify_test_diff_client_ids_diff_ports_same_service_id_master.json
diff --git a/CHANGES b/CHANGES
index 1837480..2695a0f 100644
--- a/CHANGES
+++ b/CHANGES
@@ -306,3 +306,26 @@ v2.6.3
v2.6.4
- Fix bug in reboot detection of other nodes
- Improve restarting of TCP connections
+
+v2.7.0
+- Add possibility to register a subscription status handler via
+ application interface. The handler will be called if a subscription
+ is acknowledged / not acknowledged by the application hosting the
+ target service instance of the subscription
+- The default subscription type of application::subscribe method was
+ changed from RELIABLE_AND_UNRELIABLE to PREFER_RELIABLE to harmonize
+ initial event behaviour
+- Add generic plug-in concept
+- Fix bug which caused sending out subscription messages containing
+ endpoint options with port set to zero
+- Make magic cookie detection TCP connection based
+- Avoid sending unneeded SIGKILLs to current routing manager
+- Forward service's instance IDs to DLT
+- Fixed performance loss on "client ID" lookup needed for ingoing
+ remote subscriptions
+- Add signal handling for starting stopping the service discovery to
+ vsomeipd
+- The message object can now be asked for CRC check state:
+ is_valid_crc()
+- Incoming remote responses where the CRC check fails will trigger:
+ set_is_valid_crc(false)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 15a7d59..5c2db35 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -7,8 +7,8 @@ cmake_minimum_required (VERSION 2.8.12)
project (vsomeip)
set (VSOMEIP_MAJOR_VERSION 2)
-set (VSOMEIP_MINOR_VERSION 6)
-set (VSOMEIP_PATCH_VERSION 4)
+set (VSOMEIP_MINOR_VERSION 7)
+set (VSOMEIP_PATCH_VERSION 0)
set (VSOMEIP_VERSION ${VSOMEIP_MAJOR_VERSION}.${VSOMEIP_MINOR_VERSION}.${VSOMEIP_PATCH_VERSION})
set (PACKAGE_VERSION ${VSOMEIP_VERSION}) # Used in documentatin/doxygen.in
set (CMAKE_VERBOSE_MAKEFILE off)
@@ -122,6 +122,7 @@ file(GLOB vsomeip_SRC
"implementation/routing/src/*.cpp"
"implementation/runtime/src/*.cpp"
"implementation/utility/src/*.cpp"
+ "implementation/plugin/src/*.cpp"
)
file(GLOB_RECURSE vsomeip_e2e_SRC
@@ -167,6 +168,7 @@ add_library(vsomeip-cfg SHARED ${vsomeip-cfg_SRC})
set_target_properties (vsomeip-cfg PROPERTIES VERSION ${VSOMEIP_VERSION} SOVERSION ${VSOMEIP_MAJOR_VERSION})
target_link_libraries(vsomeip-cfg vsomeip ${Boost_LIBRARIES} ${USE_RT} ${DL_LIBRARY} ${SystemD_LIBRARIES})
+# Service-Discovery library
file(GLOB vsomeip-sd_SRC
"implementation/service_discovery/src/*.cpp"
)
@@ -177,8 +179,8 @@ set_target_properties (vsomeip-sd PROPERTIES VERSION ${VSOMEIP_VERSION} SOVERSIO
target_link_libraries(vsomeip-sd vsomeip ${Boost_LIBRARIES} ${USE_RT} ${DL_LIBRARY} ${SystemD_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT})
if (MSVC)
- set_target_properties(vsomeip-cfg PROPERTIES COMPILE_DEFINITIONS "VSOMEIP_DLL_COMPILATION_CONFIG")
- set_target_properties(vsomeip-sd PROPERTIES COMPILE_DEFINITIONS "VSOMEIP_DLL_COMPILATION")
+ set_target_properties(vsomeip-cfg PROPERTIES COMPILE_DEFINITIONS "VSOMEIP_DLL_COMPILATION_PLUGIN")
+ set_target_properties(vsomeip-sd PROPERTIES COMPILE_DEFINITIONS "VSOMEIP_DLL_COMPILATION_PLUGIN")
set_target_properties(vsomeip PROPERTIES COMPILE_DEFINITIONS "VSOMEIP_DLL_COMPILATION")
endif()
@@ -378,6 +380,16 @@ add_subdirectory( tools )
add_custom_target( examples )
add_subdirectory( examples EXCLUDE_FROM_ALL )
+# build plugins located directly in the build tree
+# (Non-Windows only)
+if (NOT MSVC)
+ if(EXISTS "${PROJECT_SOURCE_DIR}/plugins/CMakeLists.txt")
+ # build plugins if available
+ message("Plugins CMakeList.txt found: Build plugins")
+ add_subdirectory( plugins )
+ endif()
+endif()
+
##############################################################################
# Test section
diff --git a/daemon/vsomeipd.cpp b/daemon/vsomeipd.cpp
index 6688ec2..b329534 100644
--- a/daemon/vsomeipd.cpp
+++ b/daemon/vsomeipd.cpp
@@ -26,13 +26,22 @@ static std::shared_ptr<vsomeip::application> its_application;
* Handle signal to stop the daemon
*/
void vsomeipd_stop(int _signal) {
- if (_signal == SIGINT || _signal == SIGTERM)
+ if (_signal == SIGINT || _signal == SIGTERM) {
its_application->stop();
+ }
if (_signal == SIGABRT) {
- VSOMEIP_INFO << "Suspending service discovery";
+ VSOMEIP_INFO << "Stopping service discovery";
its_application->set_routing_state(vsomeip::routing_state_e::RS_SUSPENDED);
its_application->stop();
}
+ if (_signal == SIGUSR1) {
+ VSOMEIP_INFO << "Suspending service discovery";
+ its_application->set_routing_state(vsomeip::routing_state_e::RS_SUSPENDED);
+ }
+ if (_signal == SIGUSR2) {
+ VSOMEIP_INFO << "Resuming service discovery";
+ its_application->set_routing_state(vsomeip::routing_state_e::RS_RESUMED);
+ }
}
#endif
@@ -61,6 +70,8 @@ int vsomeipd_process(bool _is_quiet) {
signal(SIGINT, vsomeipd_stop);
signal(SIGTERM, vsomeipd_stop);
signal(SIGABRT, vsomeipd_stop);
+ signal(SIGUSR1, vsomeipd_stop);
+ signal(SIGUSR2, vsomeipd_stop);
#endif
if (its_application->init()) {
if (its_application->is_routing()) {
diff --git a/documentation/vsomeipUserGuide b/documentation/vsomeipUserGuide
index 19aa864..922af01 100644
--- a/documentation/vsomeipUserGuide
+++ b/documentation/vsomeipUserGuide
@@ -285,6 +285,14 @@ The netmask to specify the subnet of the host system.
+
The diagnosis address (byte) that will be used to build client identifiers.
+
+* 'network'
++
+Network identifier used to support multiple routing managers on one host. This
+setting changes the name of the shared memory segment in `/dev/shm` and the name
+of the unix domain sockets in `/tmp/`. Defaults to `vsomeip` meaning the shared
+memory will be named `/dev/shm/vsomeip` and the unix domain sockets will be
+named `/tmp/vsomeip-$CLIENTID`
++
//Logging
* 'logging'
+
@@ -312,6 +320,19 @@ The absolute path of the log file.
Specifies whether Diagnostic Log and Trace (DLT) is enabled (valid values:
_true, false_).
+
+** 'version'
++
+Configures logging of the vSomeIP version
++
+*** 'enable'
++
+Enable or disable cyclic logging of vSomeIP version, defaults to true (valid
+values: _true, false_)
++
+*** 'interval'
++
+Configures interval in seconds to log the vSomeIP version. Default value is 10.
++
//Tracing
* anchor:config-tracing[]'tracing' (optional)
+
diff --git a/exportmap.gcc b/exportmap.gcc
index e0136e6..61da700 100644
--- a/exportmap.gcc
+++ b/exportmap.gcc
@@ -38,9 +38,10 @@ global:
vsomeip::sd::runtime::*;
*vsomeip::utility;
vsomeip::utility::is*;
+ *vsomeip::plugin_manager;
+ vsomeip::plugin_manager::*;
};
- VSOMEIP_CFG_RUNTIME;
- VSOMEIP_SD_RUNTIME;
+ vsomeip_plugin_init;
local:
*;
};
diff --git a/implementation/configuration/include/configuration.hpp b/implementation/configuration/include/configuration.hpp
index c8b7717..6f18300 100644
--- a/implementation/configuration/include/configuration.hpp
+++ b/implementation/configuration/include/configuration.hpp
@@ -16,6 +16,7 @@
#include <vsomeip/export.hpp>
#include <vsomeip/defines.hpp>
+#include <vsomeip/plugin.hpp>
#include <vsomeip/primitive_types.hpp>
#include "internal.hpp"
@@ -24,17 +25,20 @@
#include "../../e2e_protection/include/e2exf/config.hpp"
#include "e2e.hpp"
+#define VSOMEIP_CONFIG_PLUGIN_VERSION 1
+
namespace vsomeip {
class event;
-class VSOMEIP_IMPORT_EXPORT_CONFIG configuration {
+class configuration {
public:
- static std::shared_ptr<configuration> get();
virtual ~configuration() {}
virtual bool load(const std::string &_name) = 0;
+ virtual const std::string &get_network() const = 0;
+
virtual const boost::asio::ip::address & get_unicast_address() const = 0;
virtual unsigned short get_diagnosis_address() const = 0;
virtual bool is_v4() const = 0;
@@ -129,6 +133,12 @@ public:
instance_t _instance) const = 0;
virtual bool check_credentials(client_t _client, uint32_t _uid, uint32_t _gid) const = 0;
+ // Plugins
+ virtual std::map<plugin_type_e, std::string> get_plugins(
+ const std::string &_name) const = 0;
+
+ virtual void set_configuration_path(const std::string &_path) = 0;
+
//E2E
virtual std::map<e2exf::data_identifier, std::shared_ptr<cfg::e2e>> get_e2e_configuration() const = 0;
virtual bool is_e2e_enabled() const = 0;
diff --git a/implementation/configuration/include/configuration_impl.hpp b/implementation/configuration/include/configuration_impl.hpp
index b345d9d..c519f05 100644
--- a/implementation/configuration/include/configuration_impl.hpp
+++ b/implementation/configuration/include/configuration_impl.hpp
@@ -41,16 +41,21 @@ struct element {
}
};
-class configuration_impl: public configuration, public std::enable_shared_from_this<configuration_impl> {
+class configuration_impl:
+ public configuration,
+ public plugin_impl<configuration_impl>,
+ public std::enable_shared_from_this<configuration_impl> {
public:
- VSOMEIP_EXPORT static std::shared_ptr<configuration> get();
-
VSOMEIP_EXPORT configuration_impl();
VSOMEIP_EXPORT configuration_impl(const configuration_impl &_cfg);
VSOMEIP_EXPORT virtual ~configuration_impl();
VSOMEIP_EXPORT bool load(const std::string &_name);
+ VSOMEIP_EXPORT const std::string &get_network() const;
+
+ VSOMEIP_EXPORT void set_configuration_path(const std::string &_path);
+
VSOMEIP_EXPORT const boost::asio::ip::address & get_unicast_address() const;
VSOMEIP_EXPORT unsigned short get_diagnosis_address() const;
VSOMEIP_EXPORT bool is_v4() const;
@@ -139,8 +144,10 @@ public:
VSOMEIP_EXPORT bool is_offer_allowed(client_t _client, service_t _service,
instance_t _instance) const;
VSOMEIP_EXPORT bool check_credentials(client_t _client, uint32_t _uid, uint32_t _gid) const;
-
- //E2E
+
+ VSOMEIP_EXPORT std::map<plugin_type_e, std::string> get_plugins(
+ const std::string &_name) const;
+ // E2E
VSOMEIP_EXPORT std::map<e2exf::data_identifier, std::shared_ptr<cfg::e2e>> get_e2e_configuration() const;
VSOMEIP_EXPORT bool is_e2e_enabled() const;
@@ -171,6 +178,8 @@ private:
std::string &_criteria,
std::shared_ptr<trace_filter_rule> &_filter_rule);
+ void load_network(const element &_element);
+
void load_unicast_address(const element &_element);
void load_diagnosis_address(const element &_element);
@@ -237,7 +246,8 @@ protected:
std::string logfile_;
boost::log::trivial::severity_level loglevel_;
- std::map<std::string, std::tuple<client_t, std::size_t, std::size_t, std::size_t, std::size_t>> applications_;
+ std::map<std::string, std::tuple<client_t, std::size_t, std::size_t,
+ size_t, size_t, std::map<plugin_type_e, std::string>>> applications_;
std::set<client_t> client_identifiers_;
std::map<service_t,
@@ -284,6 +294,7 @@ protected:
uint32_t log_version_interval_;
enum element_type_e {
+ ET_NETWORK,
ET_UNICAST,
ET_DIAGNOSIS,
ET_LOGGING_CONSOLE,
@@ -308,7 +319,7 @@ protected:
ET_TRACING_ENABLE,
ET_TRACING_SD_ENABLE,
ET_SERVICE_DISCOVERY_OFFER_DEBOUNCE_TIME,
- ET_MAX = 24
+ ET_MAX = 25
};
bool is_configured_[ET_MAX];
@@ -319,6 +330,9 @@ protected:
bool policy_enabled_;
bool check_credentials_;
+ std::string network_;
+ std::string configuration_path_;
+
bool e2e_enabled_;
std::map<e2exf::data_identifier, std::shared_ptr<cfg::e2e>> e2e_configuration_;
};
diff --git a/implementation/configuration/include/e2e.hpp b/implementation/configuration/include/e2e.hpp
index 305ef7a..349c6f4 100644
--- a/implementation/configuration/include/e2e.hpp
+++ b/implementation/configuration/include/e2e.hpp
@@ -25,13 +25,15 @@ struct e2e {
event_id(0),
crc_offset(0),
data_id_mode(0),
- data_length(0) {
+ data_length(0),
+ data_id_nibble_offset(0),
+ counter_offset(0) {
}
e2e(uint16_t _data_id, std::string _variant, std::string _profile, uint16_t _service_id,
uint16_t _event_id,uint16_t _crc_offset,
- uint8_t _data_id_mode, uint16_t _data_length) :
+ uint8_t _data_id_mode, uint16_t _data_length, uint16_t _data_id_nibble_offset, uint16_t _counter_offset) :
data_id(_data_id),
variant(_variant),
@@ -40,7 +42,9 @@ struct e2e {
event_id(_event_id),
crc_offset(_crc_offset),
data_id_mode(_data_id_mode),
- data_length(_data_length) {
+ data_length(_data_length),
+ data_id_nibble_offset(_data_id_nibble_offset),
+ counter_offset(_counter_offset) {
}
@@ -56,6 +60,8 @@ struct e2e {
uint16_t crc_offset;
uint8_t data_id_mode;
uint16_t data_length;
+ uint16_t data_id_nibble_offset;
+ uint16_t counter_offset;
};
diff --git a/implementation/configuration/include/internal.hpp.in b/implementation/configuration/include/internal.hpp.in
index 7d8a18c..14d58f9 100644
--- a/implementation/configuration/include/internal.hpp.in
+++ b/implementation/configuration/include/internal.hpp.in
@@ -14,6 +14,7 @@
#define VSOMEIP_ENV_CONFIGURATION "VSOMEIP_CONFIGURATION"
#define VSOMEIP_ENV_CONFIGURATION_MODULE "VSOMEIP_CONFIGURATION_MODULE"
#define VSOMEIP_ENV_MANDATORY_CONFIGURATION_FILES "VSOMEIP_MANDATORY_CONFIGURATION_FILES"
+#define VSOMEIP_ENV_LOAD_PLUGINS "VSOMEIP_LOAD_PLUGINS"
#define VSOMEIP_DEFAULT_CONFIGURATION_FILE "/etc/vsomeip.json"
#define VSOMEIP_LOCAL_CONFIGURATION_FILE "./vsomeip.json"
@@ -22,15 +23,19 @@
#define VSOMEIP_DEFAULT_CONFIGURATION_FOLDER "/etc/vsomeip"
#define VSOMEIP_LOCAL_CONFIGURATION_FOLDER "./vsomeip"
-#define VSOMEIP_BASE_PATH "/tmp/vsomeip-"
+#define VSOMEIP_BASE_PATH "/tmp/"
+#ifdef WIN32
+#define VSOMEIP_CFG_LIBRARY "vsomeip-cfg.dll"
+#else
#define VSOMEIP_CFG_LIBRARY "libvsomeip-cfg.so.@VSOMEIP_MAJOR_VERSION@"
-#define VSOMEIP_CFG_RUNTIME_SYMBOL VSOMEIP_CFG_RUNTIME
-#define VSOMEIP_CFG_RUNTIME_SYMBOL_STRING "VSOMEIP_CFG_RUNTIME"
+#endif
+#ifdef WIN32
+#define VSOMEIP_SD_LIBRARY "vsomeip-sd.dll"
+#else
#define VSOMEIP_SD_LIBRARY "libvsomeip-sd.so.@VSOMEIP_MAJOR_VERSION@"
-#define VSOMEIP_SD_RUNTIME_SYMBOL VSOMEIP_SD_RUNTIME
-#define VSOMEIP_SD_RUNTIME_SYMBOL_STRING "VSOMEIP_SD_RUNTIME"
+#endif
#define VSOMEIP_ROUTING "@VSOMEIP_ROUTING@"
#define VSOMEIP_ROUTING_CLIENT 0
@@ -112,7 +117,6 @@
#endif
#define VSOMEIP_DATA_ID 0x677D
-#define VSOMEIP_SHM_NAME "/vsomeip"
#define VSOMEIP_DIAGNOSIS_ADDRESS @VSOMEIP_DIAGNOSIS_ADDRESS@
#define VSOMEIP_DEFAULT_SHM_PERMISSION 0666
@@ -145,6 +149,12 @@ struct service_data_t {
}
};
+typedef enum {
+ SUBSCRIPTION_ACKNOWLEDGED,
+ SUBSCRIPTION_NOT_ACKNOWLEDGED,
+ IS_SUBSCRIBING
+} subscription_state_e;
+
struct configuration_data_t {
#ifndef _WIN32
volatile char initialized_;
diff --git a/implementation/configuration/src/configuration.cpp b/implementation/configuration/src/configuration.cpp
deleted file mode 100644
index c4039f7..0000000
--- a/implementation/configuration/src/configuration.cpp
+++ /dev/null
@@ -1,36 +0,0 @@
-// 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/configuration_impl.hpp"
-
-#ifdef _WIN32
-extern "C"
-{
- __declspec(dllexport) std::shared_ptr<vsomeip::configuration> VSOMEIP_CFG_RUNTIME_SYMBOL;
-}
-#else
-std::shared_ptr<vsomeip::configuration> VSOMEIP_CFG_RUNTIME_SYMBOL(vsomeip::configuration::get());
-#endif
-
-#ifdef _WIN32
-#define CCALL __cdecl
-#pragma section(".CRT$XCU",read)
-#define INITIALIZER(f) \
- static void __cdecl f(void); \
- __declspec(allocate(".CRT$XCU")) void(__cdecl*f##_)(void) = f; \
- static void __cdecl f(void)
-
-INITIALIZER(init_vsomeip_cfg) {
- VSOMEIP_CFG_RUNTIME_SYMBOL = vsomeip::configuration::get();
-}
-#endif
-
-namespace vsomeip {
-
-std::shared_ptr<configuration> configuration::get() {
- return cfg::configuration_impl::get();
-}
-
-} // namespace vsomeip
diff --git a/implementation/configuration/src/configuration_impl.cpp b/implementation/configuration/src/configuration_impl.cpp
index dc13103..68ad340 100644
--- a/implementation/configuration/src/configuration_impl.cpp
+++ b/implementation/configuration/src/configuration_impl.cpp
@@ -18,6 +18,7 @@
#include <boost/property_tree/json_parser.hpp>
#include <vsomeip/constants.hpp>
+#include <vsomeip/plugins/application_plugin.hpp>
#include "../include/client.hpp"
#include "../include/configuration_impl.hpp"
@@ -30,15 +31,14 @@
#include "../../service_discovery/include/defines.hpp"
#include "../../utility/include/utility.hpp"
+VSOMEIP_PLUGIN(vsomeip::cfg::configuration_impl)
+
namespace vsomeip {
namespace cfg {
-std::shared_ptr<configuration> configuration_impl::get() {
- return std::make_shared<configuration_impl>();
-}
-
configuration_impl::configuration_impl()
- : is_loaded_(false),
+ : plugin_impl("vsomeip cfg plugin", 1, plugin_type_e::CONFIGURATION_PLUGIN),
+ is_loaded_(false),
is_logging_loaded_(false),
diagnosis_(VSOMEIP_DIAGNOSIS_ADDRESS),
has_console_log_(true),
@@ -70,6 +70,7 @@ configuration_impl::configuration_impl()
umask_(VSOMEIP_DEFAULT_UMASK_LOCAL_ENDPOINTS),
policy_enabled_(false),
check_credentials_(false),
+ network_("vsomeip"),
e2e_enabled_(false) {
unicast_ = unicast_.from_string(VSOMEIP_UNICAST_ADDRESS);
for (auto i = 0; i < ET_MAX; i++)
@@ -77,7 +78,8 @@ configuration_impl::configuration_impl()
}
configuration_impl::configuration_impl(const configuration_impl &_other)
- : std::enable_shared_from_this<configuration_impl>(_other),
+ : plugin_impl("vsomeip cfg plugin", 1, plugin_type_e::CONFIGURATION_PLUGIN),
+ std::enable_shared_from_this<configuration_impl>(_other),
is_loaded_(_other.is_loaded_),
is_logging_loaded_(_other.is_logging_loaded_),
mandatory_(_other.mandatory_),
@@ -129,6 +131,7 @@ configuration_impl::configuration_impl(const configuration_impl &_other)
policy_enabled_ = _other.policy_enabled_;
check_credentials_ = _other.check_credentials_;
+ network_ = _other.network_;
e2e_enabled_ = _other.e2e_enabled_;
}
@@ -155,7 +158,7 @@ bool configuration_impl::load(const std::string &_name) {
its_folder = its_local_folder;
}
- // Finally, override with path from environment (if existing)
+ // Override with path from environment (if existing)
const char *its_env = getenv(VSOMEIP_ENV_CONFIGURATION);
if (nullptr != its_env) {
if (utility::is_file(its_env)) {
@@ -167,6 +170,17 @@ bool configuration_impl::load(const std::string &_name) {
}
}
+ // Finally, pverride with path from set config path (if existing)
+ if (configuration_path_.length()) {
+ if (utility::is_file(configuration_path_)) {
+ its_file = configuration_path_;
+ its_folder = "";
+ } else if (utility::is_folder(configuration_path_)) {
+ its_folder = configuration_path_;
+ its_file = "";
+ }
+ }
+
std::set<std::string> its_input;
if (its_file != "") {
its_input.insert(its_file);
@@ -302,6 +316,7 @@ bool configuration_impl::load_data(const std::vector<element> &_elements,
for (auto e : _elements) {
has_routing = load_routing(e) || has_routing;
has_applications = load_applications(e) || has_applications;
+ load_network(e);
load_diagnosis_address(e);
load_payload_sizes(e);
load_permissions(e);
@@ -447,6 +462,7 @@ void configuration_impl::load_application_data(
std::size_t its_max_dispatch_time(VSOMEIP_MAX_DISPATCH_TIME);
std::size_t its_io_thread_count(VSOMEIP_IO_THREAD_COUNT);
std::size_t its_request_debounce_time(VSOMEIP_REQUEST_DEBOUNCE_TIME);
+ std::map<plugin_type_e, std::string> plugins;
for (auto i = _tree.begin(); i != _tree.end(); ++i) {
std::string its_key(i->first);
std::string its_value(i->second.data());
@@ -483,6 +499,32 @@ void configuration_impl::load_application_data(
VSOMEIP_WARNING << "Max. request debounce time is 10.000ms";
its_request_debounce_time = 10000;
}
+ } else if (its_key == "plugins") {
+ for (auto l = i->second.begin(); l != i->second.end(); ++l) {
+ for (auto n = l->second.begin(); n != l->second.end(); ++n) {
+ std::string its_inner_key(n->first);
+ std::string its_inner_value(n->second.data());
+ #ifdef _WIN32
+ std::string library(its_inner_value);
+ library += ".dll";
+ #else
+ std::string library("lib");
+ library += its_inner_value;
+ library += ".so";
+ #endif
+ if (its_inner_key == "application_plugin") {
+ #ifndef _WIN32
+ library += ".";
+ library += (VSOMEIP_APPLICATION_PLUGIN_VERSION + '0');
+ #endif
+ plugins[plugin_type_e::APPLICATION_PLUGIN] = library;
+ } else {
+ VSOMEIP_WARNING << "Unknown plug-in type ("
+ << its_inner_key << ") configured for client: "
+ << its_name;
+ }
+ }
+ }
}
}
if (its_name != "") {
@@ -501,7 +543,7 @@ void configuration_impl::load_application_data(
applications_[its_name]
= std::make_tuple(its_id, its_max_dispatchers,
its_max_dispatch_time, its_io_thread_count,
- its_request_debounce_time);
+ its_request_debounce_time, plugins);
} else {
VSOMEIP_WARNING << "Multiple configurations for application "
<< its_name << ". Ignoring a configuration from "
@@ -654,6 +696,21 @@ void configuration_impl::load_unicast_address(const element &_element) {
}
}
+void configuration_impl::load_network(const element &_element) {
+ try {
+ std::string its_value(_element.tree_.get<std::string>("network"));
+ if (is_configured_[ET_NETWORK]) {
+ VSOMEIP_WARNING << "Multiple definitions for network."
+ "Ignoring definition from " << _element.name_;
+ } else {
+ network_ = its_value;
+ is_configured_[ET_NETWORK] = true;
+ }
+ } catch (...) {
+ // intentionally left empty
+ }
+}
+
void configuration_impl::load_diagnosis_address(const element &_element) {
try {
std::string its_value = _element.tree_.get<std::string>("diagnosis");
@@ -757,7 +814,9 @@ void configuration_impl::load_service_discovery(
int tmp;
its_converter << its_value;
its_converter >> tmp;
- sd_repetitions_max_ = (uint8_t)tmp;
+ sd_repetitions_max_ = (tmp > (std::numeric_limits<std::uint8_t>::max)()) ?
+ (std::numeric_limits<std::uint8_t>::max)() :
+ static_cast<std::uint8_t>(tmp);
is_configured_[ET_SERVICE_DISCOVERY_REPETITION_MAX] = true;
}
} else if (its_key == "ttl") {
@@ -820,7 +879,11 @@ void configuration_impl::load_delays(
int tmp_repetition_max;
its_converter << std::dec << i->second.data();
its_converter >> tmp_repetition_max;
- sd_repetitions_max_ = uint8_t(tmp_repetition_max);
+ sd_repetitions_max_ =
+ (tmp_repetition_max
+ > (std::numeric_limits<std::uint8_t>::max)()) ?
+ (std::numeric_limits<std::uint8_t>::max)() :
+ static_cast<std::uint8_t>(tmp_repetition_max);
} else if (its_key == "cyclic-offer") {
its_converter << std::dec << i->second.data();
its_converter >> sd_cyclic_offer_delay_;
@@ -1061,7 +1124,10 @@ void configuration_impl::load_eventgroup(
std::stringstream its_converter;
its_converter << std::dec << its_value;
its_converter >> std::dec >> its_threshold;
- its_eventgroup->threshold_ = static_cast<uint8_t>(its_threshold);
+ its_eventgroup->threshold_ =
+ (its_threshold > (std::numeric_limits<std::uint8_t>::max)()) ?
+ (std::numeric_limits<std::uint8_t>::max)() :
+ static_cast<uint8_t>(its_threshold);
} else if (its_key == "events") {
for (auto k = j->second.begin(); k != j->second.end(); ++k) {
std::stringstream its_converter;
@@ -1488,7 +1554,8 @@ void configuration_impl::load_policy(const boost::property_tree::ptree &_tree) {
if (i->first == "client") {
std::string value = i->second.data();
if (value == "") {
- client_t firstClient, lastClient;
+ client_t firstClient(ILLEGAL_CLIENT);
+ client_t lastClient(ILLEGAL_CLIENT);
for (auto n = i->second.begin();
n != i->second.end(); ++n) {
if (n->first == "first") {
@@ -1700,6 +1767,10 @@ bool configuration_impl::is_internal_service(service_t _service,
///////////////////////////////////////////////////////////////////////////////
// Public interface
///////////////////////////////////////////////////////////////////////////////
+const std::string &configuration_impl::get_network() const {
+ return network_;
+}
+
const boost::asio::ip::address & configuration_impl::get_unicast_address() const {
return unicast_;
}
@@ -2243,6 +2314,22 @@ bool configuration_impl::is_offer_allowed(client_t _client, service_t _service,
return !check_credentials_;
}
+std::map<plugin_type_e, std::string> configuration_impl::get_plugins(
+ const std::string &_name) const {
+ std::map<plugin_type_e, std::string> result;
+
+ auto found_application = applications_.find(_name);
+ if (found_application != applications_.end()) {
+ result = std::get<5>(found_application->second);
+ }
+
+ return result;
+}
+
+void configuration_impl::set_configuration_path(const std::string &_path) {
+ configuration_path_ = _path;
+}
+
bool configuration_impl::is_e2e_enabled() const {
return e2e_enabled_;
}
@@ -2286,6 +2373,8 @@ void configuration_impl::load_e2e_protected(const boost::property_tree::ptree &_
uint16_t crc_offset(0);
uint8_t data_id_mode(0);
uint16_t data_length(0);
+ uint16_t data_id_nibble_offset(12); // data id nibble behind 4 bit counter value
+ uint16_t counter_offset(8); // counter field behind CRC8
for (auto l = _tree.begin(); l != _tree.end(); ++l) {
std::stringstream its_converter;
@@ -2326,12 +2415,21 @@ void configuration_impl::load_e2e_protected(const boost::property_tree::ptree &_
std::string value = l->second.data();
its_converter << value;
its_converter >> crc_offset;
+ } else if (l->first == "counter_offset") {
+ std::string value = l->second.data();
+ its_converter << value;
+ its_converter >> counter_offset;
} else if (l->first == "data_id_mode") {
std::string value = l->second.data();
its_converter << value;
its_converter >> tmp;
data_id_mode = static_cast<uint8_t>(tmp);
- } else if (l->first == "data_length") {
+ } else if (l->first == "data_id_nibble_offset") {
+ std::string value = l->second.data();
+ its_converter << value;
+ its_converter >> data_id_nibble_offset;
+ }
+ else if (l->first == "data_length") {
std::string value = l->second.data();
its_converter << value;
its_converter >> data_length;
@@ -2346,7 +2444,9 @@ void configuration_impl::load_e2e_protected(const boost::property_tree::ptree &_
event_id,
crc_offset,
data_id_mode,
- data_length
+ data_length,
+ data_id_nibble_offset,
+ counter_offset
);
}
diff --git a/implementation/e2e_protection/include/e2e/profile/profile01/profile_01.hpp b/implementation/e2e_protection/include/e2e/profile/profile01/profile_01.hpp
index 4574ca3..569a20d 100644
--- a/implementation/e2e_protection/include/e2e/profile/profile01/profile_01.hpp
+++ b/implementation/e2e_protection/include/e2e/profile/profile01/profile_01.hpp
@@ -31,16 +31,18 @@ struct Config {
uint16_t data_id;
p01_data_id_mode data_id_mode;
uint16_t data_length;
+ uint16_t counter_offset;
+ uint16_t data_id_nibble_offset;
#ifndef E2E_DEVELOPMENT
Config() = delete;
#else
Config() = default;
#endif
- Config(uint16_t _crc_offset, uint16_t _data_id, p01_data_id_mode _data_id_mode, uint16_t _data_length)
+ Config(uint16_t _crc_offset, uint16_t _data_id, p01_data_id_mode _data_id_mode, uint16_t _data_length, uint16_t _counter_offset, uint16_t _data_id_nibble_offset)
: crc_offset(_crc_offset), data_id(_data_id),
- data_id_mode(_data_id_mode), data_length(_data_length) {
+ data_id_mode(_data_id_mode), data_length(_data_length), counter_offset(_counter_offset), data_id_nibble_offset(_data_id_nibble_offset) {
}
Config(const Config &_config) = default;
Config &operator=(const Config &_config) = default;
diff --git a/implementation/e2e_protection/include/e2e/profile/profile01/protector.hpp b/implementation/e2e_protection/include/e2e/profile/profile01/protector.hpp
index 7c10f25..f5a129d 100644
--- a/implementation/e2e_protection/include/e2e/profile/profile01/protector.hpp
+++ b/implementation/e2e_protection/include/e2e/profile/profile01/protector.hpp
@@ -18,16 +18,24 @@ class protector final : public e2e::profile::profile_interface::protector {
public:
protector(void) = delete;
- explicit protector(const Config &_config) : config(_config){};
+ explicit protector(const Config &_config) : config(_config), counter(0){};
void protect(buffer::e2e_buffer &_buffer) override final;
private:
+ void write_counter(buffer::e2e_buffer &_buffer);
+
+ void write_data_id(buffer::e2e_buffer &_buffer);
+
void write_crc(buffer::e2e_buffer &_buffer, uint8_t _computed_crc);
+ void increment_counter(void);
+
+
private:
Config config;
+ uint8_t counter;
std::mutex protect_mutex;
};
}
diff --git a/implementation/e2e_protection/src/e2e/profile/profile01/profile_01.cpp b/implementation/e2e_protection/src/e2e/profile/profile01/profile_01.cpp
index f00ab86..d28d17c 100644
--- a/implementation/e2e_protection/src/e2e/profile/profile01/profile_01.cpp
+++ b/implementation/e2e_protection/src/e2e/profile/profile01/profile_01.cpp
@@ -99,7 +99,10 @@ uint8_t profile_01::compute_crc(const Config &_config, const buffer::e2e_buffer
/** @req [SWS_E2E_00356] */
bool profile_01::is_buffer_length_valid(const Config &_config, const buffer::e2e_buffer &_buffer) {
- return (((_config.data_length / 8) + 1U <= _buffer.size()) && _config.crc_offset <= _buffer.size());
+ return (((_config.data_length / 8) + 1U <= _buffer.size())
+ && _config.crc_offset <= _buffer.size()
+ && _config.counter_offset / 8 <= _buffer.size()
+ && _config.data_id_nibble_offset / 8 <= _buffer.size());
}
}
}
diff --git a/implementation/e2e_protection/src/e2e/profile/profile01/protector.cpp b/implementation/e2e_protection/src/e2e/profile/profile01/protector.cpp
index f3e7134..639eb4c 100644
--- a/implementation/e2e_protection/src/e2e/profile/profile01/protector.cpp
+++ b/implementation/e2e_protection/src/e2e/profile/profile01/protector.cpp
@@ -21,19 +21,57 @@ void protector::protect(buffer::e2e_buffer &_buffer) {
std::lock_guard<std::mutex> lock(protect_mutex);
if(profile_01::is_buffer_length_valid(config, _buffer)) {
+ // write the current Counter value in Data
+ write_counter(_buffer);
+
+ // write DataID nibble in Data (E2E_P01_DATAID_NIBBLE) in Data
+ write_data_id(_buffer);
+
// compute the CRC over DataID and Data
uint8_t computed_crc = profile_01::compute_crc(config, _buffer);
// write CRC in Data
write_crc(_buffer, computed_crc);
+
+ // increment the Counter (new value will be used in the next invocation of E2E_P01Protect()),
+ increment_counter();
}
}
+/** @req [SRS_E2E_08528] */
+void protector::write_counter(buffer::e2e_buffer &_buffer) {
+ if(config.counter_offset % 8 == 0) {
+ // write write counter value into low nibble
+ _buffer[config.counter_offset / 8] = static_cast<uint8_t>((_buffer[config.counter_offset / 8] & 0xF0) | (counter & 0x0F));
+ } else {
+ // write counter into high nibble
+ _buffer[config.counter_offset / 8] = static_cast<uint8_t>((_buffer[config.counter_offset / 8] & 0x0F) | ((counter << 4) & 0xF0));
+ }
+}
+
+/** @req [SRS_E2E_08528] */
+void protector::write_data_id(buffer::e2e_buffer &_buffer) {
+ if(config.data_id_mode == p01_data_id_mode::E2E_P01_DATAID_NIBBLE) {
+ if(config.data_id_nibble_offset % 8 == 0) {
+ // write low nibble of high byte of Data ID
+ _buffer[config.data_id_nibble_offset / 8] = static_cast<uint8_t>((_buffer[config.data_id_nibble_offset / 8] & 0xF0) | ((config.data_id >> 8) & 0x0F));
+ } else {
+ // write low nibble of high byte of Data ID
+ _buffer[config.data_id_nibble_offset / 8] = static_cast<uint8_t>((_buffer[config.data_id_nibble_offset / 8] & 0x0F) | ((config.data_id >> 4) & 0xF0));
+ }
+ }
+}
/** @req [SRS_E2E_08528] */
void protector::write_crc(buffer::e2e_buffer &_buffer, uint8_t _computed_crc) {
_buffer[config.crc_offset] = _computed_crc;
}
+/** @req [SWS_E2E_00075] */
+void protector::increment_counter(void) {
+ counter = static_cast<uint8_t>((counter + 1U) % 15);
+}
+
+
}
}
}
diff --git a/implementation/endpoints/include/local_server_endpoint_impl.hpp b/implementation/endpoints/include/local_server_endpoint_impl.hpp
index b6c26a7..f9fa0ab 100644
--- a/implementation/endpoints/include/local_server_endpoint_impl.hpp
+++ b/implementation/endpoints/include/local_server_endpoint_impl.hpp
@@ -9,10 +9,10 @@
#include <map>
#include <thread>
#include <condition_variable>
+#include <memory>
#include <boost/asio/io_service.hpp>
#include <boost/asio/local/stream_protocol.hpp>
-#include <boost/enable_shared_from_this.hpp>
#ifdef _WIN32
#include <boost/asio/ip/tcp.hpp>
@@ -56,7 +56,6 @@ public:
void start();
void stop();
- void restart();
void receive();
bool send_to(const std::shared_ptr<endpoint_definition>,
@@ -70,14 +69,15 @@ public:
void accept_client_func();
private:
- class connection: public boost::enable_shared_from_this<connection> {
+ class connection: public std::enable_shared_from_this<connection> {
public:
- typedef boost::shared_ptr<connection> ptr;
+ typedef std::shared_ptr<connection> ptr;
static ptr create(std::weak_ptr<local_server_endpoint_impl> _server,
std::uint32_t _max_message_size,
- std::uint32_t _buffer_shrink_threshold);
+ std::uint32_t _buffer_shrink_threshold,
+ boost::asio::io_service &_io_service);
socket_type & get_socket();
std::unique_lock<std::mutex> get_socket_lock();
@@ -92,7 +92,8 @@ private:
connection(std::weak_ptr<local_server_endpoint_impl> _server,
std::uint32_t _recv_buffer_size_initial,
std::uint32_t _max_message_size,
- std::uint32_t _buffer_shrink_threshold);
+ std::uint32_t _buffer_shrink_threshold,
+ boost::asio::io_service &_io_service);
void send_magic_cookie();
void receive_cbk(boost::system::error_code const &_error,
@@ -128,7 +129,6 @@ private:
std::mutex connections_mutex_;
std::map<endpoint_type, connection::ptr> connections_;
- connection::ptr current_;
const std::uint32_t buffer_shrink_threshold_;
private:
diff --git a/implementation/endpoints/include/netlink_connector.hpp b/implementation/endpoints/include/netlink_connector.hpp
index 3c77bb7..db0cbc5 100644
--- a/implementation/endpoints/include/netlink_connector.hpp
+++ b/implementation/endpoints/include/netlink_connector.hpp
@@ -73,7 +73,7 @@ public:
/// Get the underlying endpoint in the native type.
const data_type* data() const
{
- return (struct sockaddr*)&sockaddr;
+ return reinterpret_cast<const struct sockaddr*>(&sockaddr);
}
/// Get the underlying size of the endpoint in the native type.
@@ -192,7 +192,7 @@ public:
void stop();
private:
- bool has_address(const struct ifaddrmsg * ifa_struct,
+ bool has_address(struct ifaddrmsg * ifa_struct,
size_t length,
const unsigned int address);
void send_ifa_request();
diff --git a/implementation/endpoints/include/server_endpoint_impl.hpp b/implementation/endpoints/include/server_endpoint_impl.hpp
index 701d6db..710df35 100644
--- a/implementation/endpoints/include/server_endpoint_impl.hpp
+++ b/implementation/endpoints/include/server_endpoint_impl.hpp
@@ -36,6 +36,7 @@ public:
virtual ~server_endpoint_impl();
bool is_client() const;
+ void restart();
bool is_connected() const;
bool send(const uint8_t *_data, uint32_t _size, bool _flush);
@@ -64,6 +65,7 @@ protected:
std::mutex clients_mutex_;
std::map<client_t, std::map<session_t, endpoint_type> > clients_;
+ std::map<client_t, endpoint_type> clients_to_endpoint_;
boost::asio::steady_timer flush_timer_;
diff --git a/implementation/endpoints/include/tcp_server_endpoint_impl.hpp b/implementation/endpoints/include/tcp_server_endpoint_impl.hpp
index 410bca7..179825e 100644
--- a/implementation/endpoints/include/tcp_server_endpoint_impl.hpp
+++ b/implementation/endpoints/include/tcp_server_endpoint_impl.hpp
@@ -7,9 +7,9 @@
#define VSOMEIP_TCP_SERVER_ENDPOINT_IMPL_HPP
#include <map>
+#include <memory>
#include <boost/asio/ip/tcp.hpp>
-#include <boost/enable_shared_from_this.hpp>
#include <vsomeip/defines.hpp>
#include <vsomeip/export.hpp>
@@ -34,8 +34,6 @@ public:
void start();
void stop();
- void stop_all_connections(const boost::asio::ip::address &_address);
-
bool send_to(const std::shared_ptr<endpoint_definition> _target,
const byte_t *_data, uint32_t _size, bool _flush);
void send_queued(queue_iterator_type _queue_iterator);
@@ -53,17 +51,18 @@ public:
// dummies to implement endpoint_impl interface
// TODO: think about a better design!
void receive();
- void restart();
private:
- class connection: public boost::enable_shared_from_this<connection> {
+ class connection: public std::enable_shared_from_this<connection> {
public:
- typedef boost::shared_ptr<connection> ptr;
+ typedef std::shared_ptr<connection> ptr;
static ptr create(std::weak_ptr<tcp_server_endpoint_impl> _server,
std::uint32_t _max_message_size,
- std::uint32_t _buffer_shrink_threshold);
+ std::uint32_t _buffer_shrink_threshold,
+ bool _magic_cookies_enabled,
+ boost::asio::io_service & _io_service);
socket_type & get_socket();
std::unique_lock<std::mutex> get_socket_lock();
@@ -71,8 +70,6 @@ private:
void stop();
void receive();
- client_t get_client(endpoint_type _endpoint_type);
-
void send_queued(queue_iterator_type _queue_iterator);
void set_remote_info(const endpoint_type &_remote);
@@ -81,7 +78,9 @@ private:
connection(std::weak_ptr<tcp_server_endpoint_impl> _server,
std::uint32_t _max_message_size,
std::uint32_t _recv_buffer_size_initial,
- std::uint32_t _buffer_shrink_threshold);
+ std::uint32_t _buffer_shrink_threshold,
+ bool _magic_cookies_enabled,
+ boost::asio::io_service & _io_service);
void send_magic_cookie(message_buffer_ptr_t &_buffer);
bool is_magic_cookie(size_t _offset) const;
void receive_cbk(boost::system::error_code const &_error,
@@ -108,6 +107,7 @@ private:
endpoint_type remote_;
boost::asio::ip::address remote_address_;
std::uint16_t remote_port_;
+ std::atomic<bool> magic_cookies_enabled_;
};
std::mutex acceptor_mutex_;
diff --git a/implementation/endpoints/include/udp_server_endpoint_impl.hpp b/implementation/endpoints/include/udp_server_endpoint_impl.hpp
index 8d4add0..44bca0d 100644
--- a/implementation/endpoints/include/udp_server_endpoint_impl.hpp
+++ b/implementation/endpoints/include/udp_server_endpoint_impl.hpp
@@ -30,7 +30,6 @@ public:
void start();
void stop();
- void restart();
void receive();
bool send_to(const std::shared_ptr<endpoint_definition> _target,
diff --git a/implementation/endpoints/src/endpoint_impl.cpp b/implementation/endpoints/src/endpoint_impl.cpp
index 1d16d05..4e9d9aa 100644
--- a/implementation/endpoints/src/endpoint_impl.cpp
+++ b/implementation/endpoints/src/endpoint_impl.cpp
@@ -47,46 +47,45 @@ uint32_t endpoint_impl<Protocol>::find_magic_cookie(
byte_t *_buffer, size_t _size) {
bool is_found(false);
uint32_t its_offset = 0xFFFFFFFF;
- if (has_enabled_magic_cookies_) {
- uint8_t its_cookie_identifier, its_cookie_type;
-
- if (is_client()) {
- its_cookie_identifier =
- static_cast<uint8_t>(MAGIC_COOKIE_SERVICE_MESSAGE);
- its_cookie_type =
- static_cast<uint8_t>(MAGIC_COOKIE_SERVICE_MESSAGE_TYPE);
+
+ uint8_t its_cookie_identifier, its_cookie_type;
+
+ if (is_client()) {
+ its_cookie_identifier =
+ static_cast<uint8_t>(MAGIC_COOKIE_SERVICE_MESSAGE);
+ its_cookie_type =
+ static_cast<uint8_t>(MAGIC_COOKIE_SERVICE_MESSAGE_TYPE);
+ } else {
+ its_cookie_identifier =
+ static_cast<uint8_t>(MAGIC_COOKIE_CLIENT_MESSAGE);
+ its_cookie_type =
+ static_cast<uint8_t>(MAGIC_COOKIE_CLIENT_MESSAGE_TYPE);
+ }
+
+ do {
+ its_offset++; // --> first loop has "its_offset = 0"
+ if (_size > its_offset + 16) {
+ is_found = (_buffer[its_offset] == 0xFF
+ && _buffer[its_offset + 1] == 0xFF
+ && _buffer[its_offset + 2] == its_cookie_identifier
+ && _buffer[its_offset + 3] == 0x00
+ && _buffer[its_offset + 4] == 0x00
+ && _buffer[its_offset + 5] == 0x00
+ && _buffer[its_offset + 6] == 0x00
+ && _buffer[its_offset + 7] == 0x08
+ && _buffer[its_offset + 8] == 0xDE
+ && _buffer[its_offset + 9] == 0xAD
+ && _buffer[its_offset + 10] == 0xBE
+ && _buffer[its_offset + 11] == 0xEF
+ && _buffer[its_offset + 12] == 0x01
+ && _buffer[its_offset + 13] == 0x01
+ && _buffer[its_offset + 14] == its_cookie_type
+ && _buffer[its_offset + 15] == 0x00);
} else {
- its_cookie_identifier =
- static_cast<uint8_t>(MAGIC_COOKIE_CLIENT_MESSAGE);
- its_cookie_type =
- static_cast<uint8_t>(MAGIC_COOKIE_CLIENT_MESSAGE_TYPE);
+ break;
}
- do {
- its_offset++; // --> first loop has "its_offset = 0"
- if (_size > its_offset + 16) {
- is_found = (_buffer[its_offset] == 0xFF
- && _buffer[its_offset + 1] == 0xFF
- && _buffer[its_offset + 2] == its_cookie_identifier
- && _buffer[its_offset + 3] == 0x00
- && _buffer[its_offset + 4] == 0x00
- && _buffer[its_offset + 5] == 0x00
- && _buffer[its_offset + 6] == 0x00
- && _buffer[its_offset + 7] == 0x08
- && _buffer[its_offset + 8] == 0xDE
- && _buffer[its_offset + 9] == 0xAD
- && _buffer[its_offset + 10] == 0xBE
- && _buffer[its_offset + 11] == 0xEF
- && _buffer[its_offset + 12] == 0x01
- && _buffer[its_offset + 13] == 0x01
- && _buffer[its_offset + 14] == its_cookie_type
- && _buffer[its_offset + 15] == 0x00);
- } else {
- break;
- }
-
- } while (!is_found);
- }
+ } while (!is_found);
return (is_found ? its_offset : 0xFFFFFFFF);
}
diff --git a/implementation/endpoints/src/local_client_endpoint_impl.cpp b/implementation/endpoints/src/local_client_endpoint_impl.cpp
index e9de8f7..3238153 100644
--- a/implementation/endpoints/src/local_client_endpoint_impl.cpp
+++ b/implementation/endpoints/src/local_client_endpoint_impl.cpp
@@ -107,7 +107,6 @@ void local_client_endpoint_impl::connect() {
}
void local_client_endpoint_impl::receive() {
-#ifndef _WIN32
std::lock_guard<std::mutex> its_lock(socket_mutex_);
if (socket_->is_open()) {
socket_->async_receive(
@@ -122,7 +121,6 @@ void local_client_endpoint_impl::receive() {
)
);
}
-#endif
}
void local_client_endpoint_impl::send_queued() {
diff --git a/implementation/endpoints/src/local_server_endpoint_impl.cpp b/implementation/endpoints/src/local_server_endpoint_impl.cpp
index 0e9bd4f..5a44f2f 100644
--- a/implementation/endpoints/src/local_server_endpoint_impl.cpp
+++ b/implementation/endpoints/src/local_server_endpoint_impl.cpp
@@ -32,7 +32,6 @@ local_server_endpoint_impl::local_server_endpoint_impl(
std::uint32_t _buffer_shrink_threshold)
: local_server_endpoint_base_impl(_host, _local, _io, _max_message_size),
acceptor_(_io),
- current_(nullptr),
buffer_shrink_threshold_(_buffer_shrink_threshold) {
is_supporting_magic_cookies_ = false;
@@ -61,7 +60,6 @@ local_server_endpoint_impl::local_server_endpoint_impl(
std::uint32_t _buffer_shrink_threshold)
: local_server_endpoint_base_impl(_host, _local, _io, _max_message_size),
acceptor_(_io),
- current_(nullptr),
buffer_shrink_threshold_(_buffer_shrink_threshold) {
is_supporting_magic_cookies_ = false;
@@ -86,21 +84,22 @@ bool local_server_endpoint_impl::is_local() const {
void local_server_endpoint_impl::start() {
std::lock_guard<std::mutex> its_lock(acceptor_mutex_);
if (acceptor_.is_open()) {
- current_ = connection::create(
+ connection::ptr new_connection = connection::create(
std::dynamic_pointer_cast<local_server_endpoint_impl>(
shared_from_this()), max_message_size_,
- buffer_shrink_threshold_);
+ buffer_shrink_threshold_,
+ service_);
{
- std::unique_lock<std::mutex> its_lock(current_->get_socket_lock());
+ std::unique_lock<std::mutex> its_lock(new_connection->get_socket_lock());
acceptor_.async_accept(
- current_->get_socket(),
+ new_connection->get_socket(),
std::bind(
&local_server_endpoint_impl::accept_cbk,
std::dynamic_pointer_cast<
local_server_endpoint_impl
>(shared_from_this()),
- current_,
+ new_connection,
std::placeholders::_1
)
);
@@ -148,10 +147,6 @@ void local_server_endpoint_impl::receive() {
// intentionally left empty
}
-void local_server_endpoint_impl::restart() {
- current_->start();
-}
-
bool local_server_endpoint_impl::get_default_target(
service_t,
local_server_endpoint_impl::endpoint_type &) const {
@@ -187,8 +182,8 @@ void local_server_endpoint_impl::accept_cbk(
if (its_host->get_configuration()->is_security_enabled()) {
std::unique_lock<std::mutex> its_socket_lock(_connection->get_socket_lock());
socket_type &new_connection_socket = _connection->get_socket();
- uid_t uid;
- gid_t gid;
+ uid_t uid(0);
+ gid_t gid(0);
client_t client = credentials::receive_credentials(
new_connection_socket.native(), uid, gid);
if (!its_host->check_credentials(client, uid, gid)) {
@@ -232,8 +227,9 @@ local_server_endpoint_impl::connection::connection(
std::weak_ptr<local_server_endpoint_impl> _server,
std::uint32_t _max_message_size,
std::uint32_t _initial_recv_buffer_size,
- std::uint32_t _buffer_shrink_threshold)
- : socket_(_server.lock()->service_),
+ std::uint32_t _buffer_shrink_threshold,
+ boost::asio::io_service &_io_service)
+ : socket_(_io_service),
server_(_server),
recv_buffer_size_initial_(_initial_recv_buffer_size + 8),
max_message_size_(_max_message_size),
@@ -249,13 +245,14 @@ local_server_endpoint_impl::connection::ptr
local_server_endpoint_impl::connection::create(
std::weak_ptr<local_server_endpoint_impl> _server,
std::uint32_t _max_message_size,
- std::uint32_t _buffer_shrink_threshold) {
+ std::uint32_t _buffer_shrink_threshold,
+ boost::asio::io_service &_io_service) {
const std::uint32_t its_initial_buffer_size = VSOMEIP_COMMAND_HEADER_SIZE
+ VSOMEIP_MAX_LOCAL_MESSAGE_SIZE
+ static_cast<std::uint32_t>(sizeof(instance_t) + sizeof(bool)
+ sizeof(bool));
return ptr(new connection(_server, _max_message_size, its_initial_buffer_size,
- _buffer_shrink_threshold));
+ _buffer_shrink_threshold, _io_service));
}
local_server_endpoint_impl::socket_type &
@@ -281,8 +278,8 @@ void local_server_endpoint_impl::connection::start() {
}
const std::size_t its_required_capacity(recv_buffer_size_ + missing_capacity_);
if (its_capacity < its_required_capacity) {
- recv_buffer_.reserve(its_required_capacity);
- recv_buffer_.resize(its_required_capacity, 0x0);
+ recv_buffer_.reserve(its_required_capacity);
+ recv_buffer_.resize(its_required_capacity, 0x0);
}
buffer_size = missing_capacity_;
missing_capacity_ = 0;
diff --git a/implementation/endpoints/src/netlink_connector.cpp b/implementation/endpoints/src/netlink_connector.cpp
index 2d832c8..eb43b74 100644
--- a/implementation/endpoints/src/netlink_connector.cpp
+++ b/implementation/endpoints/src/netlink_connector.cpp
@@ -85,7 +85,7 @@ void netlink_connector::receive_cbk(boost::system::error_code const &_error,
if (!_error) {
size_t len = _bytes;
- unsigned int address;
+ unsigned int address(0);
if (address_.is_v4()) {
inet_pton(AF_INET, address_.to_string().c_str(), &address);
} else {
@@ -247,12 +247,12 @@ void netlink_connector::send_ifi_request() {
}
}
-bool netlink_connector::has_address(const struct ifaddrmsg * ifa_struct,
+bool netlink_connector::has_address(struct ifaddrmsg * ifa_struct,
size_t length,
const unsigned int address) {
struct rtattr *retrta;
- retrta = (struct rtattr *)IFA_RTA(ifa_struct);
+ retrta = static_cast<struct rtattr *>(IFA_RTA(ifa_struct));
while RTA_OK(retrta, length) {
if (retrta->rta_type == IFA_ADDRESS) {
char pradd[128];
diff --git a/implementation/endpoints/src/server_endpoint_impl.cpp b/implementation/endpoints/src/server_endpoint_impl.cpp
index 1631c5d..3d00ca4 100644
--- a/implementation/endpoints/src/server_endpoint_impl.cpp
+++ b/implementation/endpoints/src/server_endpoint_impl.cpp
@@ -46,6 +46,11 @@ bool server_endpoint_impl<Protocol>::is_client() const {
}
template<typename Protocol>
+void server_endpoint_impl<Protocol>::restart() {
+ // intentionally left blank
+}
+
+template<typename Protocol>
bool server_endpoint_impl<Protocol>::is_connected() const {
return true;
}
@@ -88,6 +93,11 @@ bool server_endpoint_impl<Protocol>::send(const uint8_t *_data,
if (found_session != found_client->second.end()) {
its_target = found_session->second;
is_valid_target = true;
+ found_client->second.erase(its_session);
+ } else {
+ VSOMEIP_WARNING << "server_endpoint::send: session_id 0x"
+ << std::hex << its_session
+ << " not found for client 0x" << its_client;
}
} else {
is_valid_target = get_default_target(its_service, its_target);
diff --git a/implementation/endpoints/src/tcp_client_endpoint_impl.cpp b/implementation/endpoints/src/tcp_client_endpoint_impl.cpp
index cee27ae..61a8b48 100644
--- a/implementation/endpoints/src/tcp_client_endpoint_impl.cpp
+++ b/implementation/endpoints/src/tcp_client_endpoint_impl.cpp
@@ -396,7 +396,9 @@ void tcp_client_endpoint_impl::receive_cbk(
if (_error == boost::asio::error::connection_reset ||
_error == boost::asio::error::eof ||
_error == boost::asio::error::timed_out) {
- VSOMEIP_WARNING << "tcp_client_endpoint receive_cbk error detected: " << _error.message();
+ if(_error == boost::asio::error::timed_out) {
+ VSOMEIP_WARNING << "tcp_client_endpoint receive_cbk: " << _error.message();
+ }
shutdown_and_close_socket_unlocked();
} else {
its_lock.unlock();
diff --git a/implementation/endpoints/src/tcp_server_endpoint_impl.cpp b/implementation/endpoints/src/tcp_server_endpoint_impl.cpp
index 251137b..3f4e548 100644
--- a/implementation/endpoints/src/tcp_server_endpoint_impl.cpp
+++ b/implementation/endpoints/src/tcp_server_endpoint_impl.cpp
@@ -54,7 +54,8 @@ void tcp_server_endpoint_impl::start() {
connection::ptr new_connection = connection::create(
std::dynamic_pointer_cast<tcp_server_endpoint_impl>(
shared_from_this()), max_message_size_,
- buffer_shrink_threshold_);
+ buffer_shrink_threshold_, has_enabled_magic_cookies_,
+ service_);
{
std::unique_lock<std::mutex> its_socket_lock(new_connection->get_socket_lock());
@@ -85,22 +86,6 @@ void tcp_server_endpoint_impl::stop() {
}
}
-void tcp_server_endpoint_impl::stop_all_connections(const boost::asio::ip::address &_address) {
- std::lock_guard<std::mutex> its_lock(connections_mutex_);
- endpoint_type type;
-
- for (const auto &c : connections_) {
- if(c.first.address() == _address) {
- VSOMEIP_INFO << "Stopping connections for " << _address.to_string()
- << " : " << std::dec << c.first.port();
- c.second->stop();
- type = c.first;
- }
- }
- connections_.erase(type);
-}
-
-
bool tcp_server_endpoint_impl::send_to(
const std::shared_ptr<endpoint_definition> _target,
const byte_t *_data,
@@ -215,8 +200,10 @@ tcp_server_endpoint_impl::connection::connection(
std::weak_ptr<tcp_server_endpoint_impl> _server,
std::uint32_t _max_message_size,
std::uint32_t _initial_recv_buffer_size,
- std::uint32_t _buffer_shrink_threshold) :
- socket_(_server.lock()->service_),
+ std::uint32_t _buffer_shrink_threshold,
+ bool _magic_cookies_enabled,
+ boost::asio::io_service &_io_service) :
+ socket_(_io_service),
server_(_server),
max_message_size_(_max_message_size),
recv_buffer_size_initial_(_initial_recv_buffer_size),
@@ -225,19 +212,24 @@ tcp_server_endpoint_impl::connection::connection(
missing_capacity_(0),
shrink_count_(0),
buffer_shrink_threshold_(_buffer_shrink_threshold),
- remote_port_(0) {
+ remote_port_(0),
+ magic_cookies_enabled_(_magic_cookies_enabled) {
}
tcp_server_endpoint_impl::connection::ptr
tcp_server_endpoint_impl::connection::create(
std::weak_ptr<tcp_server_endpoint_impl> _server,
- std::uint32_t _max_message_size, std::uint32_t _buffer_shrink_threshold) {
+ std::uint32_t _max_message_size,
+ std::uint32_t _buffer_shrink_threshold,
+ bool _magic_cookies_enabled,
+ boost::asio::io_service & _io_service) {
const std::uint32_t its_initial_receveive_buffer_size =
VSOMEIP_SOMEIP_HEADER_SIZE + 8 + MAGIC_COOKIE_SIZE + 8
+ VSOMEIP_MAX_TCP_MESSAGE_SIZE;
return ptr(new connection(_server, _max_message_size,
its_initial_receveive_buffer_size,
- _buffer_shrink_threshold));
+ _buffer_shrink_threshold, _magic_cookies_enabled,
+ _io_service));
}
tcp_server_endpoint_impl::socket_type &
@@ -310,7 +302,7 @@ void tcp_server_endpoint_impl::connection::send_queued(
return;
}
message_buffer_ptr_t its_buffer = _queue_iterator->second.front();
- if (its_server->has_enabled_magic_cookies_) {
+ if (magic_cookies_enabled_) {
send_magic_cookie(its_buffer);
}
@@ -384,9 +376,9 @@ void tcp_server_endpoint_impl::connection::receive_cbk(
if (has_full_message) {
bool needs_forwarding(true);
if (is_magic_cookie(its_iteration_gap)) {
- its_server->has_enabled_magic_cookies_ = true;
+ magic_cookies_enabled_ = true;
} else {
- if (its_server->has_enabled_magic_cookies_) {
+ if (magic_cookies_enabled_) {
uint32_t its_offset
= its_server->find_magic_cookie(&recv_buffer_[its_iteration_gap],
recv_buffer_size_);
@@ -416,9 +408,10 @@ void tcp_server_endpoint_impl::connection::receive_cbk(
sizeof(session_t));
its_server->clients_mutex_.lock();
its_server->clients_[its_client][its_session] = remote_;
+ its_server->clients_to_endpoint_[its_client] = remote_;
its_server->clients_mutex_.unlock();
}
- if (!its_server->has_enabled_magic_cookies_) {
+ if (!magic_cookies_enabled_) {
its_host->on_message(&recv_buffer_[its_iteration_gap],
current_message_size, its_server.get(),
boost::asio::ip::address(),
@@ -439,7 +432,7 @@ void tcp_server_endpoint_impl::connection::receive_cbk(
missing_capacity_ = 0;
recv_buffer_size_ -= current_message_size;
its_iteration_gap += current_message_size;
- } else if (its_server->has_enabled_magic_cookies_ && recv_buffer_size_ > 0){
+ } else if (magic_cookies_enabled_ && recv_buffer_size_ > 0) {
uint32_t its_offset =
its_server->find_magic_cookie(&recv_buffer_[its_iteration_gap],
recv_buffer_size_);
@@ -468,7 +461,7 @@ void tcp_server_endpoint_impl::connection::receive_cbk(
recv_buffer_size_ = 0;
recv_buffer_.resize(recv_buffer_size_initial_, 0x0);
recv_buffer_.shrink_to_fit();
- if (its_server->has_enabled_magic_cookies_) {
+ if (magic_cookies_enabled_) {
VSOMEIP_ERROR << "Received a TCP message which exceeds "
<< "maximum message size ("
<< std::dec << current_message_size
@@ -524,7 +517,9 @@ void tcp_server_endpoint_impl::connection::receive_cbk(
if (_error == boost::asio::error::eof
|| _error == boost::asio::error::connection_reset
|| _error == boost::asio::error::timed_out) {
- VSOMEIP_WARNING << "tcp_server_endpoint receive_cbk error detected: " << _error.message();
+ if(_error == boost::asio::error::timed_out) {
+ VSOMEIP_WARNING << "tcp_server_endpoint receive_cbk: " << _error.message();
+ }
{
std::lock_guard<std::mutex> its_lock(its_server->connections_mutex_);
stop();
@@ -546,33 +541,13 @@ void tcp_server_endpoint_impl::connection::calculate_shrink_count() {
}
client_t tcp_server_endpoint_impl::get_client(std::shared_ptr<endpoint_definition> _endpoint) {
- endpoint_type endpoint(_endpoint->get_address(), _endpoint->get_port());
- {
- std::lock_guard<std::mutex> its_lock(connections_mutex_);
- auto its_remote = connections_.find(endpoint);
- if (its_remote != connections_.end()) {
- return its_remote->second->get_client(endpoint);
- }
- }
- return 0;
-}
-
-client_t tcp_server_endpoint_impl::connection::get_client(endpoint_type _endpoint_type) {
- std::shared_ptr<tcp_server_endpoint_impl> its_server(server_.lock());
- if (!its_server) {
- VSOMEIP_TRACE << "tcp_server_endpoint_impl::connection::get_client "
- " couldn't lock server_";
- return 0;
- }
- std::lock_guard<std::mutex> its_lock(its_server->clients_mutex_);
- for (const auto its_client : its_server->clients_) {
- for (const auto its_session : its_server->clients_[its_client.first]) {
- auto endpoint = its_session.second;
- if (endpoint == _endpoint_type) {
- // TODO: Check system byte order before convert!
- client_t client = client_t(its_client.first << 8 | its_client.first >> 8);
- return client;
- }
+ const endpoint_type endpoint(_endpoint->get_address(), _endpoint->get_port());
+ std::lock_guard<std::mutex> its_lock(clients_mutex_);
+ for (const auto its_client : clients_to_endpoint_) {
+ if (its_client.second == endpoint) {
+ // TODO: Check system byte order before convert!
+ client_t client = client_t(its_client.first << 8 | its_client.first >> 8);
+ return client;
}
}
return 0;
@@ -646,8 +621,4 @@ void tcp_server_endpoint_impl::receive() {
// intentionally left empty
}
-void tcp_server_endpoint_impl::restart() {
- // intentionally left empty
-}
-
} // namespace vsomeip
diff --git a/implementation/endpoints/src/udp_server_endpoint_impl.cpp b/implementation/endpoints/src/udp_server_endpoint_impl.cpp
index 7a7a2e4..bd323e4 100644
--- a/implementation/endpoints/src/udp_server_endpoint_impl.cpp
+++ b/implementation/endpoints/src/udp_server_endpoint_impl.cpp
@@ -110,10 +110,6 @@ void udp_server_endpoint_impl::receive() {
}
}
-void udp_server_endpoint_impl::restart() {
- receive();
-}
-
bool udp_server_endpoint_impl::send_to(
const std::shared_ptr<endpoint_definition> _target,
const byte_t *_data, uint32_t _size, bool _flush) {
@@ -313,6 +309,7 @@ void udp_server_endpoint_impl::receive_cbk(
sizeof(session_t));
clients_mutex_.lock();
clients_[its_client][its_session] = remote_;
+ clients_to_endpoint_[its_client] = remote_;
clients_mutex_.unlock();
}
service_t its_service = VSOMEIP_BYTES_TO_WORD(recv_buffer_[i + VSOMEIP_SERVICE_POS_MIN],
@@ -341,7 +338,7 @@ void udp_server_endpoint_impl::receive_cbk(
remaining_bytes = 0;
}
} while (remaining_bytes > 0);
- restart();
+ receive();
} else {
receive();
}
@@ -349,15 +346,13 @@ void udp_server_endpoint_impl::receive_cbk(
}
client_t udp_server_endpoint_impl::get_client(std::shared_ptr<endpoint_definition> _endpoint) {
- endpoint_type endpoint(_endpoint->get_address(), _endpoint->get_port());
+ const endpoint_type endpoint(_endpoint->get_address(), _endpoint->get_port());
std::lock_guard<std::mutex> its_lock(clients_mutex_);
- for (auto its_client : clients_) {
- for (auto its_session : clients_[its_client.first]) {
- if (endpoint == its_session.second) {
- // TODO: Check system byte order before convert!
- client_t client = client_t(its_client.first << 8 | its_client.first >> 8);
- return client;
- }
+ for (const auto its_client : clients_to_endpoint_) {
+ if (its_client.second == endpoint) {
+ // TODO: Check system byte order before convert!
+ client_t client = client_t(its_client.first << 8 | its_client.first >> 8);
+ return client;
}
}
return 0;
diff --git a/implementation/logging/include/dlt_sink_backend.hpp b/implementation/logging/include/dlt_sink_backend.hpp
index 30ed027..58983a6 100644
--- a/implementation/logging/include/dlt_sink_backend.hpp
+++ b/implementation/logging/include/dlt_sink_backend.hpp
@@ -37,7 +37,7 @@ private:
#ifdef USE_DLT
DltLogLevelType level_as_dlt(logging::trivial::severity_level _level);
- DLT_DECLARE_CONTEXT(dlt_);
+ DLT_DECLARE_CONTEXT(dlt_)
#endif
};
diff --git a/implementation/message/include/message_base_impl.hpp b/implementation/message/include/message_base_impl.hpp
index 812c527..ad42261 100644
--- a/implementation/message/include/message_base_impl.hpp
+++ b/implementation/message/include/message_base_impl.hpp
@@ -62,10 +62,14 @@ public:
VSOMEIP_EXPORT message * get_owner() const;
VSOMEIP_EXPORT void set_owner(message *_owner);
+ VSOMEIP_EXPORT bool is_valid_crc() const;
+ VSOMEIP_EXPORT void set_is_valid_crc(bool _is_valid_crc);
+
protected: // members
message_header_impl header_;
bool is_reliable_;
bool is_initial_;
+ bool is_valid_crc_;
};
} // namespace vsomeip
diff --git a/implementation/message/src/message_base_impl.cpp b/implementation/message/src/message_base_impl.cpp
index 2d690ff..e32a914 100644
--- a/implementation/message/src/message_base_impl.cpp
+++ b/implementation/message/src/message_base_impl.cpp
@@ -10,7 +10,8 @@ namespace vsomeip {
message_base_impl::message_base_impl()
: is_reliable_(false),
- is_initial_(false) {
+ is_initial_(false),
+ is_valid_crc_(true) {
header_.set_owner(this);
}
@@ -118,4 +119,13 @@ void message_base_impl::set_initial(bool _is_initial) {
is_initial_ = _is_initial;
}
+bool message_base_impl::is_valid_crc() const {
+ return is_valid_crc_;
+}
+
+void message_base_impl::set_is_valid_crc(bool _is_valid_crc) {
+ is_valid_crc_ = _is_valid_crc;
+}
+
+
} // namespace vsomeip
diff --git a/implementation/plugin/include/plugin_manager.hpp b/implementation/plugin/include/plugin_manager.hpp
new file mode 100644
index 0000000..75ae8d7
--- /dev/null
+++ b/implementation/plugin/include/plugin_manager.hpp
@@ -0,0 +1,56 @@
+// Copyright (C) 2016-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 VSOMEIP_PLUGIN_MANAGER_HPP
+#define VSOMEIP_PLUGIN_MANAGER_HPP
+
+#include <map>
+#include <chrono>
+#include <mutex>
+#include <set>
+
+#include <vsomeip/constants.hpp>
+#include <vsomeip/export.hpp>
+#include <vsomeip/plugin.hpp>
+
+namespace vsomeip {
+
+class plugin_manager {
+public:
+ VSOMEIP_EXPORT static std::shared_ptr<plugin_manager> get();
+
+ plugin_manager();
+
+ ~plugin_manager();
+
+ VSOMEIP_EXPORT void load_plugins();
+
+ VSOMEIP_EXPORT std::shared_ptr<plugin> get_plugin(plugin_type_e _type);
+
+ VSOMEIP_EXPORT std::shared_ptr<plugin> load_plugin(
+ const std::string _library, plugin_type_e _type,
+ const uint32_t _version);
+
+ VSOMEIP_EXPORT bool unload_plugin(plugin_type_e _type);
+
+private:
+ void add_plugin(const std::shared_ptr<plugin> &_plugin);
+
+ void * load_library(const std::string &_path);
+ void * load_symbol(void * _handle, const std::string &_symbol);
+
+ bool plugins_loaded_;
+ std::mutex loader_mutex_;
+
+ std::map<plugin_type_e, std::vector<std::shared_ptr<plugin> > > plugins_;
+ std::map<plugin_type_e, std::string> plugin_names_;
+ std::map<plugin_type_e, void*> handles_;
+ std::mutex plugins_mutex_;
+
+ static std::shared_ptr<plugin_manager> the_plugin_manager__;
+};
+}
+
+#endif // VSOMEIP_PLUGIN_MANAGER_HPP
diff --git a/implementation/plugin/src/plugin_manager.cpp b/implementation/plugin/src/plugin_manager.cpp
new file mode 100644
index 0000000..f81d7b2
--- /dev/null
+++ b/implementation/plugin/src/plugin_manager.cpp
@@ -0,0 +1,212 @@
+// Copyright (C) 2016-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 <sstream>
+#include <vector>
+#include <stdlib.h>
+#include <iostream>
+
+#ifdef _WIN32
+ #ifndef _WINSOCKAPI_
+ #include <Windows.h>
+ #endif
+#else
+ #include <dlfcn.h>
+#endif
+
+#include <vsomeip/plugins/application_plugin.hpp>
+#include <vsomeip/plugins/pre_configuration_plugin.hpp>
+
+#include "../include/plugin_manager.hpp"
+#include "../../configuration/include/internal.hpp"
+#include "../../logging/include/logger.hpp"
+#include "../../utility/include/utility.hpp"
+
+namespace vsomeip {
+
+std::shared_ptr<plugin_manager> plugin_manager::the_plugin_manager__ =
+ std::make_shared<plugin_manager>();
+
+std::shared_ptr<plugin_manager> plugin_manager::get() {
+ return the_plugin_manager__;
+}
+
+plugin_manager::plugin_manager() :
+ plugins_loaded_(false) {
+ plugin_names_[plugin_type_e::CONFIGURATION_PLUGIN] = VSOMEIP_CFG_LIBRARY;
+ plugin_names_[plugin_type_e::SD_RUNTIME_PLUGIN] = VSOMEIP_SD_LIBRARY;
+}
+
+plugin_manager::~plugin_manager() {
+ handles_.clear();
+ plugins_.clear();
+ plugin_names_.clear();
+}
+
+void plugin_manager::load_plugins() {
+ {
+ std::lock_guard<std::mutex> its_lock_start_stop(loader_mutex_);
+ if (plugins_loaded_) {
+ return;
+ }
+ plugins_loaded_ = true;
+ }
+
+ // Get plug-ins libraries from environment
+ std::vector<std::string> plugins;
+ const char *its_plugins = getenv(VSOMEIP_ENV_LOAD_PLUGINS);
+ if (nullptr != its_plugins) {
+ std::string token;
+ std::stringstream ss(its_plugins);
+ while(std::getline(ss, token, ',')) {
+ plugins.push_back(token);
+ }
+ }
+
+ std::lock_guard<std::mutex> its_lock_start_stop(plugins_mutex_);
+ // Load plug-in info from libraries parsed before
+ for (auto plugin_name : plugins) {
+ void* handle = load_library(plugin_name);
+ plugin_init_func its_init_func = reinterpret_cast<plugin_init_func>(
+ load_symbol(handle, VSOMEIP_PLUGIN_INIT_SYMBOL));
+ if (its_init_func) {
+ create_plugin_func its_create_func = (*its_init_func)();
+ if (its_create_func) {
+ auto its_plugin = (*its_create_func)();
+ if (its_plugin) {
+ handles_[its_plugin->get_plugin_type()] = handle;
+ switch (its_plugin->get_plugin_type()) {
+ case plugin_type_e::APPLICATION_PLUGIN:
+ if (its_plugin->get_plugin_version()
+ == VSOMEIP_APPLICATION_PLUGIN_VERSION) {
+ add_plugin(its_plugin);
+ } else {
+ VSOMEIP_ERROR << "Plugin version mismatch. "
+ << "Ignoring application plugin "
+ << its_plugin->get_plugin_name();
+ }
+ break;
+ case plugin_type_e::PRE_CONFIGURATION_PLUGIN:
+ if (its_plugin->get_plugin_version()
+ == VSOMEIP_PRE_CONFIGURATION_PLUGIN_VERSION) {
+ add_plugin(its_plugin);
+ } else {
+ VSOMEIP_ERROR << "Plugin version mismatch. Ignoring "
+ << "pre-configuration plugin "
+ << its_plugin->get_plugin_name();
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ }
+ }
+}
+
+std::shared_ptr<plugin> plugin_manager::get_plugin(plugin_type_e _type) {
+ std::lock_guard<std::mutex> its_lock_start_stop(plugins_mutex_);
+ if (plugins_[_type].size()) {
+ return plugins_[_type][0];
+ } else {
+ auto its_name = plugin_names_.find(_type);
+ if (its_name != plugin_names_.end()) {
+ return load_plugin(its_name->second, _type, 1);
+ }
+ }
+ return nullptr;
+}
+
+std::shared_ptr<plugin> plugin_manager::load_plugin(const std::string _library,
+ plugin_type_e _type, uint32_t _version) {
+ void* handle = load_library(_library);
+ plugin_init_func its_init_func = reinterpret_cast<plugin_init_func>(
+ load_symbol(handle, VSOMEIP_PLUGIN_INIT_SYMBOL));
+ if (its_init_func) {
+ create_plugin_func its_create_func = (*its_init_func)();
+ if (its_create_func) {
+ handles_[_type] = handle;
+ auto its_plugin = (*its_create_func)();
+ if (its_plugin) {
+ if (its_plugin->get_plugin_type() == _type
+ && its_plugin->get_plugin_version() == _version) {
+ add_plugin(its_plugin);
+ return its_plugin;
+ } else {
+ VSOMEIP_ERROR << "Plugin version mismatch. Ignoring plugin "
+ << its_plugin->get_plugin_name();
+ }
+ }
+ }
+ }
+ return nullptr;
+}
+
+bool plugin_manager::unload_plugin(plugin_type_e _type) {
+ std::lock_guard<std::mutex> its_lock_start_stop(plugins_mutex_);
+ const auto found_handle = handles_.find(_type);
+ if (found_handle != handles_.end()) {
+#ifdef _WIN32
+ FreeLibrary((HMODULE)found_handle->second);
+#else
+ if (dlclose(found_handle->second)) {
+ VSOMEIP_ERROR << "Unloading failed: (" << dlerror() << ")";
+ }
+#endif
+ } else {
+ VSOMEIP_ERROR << "plugin_manager::unload_plugin didn't find plugin"
+ << " type:" << (int)_type;
+ return false;
+ }
+ return plugins_.erase(_type);
+}
+
+void plugin_manager::add_plugin(const std::shared_ptr<plugin> &_plugin) {
+ plugins_[_plugin->get_plugin_type()].push_back(_plugin);
+}
+
+void * plugin_manager::load_library(const std::string &_path) {
+#ifdef _WIN32
+ return LoadLibrary(_path.c_str());
+#else
+ return dlopen(_path.c_str(), RTLD_LAZY | RTLD_GLOBAL);
+#endif
+}
+
+void * plugin_manager::load_symbol(void * _handle,
+ const std::string &_symbol) {
+ void * its_symbol = 0;
+#ifdef _WIN32
+ HINSTANCE hDLL = (HINSTANCE)_handle;
+ if (hDLL != NULL) {
+
+ typedef UINT(CALLBACK* LPFNDLLFUNC1)(DWORD, UINT);
+
+ LPFNDLLFUNC1 lpfnDllFunc1 = (LPFNDLLFUNC1)GetProcAddress(hDLL, _symbol.c_str());
+ if (!lpfnDllFunc1) {
+ FreeLibrary(hDLL);
+ std::cerr << "Loading symbol \"" << _symbol << "\" failed (" << GetLastError() << ")" << std::endl;
+ }
+ else {
+ its_symbol = lpfnDllFunc1;
+ }
+ }
+#else
+ if (0 != _handle) {
+ its_symbol = dlsym(_handle, _symbol.c_str());
+ const char *dlsym_error = dlerror();
+ if (dlsym_error) {
+ VSOMEIP_INFO << "Cannot load symbol : " << _symbol << " : " << dlsym_error;
+ dlclose(_handle);
+ }
+ } else {
+ VSOMEIP_ERROR << "Loading failed: (" << dlerror() << ")";
+ }
+#endif
+ return (its_symbol);
+}
+
+}
diff --git a/implementation/routing/include/event.hpp b/implementation/routing/include/event.hpp
index 93eee34..e493eff 100644
--- a/implementation/routing/include/event.hpp
+++ b/implementation/routing/include/event.hpp
@@ -105,6 +105,8 @@ public:
std::set<client_t> get_subscribers(eventgroup_t _eventgroup);
+ bool is_subscribed(client_t _client);
+
private:
void update_cbk(boost::system::error_code const &_error);
void notify(bool _flush);
diff --git a/implementation/routing/include/eventgroupinfo.hpp b/implementation/routing/include/eventgroupinfo.hpp
index ae3ab87..0db929c 100644
--- a/implementation/routing/include/eventgroupinfo.hpp
+++ b/implementation/routing/include/eventgroupinfo.hpp
@@ -74,6 +74,8 @@ public:
VSOMEIP_EXPORT uint8_t get_threshold() const;
VSOMEIP_EXPORT void set_threshold(uint8_t _threshold);
+ VSOMEIP_EXPORT std::unique_lock<std::mutex> get_subscription_lock();
+
private:
std::atomic<major_version_t> major_;
std::atomic<ttl_t> ttl_;
@@ -90,6 +92,7 @@ private:
std::list<target_t> multicast_targets_;
std::atomic<uint8_t> threshold_;
+ std::mutex subscription_mutex_;
};
} // namespace vsomeip
diff --git a/implementation/routing/include/routing_manager.hpp b/implementation/routing/include/routing_manager.hpp
index 8c408c3..b14f162 100644
--- a/implementation/routing/include/routing_manager.hpp
+++ b/implementation/routing/include/routing_manager.hpp
@@ -62,13 +62,14 @@ public:
bool _flush) = 0;
virtual bool send(client_t _client, const byte_t *_data, uint32_t _size,
- instance_t _instance, bool _flush, bool _reliable) = 0;
+ instance_t _instance, bool _flush, bool _reliable, bool _is_valid_crc = true) = 0;
virtual bool send_to(const std::shared_ptr<endpoint_definition> &_target,
std::shared_ptr<message>, bool _flush) = 0;
virtual bool send_to(const std::shared_ptr<endpoint_definition> &_target,
- const byte_t *_data, uint32_t _size, bool _flush) = 0;
+ const byte_t *_data, uint32_t _size, instance_t _instance,
+ bool _flush) = 0;
virtual void register_event(client_t _client, service_t _service,
instance_t _instance, event_t _event,
diff --git a/implementation/routing/include/routing_manager_base.hpp b/implementation/routing/include/routing_manager_base.hpp
index e0ad57e..e5d7f11 100644
--- a/implementation/routing/include/routing_manager_base.hpp
+++ b/implementation/routing/include/routing_manager_base.hpp
@@ -96,7 +96,7 @@ public:
bool _flush);
virtual bool send(client_t _client, const byte_t *_data, uint32_t _size,
- instance_t _instance, bool _flush, bool _reliable) = 0;
+ instance_t _instance, bool _flush, bool _reliable, bool _is_valid_crc = true) = 0;
// Endpoint host ~> will be implemented by routing_manager_impl/_proxy/
virtual void on_connect(std::shared_ptr<endpoint> _endpoint) = 0;
@@ -151,15 +151,16 @@ protected:
bool send_local_notification(client_t _client,
const byte_t *_data, uint32_t _size, instance_t _instance,
- bool _flush = true, bool _reliable = false);
+ bool _flush = true, bool _reliable = false, bool _is_valid_crc = true);
bool send_local(
std::shared_ptr<endpoint> &_target, client_t _client,
const byte_t *_data, uint32_t _size, instance_t _instance,
- bool _flush, bool _reliable, uint8_t _command) const;
+ bool _flush, bool _reliable, uint8_t _command, bool _is_valid_crc = true) const;
bool insert_subscription(service_t _service, instance_t _instance,
- eventgroup_t _eventgroup, event_t _event, client_t _client);
+ eventgroup_t _eventgroup, event_t _event, client_t _client,
+ std::set<event_t> *_already_subscribed_events);
std::shared_ptr<deserializer> get_deserializer();
void put_deserializer(std::shared_ptr<deserializer>);
@@ -184,7 +185,8 @@ protected:
void notify_one_current_value(client_t _client, service_t _service,
instance_t _instance,
- eventgroup_t _eventgroup, event_t _event);
+ eventgroup_t _eventgroup, event_t _event,
+ const std::set<event_t> &_events_to_exclude);
void send_identify_request(service_t _service, instance_t _instance,
major_version_t _major, bool _reliable);
diff --git a/implementation/routing/include/routing_manager_host.hpp b/implementation/routing/include/routing_manager_host.hpp
index 4b0edad..532b0db 100644
--- a/implementation/routing/include/routing_manager_host.hpp
+++ b/implementation/routing/include/routing_manager_host.hpp
@@ -36,6 +36,8 @@ public:
client_t _client, bool _subscribed) = 0;
virtual void on_subscription_error(service_t _service, instance_t _instance,
eventgroup_t _eventgroup, uint16_t _error) = 0;
+ virtual void on_subscription_status(service_t _service, instance_t _instance,
+ eventgroup_t _eventgroup, event_t _event, uint16_t _error) = 0;
virtual void send(std::shared_ptr<message> _message, bool _flush) = 0;
};
diff --git a/implementation/routing/include/routing_manager_impl.hpp b/implementation/routing/include/routing_manager_impl.hpp
index 69a8412..0150d15 100644
--- a/implementation/routing/include/routing_manager_impl.hpp
+++ b/implementation/routing/include/routing_manager_impl.hpp
@@ -15,6 +15,7 @@
#include <boost/asio/ip/address.hpp>
#include <boost/asio/io_service.hpp>
+#include <boost/asio/steady_timer.hpp>
#include <vsomeip/primitive_types.hpp>
#include <vsomeip/handler.hpp>
@@ -83,13 +84,14 @@ public:
bool send(client_t _client, std::shared_ptr<message> _message, bool _flush);
bool send(client_t _client, const byte_t *_data, uint32_t _size,
- instance_t _instance, bool _flush, bool _reliable);
+ instance_t _instance, bool _flush, bool _reliable, bool _is_valid_crc = true);
bool send_to(const std::shared_ptr<endpoint_definition> &_target,
std::shared_ptr<message> _message, bool _flush);
bool send_to(const std::shared_ptr<endpoint_definition> &_target,
- const byte_t *_data, uint32_t _size, bool _flush);
+ const byte_t *_data, uint32_t _size,
+ instance_t _instance, bool _flush);
bool send_to(const std::shared_ptr<endpoint_definition> &_target,
const byte_t *_data, uint32_t _size, uint16_t _sd_port);
@@ -156,7 +158,7 @@ public:
const boost::asio::ip::address &_remote_address,
std::uint16_t _remote_port);
void on_message(service_t _service, instance_t _instance,
- const byte_t *_data, length_t _size, bool _reliable);
+ const byte_t *_data, length_t _size, bool _reliable, bool _is_valid_crc = true);
void on_notification(client_t _client, service_t _service,
instance_t _instance, const byte_t *_data, length_t _size,
bool _notify_one);
@@ -181,8 +183,6 @@ public:
bool _has_reliable, bool _has_unreliable);
std::chrono::milliseconds update_routing_info(std::chrono::milliseconds _elapsed);
- void on_reboot(const boost::asio::ip::address &_address);
-
void on_subscribe(service_t _service, instance_t _instance,
eventgroup_t _eventgroup,
std::shared_ptr<endpoint_definition> _subscriber,
@@ -214,9 +214,9 @@ public:
private:
bool deliver_message(const byte_t *_data, length_t _length,
- instance_t _instance, bool _reliable);
+ instance_t _instance, bool _reliable, bool _is_valid_crc = true);
bool deliver_notification(service_t _service, instance_t _instance,
- const byte_t *_data, length_t _length, bool _reliable);
+ const byte_t *_data, length_t _length, bool _reliable, bool _is_valid_crc = true);
instance_t find_instance(service_t _service, endpoint *_endpoint);
@@ -321,8 +321,10 @@ private:
void requested_service_remove(client_t _client, service_t _service,
instance_t _instance);
- void call_sd_reliable_endpoint_connected(service_t _service, instance_t _instance,
- std::shared_ptr<endpoint> _endpoint);
+ void call_sd_reliable_endpoint_connected(const boost::system::error_code& _error,
+ service_t _service, instance_t _instance,
+ std::shared_ptr<endpoint> _endpoint,
+ std::shared_ptr<boost::asio::steady_timer> _timer);
bool create_placeholder_event_and_subscribe(service_t _service,
instance_t _instance,
@@ -330,6 +332,14 @@ private:
event_t _event,
client_t _client);
+ void handle_subscription_state(client_t _client, service_t _service, instance_t _instance,
+ eventgroup_t _eventgroup, event_t _event);
+
+ client_t is_specific_endpoint_client(client_t _client, service_t _service, instance_t _instance);
+ std::unordered_set<client_t> get_specific_endpoint_clients(service_t _service, instance_t _instance);
+
+ bool remote_service_offered_via_tcp_and_udp(service_t _service, instance_t _instance) const;
+
std::shared_ptr<routing_manager_stub> stub_;
std::shared_ptr<sd::service_discovery> discovery_;
@@ -401,6 +411,10 @@ private:
std::mutex pending_subscription_mutex_;
+ std::mutex remote_subscription_state_mutex_;
+ std::map<std::tuple<service_t, instance_t, eventgroup_t, client_t>,
+ subscription_state_e> remote_subscription_state_;
+
std::map<e2exf::data_identifier, std::shared_ptr<e2e::profile::profile_interface::protector>> custom_protectors;
std::map<e2exf::data_identifier, std::shared_ptr<e2e::profile::profile_interface::checker>> custom_checkers;
};
diff --git a/implementation/routing/include/routing_manager_proxy.hpp b/implementation/routing/include/routing_manager_proxy.hpp
index 0bc25f7..6d92c39 100644
--- a/implementation/routing/include/routing_manager_proxy.hpp
+++ b/implementation/routing/include/routing_manager_proxy.hpp
@@ -59,13 +59,13 @@ public:
eventgroup_t _eventgroup, event_t _event);
bool send(client_t _client, const byte_t *_data, uint32_t _size,
- instance_t _instance, bool _flush = true, bool _reliable = false);
+ instance_t _instance, bool _flush = true, bool _reliable = false, bool _is_valid_crc= true);
bool send_to(const std::shared_ptr<endpoint_definition> &_target,
std::shared_ptr<message> _message, bool _flush);
bool send_to(const std::shared_ptr<endpoint_definition> &_target,
- const byte_t *_data, uint32_t _size, bool _flush);
+ const byte_t *_data, uint32_t _size, instance_t _instance, bool _flush);
void register_event(client_t _client, service_t _service,
instance_t _instance, event_t _event,
@@ -130,10 +130,10 @@ private:
event_t _event) const;
void on_subscribe_nack(client_t _client, service_t _service,
- instance_t _instance, eventgroup_t _eventgroup);
+ instance_t _instance, eventgroup_t _eventgroup, event_t _event);
void on_subscribe_ack(client_t _client, service_t _service,
- instance_t _instance, eventgroup_t _eventgroup);
+ instance_t _instance, eventgroup_t _eventgroup, event_t _event);
void cache_event_payload(const std::shared_ptr<message> &_message);
@@ -144,8 +144,8 @@ private:
void init_receiver();
- void notify_remote_initally(service_t _service, instance_t _instance,
- eventgroup_t _eventgroup);
+ void notify_remote_initially(service_t _service, instance_t _instance,
+ eventgroup_t _eventgroup, const std::set<event_t> &_events_to_exclude);
uint32_t get_remote_subscriber_count(service_t _service, instance_t _instance,
eventgroup_t _eventgroup, bool _increment);
@@ -209,8 +209,8 @@ private:
};
std::set<event_data_t> pending_event_registrations_;
- std::map<client_t, std::set<subscription_data_t>> pending_ingoing_subscripitons_;
- std::mutex pending_ingoing_subscripitons_mutex_;
+ std::map<client_t, std::set<subscription_data_t>> pending_incoming_subscripitons_;
+ std::mutex incoming_subscripitons_mutex_;
std::mutex deserialize_mutex_;
diff --git a/implementation/routing/include/routing_manager_stub.hpp b/implementation/routing/include/routing_manager_stub.hpp
index 13911dc..385c9cf 100644
--- a/implementation/routing/include/routing_manager_stub.hpp
+++ b/implementation/routing/include/routing_manager_stub.hpp
@@ -100,8 +100,6 @@ private:
void on_register_application(client_t _client);
void on_deregister_application(client_t _client);
- void broadcast_routing_stop();
-
void inform_requesters(client_t _hoster, service_t _service,
instance_t _instance, major_version_t _major,
minor_version_t _minor, routing_info_entry_e _entry,
diff --git a/implementation/routing/include/routing_manager_stub_host.hpp b/implementation/routing/include/routing_manager_stub_host.hpp
index 344d594..ec60c37 100644
--- a/implementation/routing/include/routing_manager_stub_host.hpp
+++ b/implementation/routing/include/routing_manager_stub_host.hpp
@@ -53,7 +53,7 @@ public:
instance_t _instance, eventgroup_t _eventgroup, event_t _event) = 0;
virtual void on_message(service_t _service, instance_t _instance,
- const byte_t *_data, length_t _size, bool _reliable) = 0;
+ const byte_t *_data, length_t _size, bool _reliable, bool _is_valid_crc = true) = 0;
virtual void on_notification(client_t _client,
service_t _service, instance_t _instance,
diff --git a/implementation/routing/src/event.cpp b/implementation/routing/src/event.cpp
index df39b1c..5dd6309 100644
--- a/implementation/routing/src/event.cpp
+++ b/implementation/routing/src/event.cpp
@@ -441,4 +441,14 @@ std::set<client_t> event::get_subscribers(eventgroup_t _eventgroup) {
return its_subscribers;
}
+bool event::is_subscribed(client_t _client) {
+ std::lock_guard<std::mutex> its_lock(eventgroups_mutex_);
+ for (const auto &egp : eventgroups_) {
+ if (egp.second.find(_client) != egp.second.end()) {
+ return true;
+ }
+ }
+ return false;
+}
+
} // namespace vsomeip
diff --git a/implementation/routing/src/eventgroupinfo.cpp b/implementation/routing/src/eventgroupinfo.cpp
index 0a32861..2f02a5c 100644
--- a/implementation/routing/src/eventgroupinfo.cpp
+++ b/implementation/routing/src/eventgroupinfo.cpp
@@ -189,4 +189,8 @@ void eventgroupinfo::set_threshold(uint8_t _threshold) {
threshold_ = _threshold;
}
+std::unique_lock<std::mutex> eventgroupinfo::get_subscription_lock() {
+ return std::unique_lock<std::mutex>(subscription_mutex_);
+}
+
} // namespace vsomeip
diff --git a/implementation/routing/src/routing_manager_base.cpp b/implementation/routing/src/routing_manager_base.cpp
index 04e4adb..19d1b86 100644
--- a/implementation/routing/src/routing_manager_base.cpp
+++ b/implementation/routing/src/routing_manager_base.cpp
@@ -71,6 +71,19 @@ bool routing_manager_base::offer_service(client_t _client, service_t _service,
its_info = create_service_info(_service, _instance, _major, _minor,
DEFAULT_TTL, true);
}
+ {
+ std::lock_guard<std::mutex> its_lock(events_mutex_);
+ // Set major version for all registered events of this service and instance
+ const auto found_service = events_.find(_service);
+ if (found_service != events_.end()) {
+ const auto found_instance = found_service->second.find(_instance);
+ if (found_instance != found_service->second.end()) {
+ for (const auto &j : found_instance->second) {
+ j.second->set_version(_major);
+ }
+ }
+ }
+ }
return true;
}
@@ -315,10 +328,12 @@ void routing_manager_base::subscribe(client_t _client, service_t _service,
(void) _major;
(void) _subscription_type;
-
- bool inserted = insert_subscription(_service, _instance, _eventgroup, _event, _client);
+ std::set<event_t> its_already_subscribed_events;
+ bool inserted = insert_subscription(_service, _instance, _eventgroup,
+ _event, _client, &its_already_subscribed_events);
if (inserted) {
- notify_one_current_value(_client, _service, _instance, _eventgroup, _event);
+ notify_one_current_value(_client, _service, _instance, _eventgroup,
+ _event, its_already_subscribed_events);
}
}
@@ -468,11 +483,10 @@ void routing_manager_base::unset_all_eventpayloads(service_t _service,
}
}
-void routing_manager_base::notify_one_current_value(client_t _client,
- service_t _service,
- instance_t _instance,
- eventgroup_t _eventgroup,
- event_t _event) {
+void routing_manager_base::notify_one_current_value(
+ client_t _client, service_t _service, instance_t _instance,
+ eventgroup_t _eventgroup, event_t _event,
+ const std::set<event_t> &_events_to_exclude) {
if (_event != ANY_EVENT) {
std::shared_ptr<event> its_event = find_event(_service, _instance, _event);
if (its_event && its_event->is_field())
@@ -482,8 +496,11 @@ void routing_manager_base::notify_one_current_value(client_t _client,
if (its_eventgroup) {
std::set<std::shared_ptr<event> > its_events = its_eventgroup->get_events();
for (auto e : its_events) {
- if (e->is_field())
+ if (e->is_field()
+ && _events_to_exclude.find(e->get_event())
+ == _events_to_exclude.end()) {
e->notify_one(_client, true); // TODO: use _flush to send all events together!
+ }
}
}
}
@@ -603,7 +620,7 @@ client_t routing_manager_base::find_local_client(service_t _service, instance_t
std::shared_ptr<endpoint> routing_manager_base::create_local_unlocked(client_t _client) {
std::stringstream its_path;
- its_path << VSOMEIP_BASE_PATH << std::hex << _client;
+ its_path << utility::get_base_path(configuration_) << std::hex << _client;
#ifdef _WIN32
boost::asio::ip::address address = boost::asio::ip::address::from_string("127.0.0.1");
@@ -795,7 +812,7 @@ void routing_manager_base::remove_eventgroup_info(service_t _service,
bool routing_manager_base::send_local_notification(client_t _client,
const byte_t *_data, uint32_t _size, instance_t _instance,
- bool _flush, bool _reliable) {
+ bool _flush, bool _reliable, bool _is_valid_crc) {
#ifdef USE_DLT
bool has_local(false);
#endif
@@ -822,7 +839,7 @@ bool routing_manager_base::send_local_notification(client_t _client,
std::shared_ptr<endpoint> its_local_target = find_local(its_client);
if (its_local_target) {
send_local(its_local_target, _client, _data, _size,
- _instance, _flush, _reliable, VSOMEIP_SEND);
+ _instance, _flush, _reliable, VSOMEIP_SEND, _is_valid_crc);
}
}
}
@@ -833,7 +850,7 @@ bool routing_manager_base::send_local_notification(client_t _client,
= uint16_t(_size > USHRT_MAX ? USHRT_MAX : _size);
tc::trace_header its_header;
- if (its_header.prepare(nullptr, true))
+ if (its_header.prepare(nullptr, true, _instance))
tc_->trace(its_header.data_, VSOMEIP_TRACE_HEADER_SIZE,
_data, its_data_size);
}
@@ -844,9 +861,9 @@ bool routing_manager_base::send_local_notification(client_t _client,
bool routing_manager_base::send_local(
std::shared_ptr<endpoint>& _target, client_t _client,
const byte_t *_data, uint32_t _size, instance_t _instance,
- bool _flush, bool _reliable, uint8_t _command) const {
+ bool _flush, bool _reliable, uint8_t _command, bool _is_valid_crc) const {
std::size_t its_complete_size = _size + sizeof(instance_t)
- + sizeof(bool) + sizeof(bool);
+ + sizeof(bool) + sizeof(bool) + sizeof(bool);
client_t sender = get_client();
if (_command == VSOMEIP_NOTIFY_ONE) {
its_complete_size +=sizeof(client_t);
@@ -866,10 +883,12 @@ bool routing_manager_base::send_local(
+ sizeof(instance_t)], &_flush, sizeof(bool));
std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + _size
+ sizeof(instance_t) + sizeof(bool)], &_reliable, sizeof(bool));
+ std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + _size
+ + sizeof(instance_t) + sizeof(bool) + sizeof(bool)], &_is_valid_crc, sizeof(bool));
if (_command == VSOMEIP_NOTIFY_ONE) {
// Add target client
std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + _size
- + sizeof(instance_t) + sizeof(bool) + sizeof(bool)], &_client, sizeof(client_t));
+ + sizeof(instance_t) + sizeof(bool) + sizeof(bool) + sizeof(bool)], &_client, sizeof(client_t));
}
return _target->send(&its_command[0], uint32_t(its_command.size()));
@@ -877,7 +896,7 @@ bool routing_manager_base::send_local(
bool routing_manager_base::insert_subscription(
service_t _service, instance_t _instance, eventgroup_t _eventgroup,
- event_t _event, client_t _client) {
+ event_t _event, client_t _client, std::set<event_t> *_already_subscribed_events) {
bool is_inserted(false);
if (_event != ANY_EVENT) { // subscribe to specific event
std::shared_ptr<event> its_event = find_event(_service, _instance, _event);
@@ -905,7 +924,13 @@ bool routing_manager_base::insert_subscription(
if (!its_events.size()) {
create_place_holder = true;
} else {
- for (auto e : its_events) {
+ for (const auto &e : its_events) {
+ if (e->is_subscribed(_client)) {
+ // client is already subscribed to event from eventgroup
+ // this can happen if events are members of multiple
+ // eventgroups
+ _already_subscribed_events->insert(e->get_event());
+ }
is_inserted = e->add_subscriber(_eventgroup, _client) || is_inserted;
}
}
diff --git a/implementation/routing/src/routing_manager_impl.cpp b/implementation/routing/src/routing_manager_impl.cpp
index 96e3b08..343741f 100644
--- a/implementation/routing/src/routing_manager_impl.cpp
+++ b/implementation/routing/src/routing_manager_impl.cpp
@@ -13,6 +13,8 @@
#include <systemd/sd-daemon.h>
#endif
+#include <boost/asio/steady_timer.hpp>
+
#include <vsomeip/constants.hpp>
#include <vsomeip/message.hpp>
#include <vsomeip/payload.hpp>
@@ -42,6 +44,7 @@
#include "../../service_discovery/include/service_discovery_impl.hpp"
#include "../../utility/include/byteorder.hpp"
#include "../../utility/include/utility.hpp"
+#include "../../plugin/include/plugin_manager.hpp"
#include "../../e2e_protection/include/buffer/buffer.hpp"
#include "../../e2e_protection/include/e2exf/config.hpp"
@@ -89,14 +92,11 @@ void routing_manager_impl::init() {
if (configuration_->is_sd_enabled()) {
VSOMEIP_INFO<< "Service Discovery enabled. Trying to load module.";
- std::shared_ptr<sd::runtime> *its_runtime =
- static_cast<std::shared_ptr<sd::runtime> *>(utility::load_library(
- VSOMEIP_SD_LIBRARY,
- VSOMEIP_SD_RUNTIME_SYMBOL_STRING));
-
- if (its_runtime && (*its_runtime)) {
+ auto its_plugin = plugin_manager::get()->get_plugin(
+ plugin_type_e::SD_RUNTIME_PLUGIN);
+ if (its_plugin) {
VSOMEIP_INFO << "Service Discovery module loaded.";
- discovery_ = (*its_runtime)->create_service_discovery(this);
+ discovery_ = std::dynamic_pointer_cast<sd::runtime>(its_plugin)->create_service_discovery(this);
discovery_->init();
}
}
@@ -109,7 +109,7 @@ void routing_manager_impl::init() {
if(its_cfg->profile == "CRC8") {
e2exf::data_identifier its_data_identifier = {its_cfg->service_id, its_cfg->event_id};
e2e::profile::profile01::Config its_profile_config = e2e::profile::profile01::Config(its_cfg->crc_offset, its_cfg->data_id,
- (e2e::profile::profile01::p01_data_id_mode) its_cfg->data_id_mode, its_cfg->data_length);
+ (e2e::profile::profile01::p01_data_id_mode) its_cfg->data_id_mode, its_cfg->data_length, its_cfg->counter_offset, its_cfg->data_id_nibble_offset);
if ((its_cfg->variant == "protector") || (its_cfg->variant == "both")) {
custom_protectors[its_data_identifier] = std::make_shared<e2e::profile::profile01::protector>(its_profile_config);
}
@@ -218,20 +218,6 @@ bool routing_manager_impl::offer_service(client_t _client, service_t _service,
}
}
- {
- std::lock_guard<std::mutex> its_lock(events_mutex_);
- // Set major version for all registered events of this service and instance
- auto find_service = events_.find(_service);
- if (find_service != events_.end()) {
- auto find_instance = find_service->second.find(_instance);
- if (find_instance != find_service->second.end()) {
- for (auto j : find_instance->second) {
- j.second->set_version(_major);
- }
- }
- }
- }
-
if (discovery_) {
std::shared_ptr<serviceinfo> its_info = find_service(_service, _instance);
if (its_info) {
@@ -241,11 +227,12 @@ bool routing_manager_impl::offer_service(client_t _client, service_t _service,
{
std::lock_guard<std::mutex> ist_lock(pending_subscription_mutex_);
+ std::set<event_t> its_already_subscribed_events;
for (auto &ps : pending_subscriptions_) {
if (ps.service_ == _service &&
ps.instance_ == _instance && ps.major_ == _major) {
insert_subscription(ps.service_, ps.instance_,
- ps.eventgroup_, ps.event_, client_);
+ ps.eventgroup_, ps.event_, client_, &its_already_subscribed_events);
}
}
send_pending_subscriptions(_service, _instance, _major);
@@ -402,8 +389,8 @@ void routing_manager_impl::subscribe(client_t _client, service_t _service,
<< std::hex << std::setw(4) << std::setfill('0') << _eventgroup << ":"
<< std::hex << std::setw(4) << std::setfill('0') << _event << ":"
<< std::dec << (uint16_t)_major << "]";
-
- if (get_client() == find_local_client(_service, _instance)) {
+ const client_t its_local_client = find_local_client(_service, _instance);
+ if (get_client() == its_local_client) {
bool subscription_accepted = host_->on_subscription(_service, _instance, _eventgroup, _client, true);
(void) find_or_create_local(_client);
if (!subscription_accepted) {
@@ -420,37 +407,46 @@ void routing_manager_impl::subscribe(client_t _client, service_t _service,
} else {
if (discovery_) {
client_t subscriber = VSOMEIP_ROUTING_CLIENT;
- if (0 == find_local_client(_service, _instance)) {
- // subscriber != VSOMEIP_ROUTING_CLIENT implies to use its own endpoint
- bool identify(false);
- {
- std::lock_guard<std::mutex> its_lock(specific_endpoint_clients_mutex_);
- auto found_service = specific_endpoint_clients_.find(_service);
- if (found_service != specific_endpoint_clients_.end()) {
- auto found_instance = found_service->second.find(_instance);
- if (found_instance != found_service->second.end()) {
- auto found_client = found_instance->second.find(_client);
- if(found_client != found_instance->second.end()) {
- subscriber = _client;
- if (supports_selective(_service, _instance)) {
- identify = true;
- } else {
- VSOMEIP_INFO << "Subcribe to legacy selective service: " << std::hex
- << _service << ":" << _instance << ".";
- }
- }
- }
+ if (0 == its_local_client) {
+ subscriber = is_specific_endpoint_client(_client, _service, _instance);
+ if (subscriber != VSOMEIP_ROUTING_CLIENT) {
+ if (supports_selective(_service, _instance)) {
+ identify_for_subscribe(_client, _service, _instance,
+ _major, _subscription_type);
+ } else {
+ VSOMEIP_INFO << "Subcribe to legacy selective service: " << std::hex
+ << _service << ":" << _instance << ".";
}
}
- if(identify) {
- identify_for_subscribe(_client, _service, _instance, _major, _subscription_type);
- }
}
- bool inserted = insert_subscription(_service, _instance, _eventgroup, _event, _client);
+ std::unique_lock<std::mutex> eventgroup_lock;
+ auto its_eventgroup = find_eventgroup(_service, _instance, _eventgroup);
+ if (its_eventgroup) {
+ eventgroup_lock = its_eventgroup->get_subscription_lock();
+ }
+ std::set<event_t> its_already_subscribed_events;
+ bool inserted = insert_subscription(_service, _instance, _eventgroup,
+ _event, _client, &its_already_subscribed_events);
if (inserted) {
- if (0 == find_local_client(_service, _instance)) {
+ if (0 == its_local_client) {
+ handle_subscription_state(_client, _service, _instance, _eventgroup, _event);
+ if (its_eventgroup) {
+ eventgroup_lock.unlock();
+ }
static const ttl_t configured_ttl(configuration_->get_sd_ttl());
- notify_one_current_value(_client, _service, _instance, _eventgroup, _event);
+ std::uint8_t number_notify_initially(1);
+ if (_subscription_type == subscription_type_e::SU_RELIABLE_AND_UNRELIABLE &&
+ remote_service_offered_via_tcp_and_udp(_service, _instance)) {
+ // to be consistent with remote initial events clients
+ // which want to subscribe via TCP and UDP need to get
+ // two initial events if the service is offered via TCP
+ // and UDP
+ number_notify_initially = 2;
+ }
+ for (std::uint8_t i = 0; i < number_notify_initially; i++) {
+ notify_one_current_value(_client, _service, _instance,
+ _eventgroup, _event, its_already_subscribed_events);
+ }
discovery_->subscribe(_service, _instance, _eventgroup,
_major, configured_ttl, subscriber, _subscription_type);
} else {
@@ -459,6 +455,8 @@ void routing_manager_impl::subscribe(client_t _client, service_t _service,
_client, _service, _instance, _eventgroup, _major, _event, false);
}
}
+ } else if (its_eventgroup) {
+ eventgroup_lock.unlock();
}
if (get_client() == _client) {
std::lock_guard<std::mutex> ist_lock(pending_subscription_mutex_);
@@ -501,29 +499,25 @@ void routing_manager_impl::unsubscribe(client_t _client, service_t _service,
if (discovery_) {
host_->on_subscription(_service, _instance, _eventgroup, _client, false);
if (0 == find_local_client(_service, _instance)) {
- client_t subscriber = VSOMEIP_ROUTING_CLIENT;
- // subscriber != VSOMEIP_ROUTING_CLIENT implies to use its own endpoint
- {
- std::lock_guard<std::mutex> its_lock(specific_endpoint_clients_mutex_);
- auto found_service = specific_endpoint_clients_.find(_service);
- if (found_service != specific_endpoint_clients_.end()) {
- auto found_instance = found_service->second.find(_instance);
- if (found_instance != found_service->second.end()) {
- auto found_client = found_instance->second.find(_client);
- if(found_client != found_instance->second.end()) {
- subscriber = _client;
- }
- }
- }
- }
+ client_t subscriber = is_specific_endpoint_client(_client, _service, _instance);
if (last_subscriber_removed) {
unset_all_eventpayloads(_service, _instance, _eventgroup);
}
if (subscriber == VSOMEIP_ROUTING_CLIENT && last_subscriber_removed) {
+ {
+ auto tuple = std::make_tuple(_service, _instance, _eventgroup, subscriber);
+ std::lock_guard<std::mutex> its_lock(remote_subscription_state_mutex_);
+ remote_subscription_state_.erase(tuple);
+ }
// for normal subscribers only unsubscribe via SD if last
// subscriber was removed
discovery_->unsubscribe(_service, _instance, _eventgroup, subscriber);
} else if (subscriber != VSOMEIP_ROUTING_CLIENT) {
+ {
+ auto tuple = std::make_tuple(_service, _instance, _eventgroup, subscriber);
+ std::lock_guard<std::mutex> its_lock(remote_subscription_state_mutex_);
+ remote_subscription_state_.erase(tuple);
+ }
// for selective subscribers always unsubscribe at the SD
discovery_->unsubscribe(_service, _instance, _eventgroup, subscriber);
}
@@ -549,7 +543,7 @@ bool routing_manager_impl::send(client_t _client,
bool routing_manager_impl::send(client_t _client, const byte_t *_data,
length_t _size, instance_t _instance,
- bool _flush, bool _reliable) {
+ bool _flush, bool _reliable, bool _is_valid_crc) {
bool is_sent(false);
if (_size > VSOMEIP_MESSAGE_TYPE_POS) {
std::shared_ptr<endpoint> its_target;
@@ -577,11 +571,11 @@ bool routing_manager_impl::send(client_t _client, const byte_t *_data,
= uint16_t(_size > USHRT_MAX ? USHRT_MAX : _size);
tc::trace_header its_header;
- if (its_header.prepare(its_target, true))
+ if (its_header.prepare(its_target, true, _instance))
tc_->trace(its_header.data_, VSOMEIP_TRACE_HEADER_SIZE,
_data, its_data_size);
#endif
- deliver_message(_data, _size, _instance, _reliable);
+ deliver_message(_data, _size, _instance, _reliable, _is_valid_crc);
return true;
}
its_target = find_local(_client);
@@ -593,11 +587,11 @@ bool routing_manager_impl::send(client_t _client, const byte_t *_data,
= uint16_t(_size > USHRT_MAX ? USHRT_MAX : _size);
tc::trace_header its_header;
- if (its_header.prepare(its_target, true))
+ if (its_header.prepare(its_target, true, _instance))
tc_->trace(its_header.data_, VSOMEIP_TRACE_HEADER_SIZE,
_data, its_data_size);
#endif
- is_sent = send_local(its_target, get_client(), _data, _size, _instance, _flush, _reliable, VSOMEIP_SEND);
+ is_sent = send_local(its_target, get_client(), _data, _size, _instance, _flush, _reliable, VSOMEIP_SEND, _is_valid_crc);
} else {
// Check whether hosting application should get the message
// If not, check routes to external
@@ -605,7 +599,7 @@ bool routing_manager_impl::send(client_t _client, const byte_t *_data,
|| (find_local_client(its_service, _instance)
== host_->get_client() && is_request)) {
// TODO: find out how to handle session id here
- is_sent = deliver_message(_data, _size, _instance, _reliable);
+ is_sent = deliver_message(_data, _size, _instance, _reliable, _is_valid_crc);
} else {
buffer::e2e_buffer outputBuffer;
if( configuration_->is_e2e_enabled()) {
@@ -625,20 +619,7 @@ bool routing_manager_impl::send(client_t _client, const byte_t *_data,
}
}
if (is_request) {
- client_t client = VSOMEIP_ROUTING_CLIENT;
- {
- std::lock_guard<std::mutex> its_lock(specific_endpoint_clients_mutex_);
- auto found_service = specific_endpoint_clients_.find(its_service);
- if (found_service != specific_endpoint_clients_.end()) {
- auto found_instance = found_service->second.find(_instance);
- if (found_instance != found_service->second.end()) {
- auto found_client = found_instance->second.find(its_client);
- if (found_client != found_instance->second.end()) {
- client = its_client;
- }
- }
- }
- }
+ client_t client = is_specific_endpoint_client(its_client, its_service, _instance);
its_target = find_or_create_remote_client(its_service, _instance, _reliable, client);
if (its_target) {
#ifdef USE_DLT
@@ -646,7 +627,7 @@ bool routing_manager_impl::send(client_t _client, const byte_t *_data,
= uint16_t(_size > USHRT_MAX ? USHRT_MAX : _size);
tc::trace_header its_header;
- if (its_header.prepare(its_target, true))
+ if (its_header.prepare(its_target, true, _instance))
tc_->trace(its_header.data_, VSOMEIP_TRACE_HEADER_SIZE,
_data, its_data_size);
#endif
@@ -658,7 +639,7 @@ bool routing_manager_impl::send(client_t _client, const byte_t *_data,
std::shared_ptr<serviceinfo> its_info(find_service(its_service, _instance));
if (its_info || is_service_discovery) {
if (is_notification && !is_service_discovery) {
- send_local_notification(get_client(), _data, _size, _instance, _flush, _reliable);
+ send_local_notification(get_client(), _data, _size, _instance, _flush, _reliable, _is_valid_crc);
method_t its_method = VSOMEIP_BYTES_TO_WORD(_data[VSOMEIP_METHOD_POS_MIN],
_data[VSOMEIP_METHOD_POS_MAX]);
std::shared_ptr<event> its_event = find_event(its_service, _instance, its_method);
@@ -666,49 +647,52 @@ bool routing_manager_impl::send(client_t _client, const byte_t *_data,
#ifdef USE_DLT
bool has_sent(false);
#endif
- std::vector< byte_t > its_data;
- for (auto its_group : its_event->get_eventgroups()) {
- // we need both endpoints as clients can subscribe to events via TCP and UDP
- std::shared_ptr<endpoint> its_unreliable_target = its_info->get_endpoint(false);
- std::shared_ptr<endpoint> its_reliable_target = its_info->get_endpoint(true);
- if (its_unreliable_target || its_reliable_target) {
- // remote
+ std::set<std::shared_ptr<endpoint_definition>> its_targets;
+ // we need both endpoints as clients can subscribe to events via TCP and UDP
+ std::shared_ptr<endpoint> its_udp_server_endpoint = its_info->get_endpoint(false);
+ std::shared_ptr<endpoint> its_tcp_server_endpoint = its_info->get_endpoint(true);
+ if (its_udp_server_endpoint || its_tcp_server_endpoint) {
+ for (auto its_group : its_event->get_eventgroups()) {
auto its_eventgroup = find_eventgroup(its_service, _instance, its_group);
if (its_eventgroup) {
// Unicast targets
- for (auto its_remote : its_eventgroup->get_targets()) {
- if(its_remote.endpoint_->is_reliable() && its_reliable_target) {
- its_reliable_target->send_to(its_remote.endpoint_, _data, _size, _flush);
- } else if (its_unreliable_target && !its_eventgroup->is_sending_multicast()) {
- its_unreliable_target->send_to(its_remote.endpoint_, _data, _size, _flush);
+ for (const auto &its_remote : its_eventgroup->get_targets()) {
+ if(its_remote.endpoint_->is_reliable() && its_tcp_server_endpoint) {
+ its_targets.insert(its_remote.endpoint_);
+ } else if (its_udp_server_endpoint && !its_eventgroup->is_sending_multicast()) {
+ its_targets.insert(its_remote.endpoint_);
}
-#ifdef USE_DLT
- has_sent = true;
-#endif
}
// Send to multicast targets if subscribers are still interested
if (its_eventgroup->is_sending_multicast()) {
for (auto its_multicast_target : its_eventgroup->get_multicast_targets()) {
- its_unreliable_target->send_to(its_multicast_target.endpoint_, _data, _size, _flush);
-#ifdef USE_DLT
- has_sent = true;
-#endif
+ its_targets.insert(its_multicast_target.endpoint_);
}
}
-#ifdef USE_DLT
- if (has_sent) {
- const uint16_t its_data_size
- = uint16_t(_size > USHRT_MAX ? USHRT_MAX : _size);
-
- tc::trace_header its_header;
- if (its_header.prepare(nullptr, true))
- tc_->trace(its_header.data_, VSOMEIP_TRACE_HEADER_SIZE,
- _data, its_data_size);
- }
-#endif
}
}
}
+ for (auto const &target : its_targets) {
+ if (target->is_reliable()) {
+ its_tcp_server_endpoint->send_to(target, _data, _size, _flush);
+ } else {
+ its_udp_server_endpoint->send_to(target, _data, _size, _flush);
+ }
+#ifdef USE_DLT
+ has_sent = true;
+#endif
+ }
+#ifdef USE_DLT
+ if (has_sent) {
+ const uint16_t its_data_size
+ = uint16_t(_size > USHRT_MAX ? USHRT_MAX : _size);
+
+ tc::trace_header its_header;
+ if (its_header.prepare(nullptr, true, _instance))
+ tc_->trace(its_header.data_, VSOMEIP_TRACE_HEADER_SIZE,
+ _data, its_data_size);
+ }
+#endif
}
} else {
its_target = is_service_discovery ?
@@ -719,7 +703,7 @@ bool routing_manager_impl::send(client_t _client, const byte_t *_data,
= uint16_t(_size > USHRT_MAX ? USHRT_MAX : _size);
tc::trace_header its_header;
- if (its_header.prepare(its_target, true))
+ if (its_header.prepare(its_target, true, _instance))
tc_->trace(its_header.data_, VSOMEIP_TRACE_HEADER_SIZE,
_data, its_data_size);
#endif
@@ -768,7 +752,7 @@ bool routing_manager_impl::send_to(
_data = outputBuffer.data();
}
}
- is_sent = send_to(_target, _data, _size, _flush);
+ is_sent = send_to(_target, _data, _size, _message->get_instance(), _flush);
serializer_->reset();
} else {
VSOMEIP_ERROR<< "routing_manager_impl::send_to: serialization failed.";
@@ -778,7 +762,8 @@ bool routing_manager_impl::send_to(
bool routing_manager_impl::send_to(
const std::shared_ptr<endpoint_definition> &_target,
- const byte_t *_data, uint32_t _size, bool _flush) {
+ const byte_t *_data, uint32_t _size, instance_t _instance,
+ bool _flush) {
std::shared_ptr<endpoint> its_endpoint = find_server_endpoint(
_target->get_remote_port(), _target->is_reliable());
@@ -788,16 +773,19 @@ bool routing_manager_impl::send_to(
= uint16_t(_size > USHRT_MAX ? USHRT_MAX : _size);
tc::trace_header its_header;
- if (its_header.prepare(its_endpoint, true))
+ if (its_header.prepare(its_endpoint, true, _instance))
tc_->trace(its_header.data_, VSOMEIP_TRACE_HEADER_SIZE,
_data, its_data_size);
+#else
+ (void) _instance;
#endif
return its_endpoint->send_to(_target, _data, _size, _flush);
}
return false;
}
-bool routing_manager_impl::send_to(const std::shared_ptr<endpoint_definition> &_target,
+bool routing_manager_impl::send_to(
+ const std::shared_ptr<endpoint_definition> &_target,
const byte_t *_data, uint32_t _size, uint16_t _sd_port) {
std::shared_ptr<endpoint> its_endpoint = find_server_endpoint(
_sd_port, _target->is_reliable());
@@ -808,7 +796,7 @@ bool routing_manager_impl::send_to(const std::shared_ptr<endpoint_definition> &_
= uint16_t(_size > USHRT_MAX ? USHRT_MAX : _size);
tc::trace_header its_header;
- if (its_header.prepare(its_endpoint, true))
+ if (its_header.prepare(its_endpoint, true, 0x0))
tc_->trace(its_header.data_, VSOMEIP_TRACE_HEADER_SIZE,
_data, its_data_size);
#endif
@@ -948,9 +936,13 @@ void routing_manager_impl::on_message(const byte_t *_data, length_t _size,
(void)_bound_client;
service_t its_service;
method_t its_method;
+ bool its_is_crc_valid(true);
+ instance_t its_instance(0x0);
+
if (_size >= VSOMEIP_SOMEIP_HEADER_SIZE) {
its_service = VSOMEIP_BYTES_TO_WORD(_data[VSOMEIP_SERVICE_POS_MIN],
_data[VSOMEIP_SERVICE_POS_MAX]);
+ its_instance = find_instance(its_service, _receiver);
if (its_service == VSOMEIP_SD_SERVICE) {
its_method = VSOMEIP_BYTES_TO_WORD(_data[VSOMEIP_METHOD_POS_MIN],
_data[VSOMEIP_METHOD_POS_MAX]);
@@ -967,7 +959,6 @@ void routing_manager_impl::on_message(const byte_t *_data, length_t _size,
}
}
} else {
- instance_t its_instance = find_instance(its_service, _receiver);
//Ignore messages with invalid message type
if(_size >= VSOMEIP_MESSAGE_TYPE_POS) {
if(!utility::is_valid_message_type(static_cast<message_type_e>(_data[VSOMEIP_MESSAGE_TYPE_POS]))) {
@@ -1026,6 +1017,7 @@ void routing_manager_impl::on_message(const byte_t *_data, length_t _size,
if ( check_status != e2e::profile::profile_interface::generic_check_status::E2E_OK ) {
VSOMEIP_INFO << std::hex << "E2E protection: CRC check failed for service: " << its_service << " method: " << its_method;
+ its_is_crc_valid = false;
}
}
}
@@ -1038,7 +1030,7 @@ void routing_manager_impl::on_message(const byte_t *_data, length_t _size,
its_data[VSOMEIP_CLIENT_POS_MAX] = 0x0;
}
// Common way of message handling
- on_message(its_service, its_instance, _data, _size, _receiver->is_reliable());
+ on_message(its_service, its_instance, _data, _size, _receiver->is_reliable(), its_is_crc_valid);
}
}
}
@@ -1054,7 +1046,8 @@ void routing_manager_impl::on_message(const byte_t *_data, length_t _size,
_receiver->is_local() ? tc::protocol_e::local :
_receiver->is_reliable() ? tc::protocol_e::tcp :
tc::protocol_e::udp;
- its_header.prepare(its_remote_address, _remote_port, its_protocol, false);
+ its_header.prepare(its_remote_address, _remote_port, its_protocol, false,
+ its_instance);
tc_->trace(its_header.data_, VSOMEIP_TRACE_HEADER_SIZE, _data,
its_data_size);
#endif
@@ -1063,7 +1056,7 @@ void routing_manager_impl::on_message(const byte_t *_data, length_t _size,
void routing_manager_impl::on_message(
service_t _service, instance_t _instance,
const byte_t *_data, length_t _size,
- bool _reliable) {
+ bool _reliable, bool _is_valid_crc) {
#if 0
std::stringstream msg;
msg << "rmi::on_message("
@@ -1085,11 +1078,11 @@ void routing_manager_impl::on_message(
if (its_client == VSOMEIP_ROUTING_CLIENT
&& utility::is_notification(_data[VSOMEIP_MESSAGE_TYPE_POS])) {
- deliver_notification(_service, _instance, _data, _size, _reliable);
+ deliver_notification(_service, _instance, _data, _size, _reliable, _is_valid_crc);
} else if (its_client == host_->get_client()) {
- deliver_message(_data, _size, _instance, _reliable);
+ deliver_message(_data, _size, _instance, _reliable, _is_valid_crc);
} else {
- send(its_client, _data, _size, _instance, true, _reliable);
+ send(its_client, _data, _size, _instance, true, _reliable, _is_valid_crc); //send to proxy
}
}
@@ -1115,14 +1108,21 @@ void routing_manager_impl::on_notification(client_t _client,
if (its_event->is_set()) {
its_event->set_payload(its_payload, false, true);
} else {
- // Set payload first time ~> notify all remote subscriber per unicast (inital field)
+ // Set payload first time ~> notify all remote subscriber per unicast (initial field)
+ std::vector<std::unique_lock<std::mutex>> its_locks;
+ std::vector<std::shared_ptr<eventgroupinfo>> its_eventgroupinfos;
for (auto its_group : its_event->get_eventgroups()) {
auto its_eventgroup = find_eventgroup(_service, _instance, its_group);
if (its_eventgroup) {
- //Unicast targets
- for (auto its_remote : its_eventgroup->get_targets()) {
- its_event->set_payload(its_payload, its_remote.endpoint_, true, true);
- }
+ its_locks.push_back(its_eventgroup->get_subscription_lock());
+ its_eventgroupinfos.push_back(its_eventgroup);
+ }
+ }
+
+ for (const auto &its_eventgroup : its_eventgroupinfos) {
+ //Unicast targets
+ for (auto its_remote : its_eventgroup->get_targets()) {
+ its_event->set_payload(its_payload, its_remote.endpoint_, true, true);
}
}
}
@@ -1130,7 +1130,6 @@ void routing_manager_impl::on_notification(client_t _client,
its_event->set_payload(its_payload, false, true);
}
}
-
}
}
@@ -1192,15 +1191,20 @@ void routing_manager_impl::on_connect(std::shared_ptr<endpoint> _endpoint) {
if (s.reliable_) {
stub_->on_offer_service(VSOMEIP_ROUTING_CLIENT, s.service_id_,
s.instance_id_, s.major_, s.minor_);
- try {
- io_.post(
+ std::shared_ptr<boost::asio::steady_timer> its_timer =
+ std::make_shared<boost::asio::steady_timer>(io_);
+ boost::system::error_code ec;
+ its_timer->expires_from_now(std::chrono::milliseconds(3), ec);
+ if (!ec) {
+ its_timer->async_wait(
std::bind(
&routing_manager_impl::call_sd_reliable_endpoint_connected,
- std::dynamic_pointer_cast<routing_manager_impl>(
- shared_from_this()), s.service_id_,
- s.instance_id_, s.endpoint_));
- } catch (const std::exception &e) {
- VSOMEIP_ERROR<< "routing_manager_impl::on_connect: " << e.what();
+ std::static_pointer_cast<routing_manager_impl>(
+ shared_from_this()),
+ std::placeholders::_1, s.service_id_,
+ s.instance_id_, s.endpoint_, its_timer));
+ } else {
+ VSOMEIP_ERROR<< "routing_manager_impl::on_connect: " << ec.message();
}
}
}
@@ -1382,7 +1386,7 @@ void routing_manager_impl::on_stop_offer_service(client_t _client, service_t _se
}
bool routing_manager_impl::deliver_message(const byte_t *_data, length_t _size,
- instance_t _instance, bool _reliable) {
+ instance_t _instance, bool _reliable, bool _is_valid_crc) {
bool is_delivered(false);
auto a_deserializer = get_deserializer();
@@ -1394,6 +1398,7 @@ bool routing_manager_impl::deliver_message(const byte_t *_data, length_t _size,
if (its_message) {
its_message->set_instance(_instance);
its_message->set_reliable(_reliable);
+ its_message->set_is_valid_crc(_is_valid_crc);
host_->on_message(std::move(its_message));
is_delivered = true;
} else {
@@ -1406,7 +1411,7 @@ bool routing_manager_impl::deliver_message(const byte_t *_data, length_t _size,
bool routing_manager_impl::deliver_notification(
service_t _service, instance_t _instance,
const byte_t *_data, length_t _length,
- bool _reliable) {
+ bool _reliable, bool _is_valid_crc) {
bool is_delivered(false);
method_t its_method = VSOMEIP_BYTES_TO_WORD(_data[VSOMEIP_METHOD_POS_MIN],
@@ -1414,8 +1419,6 @@ bool routing_manager_impl::deliver_notification(
std::shared_ptr<event> its_event = find_event(_service, _instance, its_method);
if (its_event) {
- std::vector< byte_t > its_data;
-
if(its_event->is_field() && !its_event->is_provided()) {
// store the current value of the remote field
const uint32_t its_length(utility::get_payload_size(_data, _length));
@@ -1428,12 +1431,12 @@ bool routing_manager_impl::deliver_notification(
for (const auto its_local_client : its_event->get_subscribers()) {
if (its_local_client == host_->get_client()) {
- deliver_message(_data, _length, _instance, _reliable);
+ deliver_message(_data, _length, _instance, _reliable, _is_valid_crc);
} else {
std::shared_ptr<endpoint> its_local_target = find_local(its_local_client);
if (its_local_target) {
send_local(its_local_target, VSOMEIP_ROUTING_CLIENT,
- _data, _length, _instance, true, _reliable, VSOMEIP_SEND);
+ _data, _length, _instance, true, _reliable, VSOMEIP_SEND, _is_valid_crc);
}
}
}
@@ -2003,17 +2006,9 @@ void routing_manager_impl::add_routing_info(
}
}
}
- {
- std::lock_guard<std::mutex> its_lock(specific_endpoint_clients_mutex_);
- auto found_service2 = specific_endpoint_clients_.find(_service);
- if (found_service2 != specific_endpoint_clients_.end()) {
- auto found_instance = found_service2->second.find(_instance);
- if (found_instance != found_service2->second.end()) {
- for (const client_t& c : found_instance->second) {
- find_or_create_remote_client(_service, _instance, true, c);
- }
- }
- }
+ auto specific_endpoint_clients = get_specific_endpoint_clients(_service, _instance);
+ for (const client_t& c : specific_endpoint_clients) {
+ find_or_create_remote_client(_service, _instance, true, c);
}
} else if (_reliable_port != ILLEGAL_PORT && is_reliable_known) {
std::lock_guard<std::mutex> its_lock(requested_services_mutex_);
@@ -2355,6 +2350,7 @@ void routing_manager_impl::on_subscribe(
std::shared_ptr<eventgroupinfo> its_eventgroup
= find_eventgroup(_service, _instance, _eventgroup);
if (its_eventgroup) {
+ std::unique_lock<std::mutex> its_subscriptions_lock(its_eventgroup->get_subscription_lock());
// IP address of target is a multicast address if the event is in a multicast eventgroup
bool target_added(false);
if (its_eventgroup->is_multicast() && !_subscriber->is_reliable()) {
@@ -2491,50 +2487,97 @@ void routing_manager_impl::on_subscribe_ack(service_t _service,
void routing_manager_impl::on_subscribe_ack(client_t _client,
service_t _service, instance_t _instance, eventgroup_t _eventgroup,
event_t _event) {
- {
- std::lock_guard<std::mutex> its_lock(specific_endpoint_clients_mutex_);
- auto found_service = specific_endpoint_clients_.find(_service);
- if(found_service != specific_endpoint_clients_.end()){
- auto found_instance = found_service->second.find(_instance);
- if(found_instance != found_service->second.end()) {
- auto found_client = found_instance->second.find(_client);
- if(found_client == found_instance->second.end()) {
- // Ack is only interesting for proxies using its own endpoint!
+ client_t its_client = is_specific_endpoint_client(_client, _service, _instance);
+ bool specific_endpoint_client = its_client != VSOMEIP_ROUTING_CLIENT;
+ auto its_eventgroup = find_eventgroup(_service, _instance, _eventgroup);
+ if (its_eventgroup) {
+ std::unique_lock<std::mutex> eventgroup_lock(its_eventgroup->get_subscription_lock());
+ {
+ auto its_tuple = std::make_tuple(_service, _instance, _eventgroup, its_client);
+ std::lock_guard<std::mutex> its_lock(remote_subscription_state_mutex_);
+ auto its_state = remote_subscription_state_.find(its_tuple);
+ if (its_state != remote_subscription_state_.end()) {
+ if (its_state->second == subscription_state_e::SUBSCRIPTION_ACKNOWLEDGED) {
+ // Already notified!
return;
}
}
+ remote_subscription_state_[its_tuple] = subscription_state_e::SUBSCRIPTION_ACKNOWLEDGED;
+ }
+
+ if (specific_endpoint_client) {
+ if (_client == get_client()) {
+ host_->on_subscription_error(_service, _instance, _eventgroup, 0x0 /*OK*/);
+ host_->on_subscription_status(_service, _instance, _eventgroup, _event, 0x0 /*OK*/);
+ } else {
+ stub_->send_subscribe_ack(_client, _service, _instance, _eventgroup,
+ _event);
+ }
+ } else {
+ std::set<client_t> subscribed_clients;
+ for (auto its_event : its_eventgroup->get_events()) {
+ for (auto its_client : its_event->get_subscribers()) {
+ subscribed_clients.insert(its_client);
+ }
+ }
+ for (auto its_subscriber : subscribed_clients) {
+ if (its_subscriber == get_client()) {
+ host_->on_subscription_error(_service, _instance, _eventgroup, 0x0 /*OK*/);
+ host_->on_subscription_status(_service, _instance, _eventgroup, _event, 0x0 /*OK*/);
+ } else {
+ stub_->send_subscribe_ack(its_subscriber, _service, _instance,
+ _eventgroup, _event);
+ }
+ }
}
- }
- if (_client == get_client()) {
- host_->on_subscription_error(_service, _instance, _eventgroup, 0x0 /*OK*/);
- } else {
- stub_->send_subscribe_ack(_client, _service, _instance, _eventgroup,
- _event);
}
}
void routing_manager_impl::on_subscribe_nack(client_t _client,
service_t _service, instance_t _instance, eventgroup_t _eventgroup,
event_t _event) {
- {
- std::lock_guard<std::mutex> its_lock(specific_endpoint_clients_mutex_);
- auto found_service = specific_endpoint_clients_.find(_service);
- if(found_service != specific_endpoint_clients_.end()){
- auto found_instance = found_service->second.find(_instance);
- if(found_instance != found_service->second.end()) {
- auto found_client = found_instance->second.find(_client);
- if(found_client == found_instance->second.end()) {
- // Nack is only interesting for proxies using its own endpoint!
+ client_t its_client = is_specific_endpoint_client(_client, _service, _instance);
+ bool specific_endpoint_client = its_client != VSOMEIP_ROUTING_CLIENT;
+ auto its_eventgroup = find_eventgroup(_service, _instance, _eventgroup);
+ if (its_eventgroup) {
+ std::unique_lock<std::mutex> eventgroup_lock(its_eventgroup->get_subscription_lock());
+ {
+ auto its_tuple = std::make_tuple(_service, _instance, _eventgroup, its_client);
+ std::lock_guard<std::mutex> its_lock(remote_subscription_state_mutex_);
+ auto its_state = remote_subscription_state_.find(its_tuple);
+ if (its_state != remote_subscription_state_.end()) {
+ if (its_state->second == subscription_state_e::SUBSCRIPTION_NOT_ACKNOWLEDGED) {
+ // Already notified!
return;
}
}
+ remote_subscription_state_[its_tuple] = subscription_state_e::SUBSCRIPTION_NOT_ACKNOWLEDGED;
+ }
+ if (specific_endpoint_client) {
+ if (_client == get_client()) {
+ host_->on_subscription_error(_service, _instance, _eventgroup, 0x7 /*Rejected*/);
+ host_->on_subscription_status(_service, _instance, _eventgroup, _event, 0x7 /*Rejected*/);
+ } else {
+ stub_->send_subscribe_nack(_client, _service, _instance, _eventgroup,
+ _event);
+ }
+ } else {
+ std::set<client_t> subscribed_clients;
+ for (auto its_event : its_eventgroup->get_events()) {
+ for (auto its_client : its_event->get_subscribers()) {
+ subscribed_clients.insert(its_client);
+ }
+ }
+ for (auto its_subscriber : subscribed_clients) {
+ if (its_subscriber == get_client()) {
+ host_->on_subscription_error(_service, _instance, _eventgroup, 0x7 /*Rejected*/);
+ host_->on_subscription_status(_service, _instance, _eventgroup, _event, 0x7 /*Rejected*/);
+ } else {
+ stub_->send_subscribe_nack(its_subscriber, _service, _instance,
+ _eventgroup, _event);
+ }
+ }
}
- }
- if (_client == get_client()) {
- host_->on_subscription_error(_service, _instance, _eventgroup, 0x7 /*Rejected*/);
- } else {
- stub_->send_subscribe_nack(_client, _service, _instance, _eventgroup,
- _event);
}
}
@@ -2583,17 +2626,7 @@ bool routing_manager_impl::deliver_specific_endpoint_message(service_t _service,
void routing_manager_impl::clear_client_endpoints(service_t _service, instance_t _instance,
bool _reliable) {
- std::unordered_set<client_t> its_specific_endpoint_clients;
- {
- std::lock_guard<std::mutex> its_lock(specific_endpoint_clients_mutex_);
- auto found_service = specific_endpoint_clients_.find(_service);
- if(found_service != specific_endpoint_clients_.end()){
- auto found_instance = found_service->second.find(_instance);
- if(found_instance != found_service->second.end()) {
- its_specific_endpoint_clients = found_instance->second;
- }
- }
- }
+ auto its_specific_endpoint_clients = get_specific_endpoint_clients(_service, _instance);
{
std::lock_guard<std::recursive_mutex> its_lock(endpoint_mutex_);
std::shared_ptr<endpoint> deleted_endpoint;
@@ -2828,7 +2861,7 @@ void routing_manager_impl::send_error(return_code_e _return_code,
_receiver->is_reliable());
its_endpoint_def->set_remote_port(_receiver->get_local_port());
send_to(its_endpoint_def, serializer_->get_data(),
- serializer_->get_size(), true);
+ serializer_->get_size(), _instance, true);
}
serializer_->reset();
} else {
@@ -3360,29 +3393,22 @@ void routing_manager_impl::handle_client_error(client_t _client) {
}
}
-void routing_manager_impl::remove_specific_client_endpoint(client_t _client, service_t _service, instance_t _instance, bool _reliable)
-{
- std::lock_guard<std::mutex> its_lock(specific_endpoint_clients_mutex_);
- auto found_service = specific_endpoint_clients_.find(_service);
- if(found_service != specific_endpoint_clients_.end()){
- auto found_instance = found_service->second.find(_instance);
- if(found_instance != found_service->second.end()) {
- auto its_client = found_instance->second.find(_client);
- if (its_client != found_instance->second.end()) {
- std::lock_guard<std::recursive_mutex> its_lock(endpoint_mutex_);
- if (remote_services_.find(_service) != remote_services_.end()) {
- if (remote_services_[_service].find(_instance) != remote_services_[_service].end()) {
- auto endpoint = remote_services_[_service][_instance][_client][_reliable];
- if (endpoint) {
- service_instances_[_service].erase(endpoint.get());
- endpoint->stop();
- }
- remote_services_[_service][_instance][_client].erase(_reliable);
- auto found_endpoint = remote_services_[_service][_instance][_client].find(!_reliable);
- if (found_endpoint == remote_services_[_service][_instance][_client].end()) {
- remote_services_[_service][_instance].erase(_client);
- }
- }
+void routing_manager_impl::remove_specific_client_endpoint(client_t _client, service_t _service,
+ instance_t _instance, bool _reliable) {
+ client_t its_client = is_specific_endpoint_client(_client, _service, _instance);
+ if (its_client != VSOMEIP_ROUTING_CLIENT) {
+ std::lock_guard<std::recursive_mutex> its_lock(endpoint_mutex_);
+ if (remote_services_.find(_service) != remote_services_.end()) {
+ if (remote_services_[_service].find(_instance) != remote_services_[_service].end()) {
+ auto endpoint = remote_services_[_service][_instance][_client][_reliable];
+ if (endpoint) {
+ service_instances_[_service].erase(endpoint.get());
+ endpoint->stop();
+ }
+ remote_services_[_service][_instance][_client].erase(_reliable);
+ auto found_endpoint = remote_services_[_service][_instance][_client].find(!_reliable);
+ if (found_endpoint == remote_services_[_service][_instance][_client].end()) {
+ remote_services_[_service][_instance].erase(_client);
}
}
}
@@ -3471,20 +3497,8 @@ void routing_manager_impl::remove_identifying_client(service_t _service, instanc
void routing_manager_impl::unsubscribe_specific_client_at_sd(
service_t _service, instance_t _instance, client_t _client) {
- bool found(false);
- {
- std::lock_guard<std::mutex> its_lock(specific_endpoint_clients_mutex_);
- auto its_service = specific_endpoint_clients_.find(_service);
- if (its_service != specific_endpoint_clients_.end()) {
- auto its_instance = its_service->second.find(_instance);
- if (its_instance != its_service->second.end()) {
- if (its_instance->second.find(_client) != its_instance->second.end()) {
- found = true;
- }
- }
- }
- }
- if (found && discovery_) {
+ client_t subscriber = is_specific_endpoint_client(_client, _service, _instance);
+ if (subscriber != VSOMEIP_ROUTING_CLIENT && discovery_) {
discovery_->unsubscribe_client(_service, _instance, _client);
}
}
@@ -3505,13 +3519,13 @@ void routing_manager_impl::set_routing_state(routing_state_e _routing_state) {
switch (_routing_state) {
case vsomeip::routing_state_e::RS_SUSPENDED:
{
- // stop cycling offers for services and processing of incoming SD messages
+ VSOMEIP_INFO << "set routing to suspend mode";
+ // stop processing of incoming SD messages
discovery_->stop();
// send StopOffer messages for remotely offered services on this node
- services_t offered_services = get_offered_services();
- for (const auto its_service : offered_services) {
- for (const auto its_instance : its_service.second) {
+ for (const auto &its_service : get_offered_services()) {
+ for (const auto &its_instance : its_service.second) {
its_instance.second->set_ttl(0);
discovery_->stop_offer_service(its_service.first, its_instance.first, its_instance.second);
}
@@ -3525,15 +3539,9 @@ void routing_manager_impl::set_routing_state(routing_state_e _routing_state) {
}
for (auto its_eventgroup : get_subscribed_eventgroups(s.first, i.first)) {
discovery_->unsubscribe(s.first, i.first, its_eventgroup, VSOMEIP_ROUTING_CLIENT);
- std::lock_guard<std::mutex> its_lock(specific_endpoint_clients_mutex_);
- auto its_specific_service = specific_endpoint_clients_.find(s.first);
- if (its_specific_service != specific_endpoint_clients_.end()) {
- auto its_specific_instance = its_specific_service->second.find(i.first);
- if (its_specific_instance != its_specific_service->second.end()) {
- for (auto its_client : its_specific_instance->second) {
- discovery_->unsubscribe(s.first, i.first, its_eventgroup, its_client);
- }
- }
+ auto specific_endpoint_clients = get_specific_endpoint_clients(s.first, i.first);
+ for (auto its_client : specific_endpoint_clients) {
+ discovery_->unsubscribe(s.first, i.first, its_eventgroup, its_client);
}
}
}
@@ -3542,9 +3550,72 @@ void routing_manager_impl::set_routing_state(routing_state_e _routing_state) {
}
case vsomeip::routing_state_e::RS_RESUMED:
{
+ VSOMEIP_INFO << "set routing to resume mode";
+
+ // Reset relevant in service info
+ for (const auto &its_service : get_offered_services()) {
+ for (const auto &its_instance : its_service.second) {
+ its_instance.second->set_ttl(DEFAULT_TTL);
+ its_instance.second->set_is_in_mainphase(false);
+ }
+ }
+ // start processing of SD messages (incoming remote offers should lead to new subscribe messages)
discovery_->start();
+
+ // Trigger initial offer phase for relevant services
+ for (const auto &its_service : get_offered_services()) {
+ for (const auto &its_instance : its_service.second) {
+ discovery_->offer_service(its_service.first,
+ its_instance.first, its_instance.second);
+ }
+ }
break;
}
+ case routing_state_e::RS_DIAGNOSIS:
+ {
+ VSOMEIP_INFO << "set routing to diagnosis mode";
+ discovery_->set_diagnosis_mode(true);
+
+ // send StopOffer messages for all someip protocal services
+ for (const auto &its_service : get_offered_services()) {
+ for (const auto &its_instance : its_service.second) {
+ if (host_->get_configuration()->is_someip(
+ its_service.first, its_instance.first)) {
+ its_instance.second->set_ttl(0);
+ discovery_->stop_offer_service(
+ its_service.first, its_instance.first, its_instance.second);
+ }
+ }
+ }
+ break;
+ }
+ case routing_state_e::RS_RUNNING:
+ VSOMEIP_INFO << "set routing to running mode";
+
+ // Reset relevant in service info
+ for (const auto &its_service : get_offered_services()) {
+ for (const auto &its_instance : its_service.second) {
+ if (host_->get_configuration()->is_someip(
+ its_service.first, its_instance.first)) {
+ its_instance.second->set_ttl(DEFAULT_TTL);
+ its_instance.second->set_is_in_mainphase(false);
+ }
+ }
+ }
+ // Switch SD back to normal operation
+ discovery_->set_diagnosis_mode(false);
+
+ // Trigger initial phase for relevant services
+ for (const auto &its_service : get_offered_services()) {
+ for (const auto &its_instance : its_service.second) {
+ if (host_->get_configuration()->is_someip(
+ its_service.first, its_instance.first)) {
+ discovery_->offer_service(its_service.first,
+ its_instance.first, its_instance.second);
+ }
+ }
+ }
+ break;
default:
break;
}
@@ -3639,10 +3710,15 @@ routing_manager_impl::get_subscribed_eventgroups(
}
void routing_manager_impl::call_sd_reliable_endpoint_connected(
+ const boost::system::error_code& _error,
service_t _service, instance_t _instance,
- std::shared_ptr<endpoint> _endpoint) {
+ std::shared_ptr<endpoint> _endpoint,
+ std::shared_ptr<boost::asio::steady_timer> _timer) {
+ (void)_timer;
+ if (_error) {
+ return;
+ }
if (discovery_) {
- std::this_thread::sleep_for(std::chrono::milliseconds(3));
discovery_->on_reliable_endpoint_connected(_service, _instance,
_endpoint);
}
@@ -3699,19 +3775,80 @@ bool routing_manager_impl::create_placeholder_event_and_subscribe(
return is_inserted;
}
-void routing_manager_impl::on_reboot(const boost::asio::ip::address &_address){
- std::lock_guard<std::recursive_mutex> its_lock(endpoint_mutex_);
- for (auto its_port : server_endpoints_) {
- for (auto its_endpoint : its_port.second) {
- if (its_endpoint.first == true) {
- std::shared_ptr<tcp_server_endpoint_impl> endpoint = std::dynamic_pointer_cast<tcp_server_endpoint_impl>(its_endpoint.second);
- if (endpoint) {
- endpoint->stop_all_connections(_address);
+void routing_manager_impl::handle_subscription_state(client_t _client, service_t _service, instance_t _instance,
+ eventgroup_t _eventgroup, event_t _event) {
+
+ client_t subscriber = is_specific_endpoint_client(_client, _service, _instance);
+ auto its_tuple = std::make_tuple(_service, _instance, _eventgroup, subscriber);
+
+ std::lock_guard<std::mutex> its_lock(remote_subscription_state_mutex_);
+ auto its_state = remote_subscription_state_.find(its_tuple);
+ if (its_state != remote_subscription_state_.end()) {
+ if (its_state->second == subscription_state_e::SUBSCRIPTION_ACKNOWLEDGED) {
+ // Subscription already acknowledged!
+ if (_client == get_client()) {
+ host_->on_subscription_error(_service, _instance, _eventgroup, 0x0 /*OK*/);
+ host_->on_subscription_status(_service, _instance, _eventgroup, _event, 0x0 /*OK*/);
+ } else {
+ stub_->send_subscribe_ack(_client, _service, _instance, _eventgroup, _event);
+ }
+ }
+ } else {
+ remote_subscription_state_[its_tuple] = subscription_state_e::IS_SUBSCRIBING;
+ }
+}
+
+client_t routing_manager_impl::is_specific_endpoint_client(client_t _client,
+ service_t _service, instance_t _instance) {
+ client_t result = VSOMEIP_ROUTING_CLIENT;
+ {
+ std::lock_guard<std::mutex> its_lock(specific_endpoint_clients_mutex_);
+ auto found_service = specific_endpoint_clients_.find(_service);
+ if (found_service != specific_endpoint_clients_.end()) {
+ auto found_instance = found_service->second.find(_instance);
+ if (found_instance != found_service->second.end()) {
+ auto found_client = found_instance->second.find(_client);
+ if(found_client != found_instance->second.end()) {
+ result = _client;
}
}
}
}
+ // A client_t != VSOMEIP_ROUTING_CLIENT implies true
+ return result;
}
+std::unordered_set<client_t> routing_manager_impl::get_specific_endpoint_clients(
+ service_t _service, instance_t _instance) {
+ std::unordered_set<client_t> result;
+ {
+ std::lock_guard<std::mutex> its_lock(specific_endpoint_clients_mutex_);
+ auto found_service = specific_endpoint_clients_.find(_service);
+ if (found_service != specific_endpoint_clients_.end()) {
+ auto found_instance = found_service->second.find(_instance);
+ if (found_instance != found_service->second.end()) {
+ result = found_instance->second;
+ }
+ }
+ }
+ return result;
+}
+
+bool routing_manager_impl::remote_service_offered_via_tcp_and_udp(
+ service_t _service, instance_t _instance) const {
+ bool ret(false);
+ std::lock_guard<std::recursive_mutex> its_lock(endpoint_mutex_);
+ const auto found_service = remote_service_info_.find(_service);
+ if (found_service != remote_service_info_.end()) {
+ const auto found_instance = found_service->second.find(_instance);
+ if (found_instance != found_service->second.end()) {
+ if (found_instance->second.find(false) != found_instance->second.end() &&
+ found_instance->second.find(true) != found_instance->second.end()) {
+ ret = true;
+ }
+ }
+ }
+ return ret;
+}
} // namespace vsomeip
diff --git a/implementation/routing/src/routing_manager_proxy.cpp b/implementation/routing/src/routing_manager_proxy.cpp
index 00359f9..6e5cf6a 100644
--- a/implementation/routing/src/routing_manager_proxy.cpp
+++ b/implementation/routing/src/routing_manager_proxy.cpp
@@ -139,7 +139,7 @@ void routing_manager_proxy::stop() {
}
std::stringstream its_client;
- its_client << VSOMEIP_BASE_PATH << std::hex << client_;
+ its_client << utility::get_base_path(configuration_) << std::hex << client_;
#ifdef _WIN32
::_unlink(its_client.str().c_str());
#else
@@ -593,7 +593,8 @@ void routing_manager_proxy::unsubscribe(client_t _client, service_t _service,
bool routing_manager_proxy::send(client_t _client, const byte_t *_data,
length_t _size, instance_t _instance,
bool _flush,
- bool _reliable) {
+ bool _reliable,
+ bool _is_valid_crc) {
(void)_client;
bool is_sent(false);
bool has_remote_subscribers(false);
@@ -630,7 +631,7 @@ bool routing_manager_proxy::send(client_t _client, const byte_t *_data,
_client == VSOMEIP_ROUTING_CLIENT) {
// notify
has_remote_subscribers = send_local_notification(get_client(), _data, _size,
- _instance, _flush, _reliable);
+ _instance, _flush, _reliable, _is_valid_crc);
} else if (utility::is_notification(_data[VSOMEIP_MESSAGE_TYPE_POS]) &&
_client != VSOMEIP_ROUTING_CLIENT) {
// notify_one
@@ -641,12 +642,12 @@ bool routing_manager_proxy::send(client_t _client, const byte_t *_data,
= uint16_t(_size > USHRT_MAX ? USHRT_MAX : _size);
tc::trace_header its_header;
- if (its_header.prepare(nullptr, true))
+ if (its_header.prepare(nullptr, true, _instance))
tc_->trace(its_header.data_, VSOMEIP_TRACE_HEADER_SIZE,
_data, its_data_size);
#endif
return send_local(its_target, get_client(), _data, _size,
- _instance, _flush, _reliable, VSOMEIP_SEND);
+ _instance, _flush, _reliable, VSOMEIP_SEND, _is_valid_crc);
}
}
// If no direct endpoint could be found
@@ -685,7 +686,7 @@ bool routing_manager_proxy::send(client_t _client, const byte_t *_data,
= uint16_t(_size > USHRT_MAX ? USHRT_MAX : _size);
tc::trace_header its_header;
- if (its_header.prepare(nullptr, true))
+ if (its_header.prepare(nullptr, true, _instance))
tc_->trace(its_header.data_, VSOMEIP_TRACE_HEADER_SIZE,
_data, its_data_size);
}
@@ -693,7 +694,7 @@ bool routing_manager_proxy::send(client_t _client, const byte_t *_data,
if (send) {
is_sent = send_local(its_target,
(command == VSOMEIP_NOTIFY_ONE ? _client : get_client()),
- _data, _size, _instance, _flush, _reliable, command);
+ _data, _size, _instance, _flush, _reliable, command, _is_valid_crc);
}
}
return (is_sent);
@@ -711,11 +712,12 @@ bool routing_manager_proxy::send_to(
bool routing_manager_proxy::send_to(
const std::shared_ptr<endpoint_definition> &_target,
- const byte_t *_data, uint32_t _size,
+ const byte_t *_data, uint32_t _size, instance_t _instance,
bool _flush) {
(void)_target;
(void)_data;
(void)_size;
+ (void)_instance;
(void)_flush;
return (false);
}
@@ -817,14 +819,18 @@ void routing_manager_proxy::on_message(const byte_t *_data, length_t _size,
instance_t its_instance;
std::memcpy(&its_instance,
&_data[_size - sizeof(instance_t) - sizeof(bool)
- - sizeof(bool)], sizeof(instance_t));
+ - sizeof(bool) - sizeof(bool)], sizeof(instance_t));
bool its_reliable;
- std::memcpy(&its_reliable, &_data[_size - sizeof(bool)],
+ std::memcpy(&its_reliable, &_data[_size - sizeof(bool) - sizeof(bool)],
sizeof(its_reliable));
- // reduce by size of instance, flush and reliable flag
+ bool its_is_vslid_crc;
+ std::memcpy(&its_is_vslid_crc, &_data[_size - sizeof(bool)],
+ sizeof(its_is_vslid_crc));
+
+ // reduce by size of instance, flush, reliable and is_valid_crc flag
const std::uint32_t its_message_size = its_length -
static_cast<uint32_t>(sizeof(its_instance)
- + sizeof(bool) + sizeof(bool));
+ + sizeof(bool) + sizeof(bool) + sizeof(bool));
auto a_deserializer = get_deserializer();
a_deserializer->set_data(&_data[VSOMEIP_COMMAND_PAYLOAD_POS],
@@ -836,6 +842,7 @@ void routing_manager_proxy::on_message(const byte_t *_data, length_t _size,
if (its_message) {
its_message->set_instance(its_instance);
its_message->set_reliable(its_reliable);
+ its_message->set_is_valid_crc(its_is_vslid_crc);
if (utility::is_notification(its_message->get_message_type())) {
if (!configuration_->is_client_allowed(get_client(), its_message->get_service(),
its_message->get_instance())) {
@@ -909,48 +916,54 @@ void routing_manager_proxy::on_message(const byte_t *_data, length_t _size,
std::memcpy(&is_remote_subscriber, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 9],
sizeof(is_remote_subscriber));
- if (is_remote_subscriber) {
- // Remote subscriber: Notify routing manager initially + count subscribes
- (void)host_->on_subscription(its_service, its_instance,
- its_eventgroup, its_client, true);
- bool inserted = insert_subscription(its_service, its_instance, its_eventgroup,
- its_event, VSOMEIP_ROUTING_CLIENT);
- if (inserted) {
- notify_remote_initally(its_service, its_instance, its_eventgroup);
- }
- (void)get_remote_subscriber_count(its_service, its_instance, its_eventgroup, true);
- } else if (is_client_known(its_client)) {
- if (!configuration_->is_client_allowed(its_client,
- its_service, its_instance)) {
- VSOMEIP_WARNING << "Security: Client " << std::hex
- << its_client << " subscribes to service/instance "
- << its_service << "/" << its_instance
- << " which violates the security policy ~> Skip subscribe!";
- return;
- }
+ {
+ std::unique_lock<std::mutex> its_lock(incoming_subscripitons_mutex_);
+ if (is_remote_subscriber) {
+ its_lock.unlock();
+ // Remote subscriber: Notify routing manager initially + count subscribes
+ (void)host_->on_subscription(its_service, its_instance,
+ its_eventgroup, its_client, true);
+ std::set<event_t> its_already_subscribed_events;
+ bool inserted = insert_subscription(its_service, its_instance, its_eventgroup,
+ its_event, VSOMEIP_ROUTING_CLIENT, &its_already_subscribed_events);
+ if (inserted) {
+ notify_remote_initially(its_service, its_instance, its_eventgroup,
+ its_already_subscribed_events);
+ }
+ (void)get_remote_subscriber_count(its_service, its_instance, its_eventgroup, true);
+ } else if (is_client_known(its_client)) {
+ its_lock.unlock();
+ if (!configuration_->is_client_allowed(its_client,
+ its_service, its_instance)) {
+ VSOMEIP_WARNING << "Security: Client " << std::hex
+ << its_client << " subscribes to service/instance "
+ << its_service << "/" << its_instance
+ << " which violates the security policy ~> Skip subscribe!";
+ return;
+ }
- // Local & already known subscriber: create endpoint + send (N)ACK + insert subscription
- (void) find_or_create_local(its_client);
- bool subscription_accepted = host_->on_subscription(its_service, its_instance,
- its_eventgroup, its_client, true);
- if (!subscription_accepted) {
- send_subscribe_nack(its_client, its_service,
- its_instance, its_eventgroup, its_event);
+ // Local & already known subscriber: create endpoint + send (N)ACK + insert subscription
+ (void) find_or_create_local(its_client);
+ bool subscription_accepted = host_->on_subscription(its_service, its_instance,
+ its_eventgroup, its_client, true);
+ if (!subscription_accepted) {
+ send_subscribe_nack(its_client, its_service,
+ its_instance, its_eventgroup, its_event);
+ } else {
+ send_subscribe_ack(its_client, its_service, its_instance,
+ its_eventgroup, its_event);
+ routing_manager_base::subscribe(its_client, its_service, its_instance,
+ its_eventgroup, its_major, its_event,
+ subscription_type_e::SU_RELIABLE_AND_UNRELIABLE);
+ send_pending_notify_ones(its_service, its_instance, its_eventgroup, its_client);
+ }
} else {
- send_subscribe_ack(its_client, its_service, its_instance,
- its_eventgroup, its_event);
- routing_manager_base::subscribe(its_client, its_service, its_instance,
+ // Local & not yet known subscriber ~> set pending until subscriber gets known!
+ subscription_data_t subscription = { its_service, its_instance,
its_eventgroup, its_major, its_event,
- subscription_type_e::SU_RELIABLE_AND_UNRELIABLE);
- send_pending_notify_ones(its_service, its_instance, its_eventgroup, its_client);
+ subscription_type_e::SU_RELIABLE_AND_UNRELIABLE};
+ pending_incoming_subscripitons_[its_client].insert(subscription);
}
- } else {
- // Local & not yet known subscriber ~> set pending until subscriber gets known!
- subscription_data_t subscription = { its_service, its_instance,
- its_eventgroup, its_major, its_event,
- subscription_type_e::SU_RELIABLE_AND_UNRELIABLE};
- std::lock_guard<std::mutex> its_lock(pending_ingoing_subscripitons_mutex_);
- pending_ingoing_subscripitons_[its_client].insert(subscription);
}
VSOMEIP_INFO << "SUBSCRIBE("
<< std::hex << std::setw(4) << std::setfill('0') << its_client <<"): ["
@@ -1011,7 +1024,7 @@ void routing_manager_proxy::on_message(const byte_t *_data, length_t _size,
std::memcpy(&its_event, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 8],
sizeof(its_event));
- on_subscribe_nack(its_subscriber, its_service, its_instance, its_eventgroup);
+ on_subscribe_nack(its_subscriber, its_service, its_instance, its_eventgroup, its_event);
VSOMEIP_INFO << "SUBSCRIBE NACK("
<< std::hex << std::setw(4) << std::setfill('0') << its_client << "): ["
<< std::hex << std::setw(4) << std::setfill('0') << its_service << "."
@@ -1036,7 +1049,7 @@ void routing_manager_proxy::on_message(const byte_t *_data, length_t _size,
std::memcpy(&its_event, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 8],
sizeof(its_event));
- on_subscribe_ack(its_subscriber, its_service, its_instance, its_eventgroup);
+ on_subscribe_ack(its_subscriber, its_service, its_instance, its_eventgroup, its_event);
VSOMEIP_INFO << "SUBSCRIBE ACK("
<< std::hex << std::setw(4) << std::setfill('0') << its_client << "): ["
<< std::hex << std::setw(4) << std::setfill('0') << its_service << "."
@@ -1079,25 +1092,6 @@ void routing_manager_proxy::on_routing_info(const byte_t *_data,
VSOMEIP_INFO << msg.str();
#endif
- bool restart_sender(_size == 1);
- if (restart_sender && is_started_) {
- // Handle restart to routing manager!
- std::unordered_set<client_t> clients_to_delete;
- {
- std::lock_guard<std::mutex> its_lock(known_clients_mutex_);
- for (auto its_client : known_clients_) {
- if (its_client != get_client()) {
- clients_to_delete.insert(its_client);
- }
- }
- }
-
- reconnect(clients_to_delete);
-
- // Abort due to routing manager has stopped
- return;
- }
-
uint32_t i = 0;
while (i + sizeof(uint32_t) + sizeof(routing_info_entry_e) <= _size) {
routing_info_entry_e routing_info_entry;
@@ -1233,14 +1227,14 @@ void routing_manager_proxy::on_routing_info(const byte_t *_data,
major_version_t major_;
event_t event_;
};
- std::lock_guard<std::mutex> its_lock(pending_ingoing_subscripitons_mutex_);
+ std::lock_guard<std::mutex> its_lock(incoming_subscripitons_mutex_);
std::forward_list<struct subscription_info> subscription_actions;
- if (pending_ingoing_subscripitons_.size()) {
+ if (pending_incoming_subscripitons_.size()) {
{
std::lock_guard<std::mutex> its_lock(known_clients_mutex_);
for (const client_t client : known_clients_) {
- auto its_client = pending_ingoing_subscripitons_.find(client);
- if (its_client != pending_ingoing_subscripitons_.end()) {
+ auto its_client = pending_incoming_subscripitons_.find(client);
+ if (its_client != pending_incoming_subscripitons_.end()) {
for (const auto subscription : its_client->second) {
subscription_actions.push_front(
{ subscription.service_, subscription.instance_,
@@ -1268,7 +1262,7 @@ void routing_manager_proxy::on_routing_info(const byte_t *_data,
send_pending_notify_ones(si.service_id_,
si.instance_id_, si.eventgroup_id_, si.client_id_);
}
- pending_ingoing_subscripitons_.erase(si.client_id_);
+ pending_incoming_subscripitons_.erase(si.client_id_);
}
}
}
@@ -1307,8 +1301,6 @@ void routing_manager_proxy::register_application() {
std::memcpy(&its_command[VSOMEIP_COMMAND_CLIENT_POS], &client_,
sizeof(client_));
- std::memset(&its_command[VSOMEIP_COMMAND_SIZE_POS_MIN], 0,
- sizeof(uint32_t));
if (is_connected_) {
std::lock_guard<std::mutex> its_state_lock(state_mutex_);
@@ -1367,8 +1359,13 @@ void routing_manager_proxy::send_request_services(std::set<service_data_t>& _req
if (!_requests.size()) {
return;
}
- uint32_t its_size = (VSOMEIP_REQUEST_SERVICE_COMMAND_SIZE - VSOMEIP_COMMAND_HEADER_SIZE)
- * (uint32_t)_requests.size();
+ size_t its_size = (VSOMEIP_REQUEST_SERVICE_COMMAND_SIZE
+ - VSOMEIP_COMMAND_HEADER_SIZE) * _requests.size();
+ if (its_size > (std::numeric_limits<std::uint32_t>::max)()) {
+ VSOMEIP_ERROR<< "routing_manager_proxy::send_request_services too many"
+ << " requests (" << std::dec << its_size << "), returning.";
+ return;
+ }
std::vector<byte_t> its_command(its_size + VSOMEIP_COMMAND_HEADER_SIZE);
its_command[VSOMEIP_COMMAND_TYPE_POS] = VSOMEIP_REQUEST_SERVICE;
@@ -1397,7 +1394,7 @@ void routing_manager_proxy::send_request_services(std::set<service_data_t>& _req
{
std::lock_guard<std::mutex> its_lock(sender_mutex_);
if (sender_) {
- sender_->send(&its_command[0], its_size + VSOMEIP_COMMAND_HEADER_SIZE);
+ sender_->send(&its_command[0], static_cast<std::uint32_t>(its_size + VSOMEIP_COMMAND_HEADER_SIZE));
}
}
}
@@ -1432,11 +1429,16 @@ void routing_manager_proxy::send_register_event(client_t _client,
event_t _event, const std::set<eventgroup_t> &_eventgroups,
bool _is_field, bool _is_provided) {
- uint32_t its_eventgroups_size = uint32_t(_eventgroups.size() * sizeof(eventgroup_t));
- byte_t *its_command = new byte_t[VSOMEIP_REGISTER_EVENT_COMMAND_SIZE + its_eventgroups_size];
- uint32_t its_size = VSOMEIP_REGISTER_EVENT_COMMAND_SIZE
- + its_eventgroups_size
- - VSOMEIP_COMMAND_HEADER_SIZE;
+ std::size_t its_eventgroups_size = (_eventgroups.size() * sizeof(eventgroup_t)) +
+ VSOMEIP_REGISTER_EVENT_COMMAND_SIZE;
+ if (its_eventgroups_size > (std::numeric_limits<std::uint32_t>::max)()) {
+ VSOMEIP_ERROR<< "routing_manager_proxy::send_register_event too many"
+ << " eventgroups (" << std::dec << its_eventgroups_size << "), returning.";
+ return;
+ }
+ byte_t *its_command = new byte_t[its_eventgroups_size];
+ uint32_t its_size = static_cast<std::uint32_t>(its_eventgroups_size)
+ - VSOMEIP_COMMAND_HEADER_SIZE;
its_command[VSOMEIP_COMMAND_TYPE_POS] = VSOMEIP_REGISTER_EVENT;
std::memcpy(&its_command[VSOMEIP_COMMAND_CLIENT_POS], &client_,
@@ -1464,9 +1466,7 @@ void routing_manager_proxy::send_register_event(client_t _client,
{
std::lock_guard<std::mutex> its_lock(sender_mutex_);
if (sender_) {
- sender_->send(its_command,
- uint32_t(VSOMEIP_REGISTER_EVENT_COMMAND_SIZE
- + its_eventgroups_size));
+ sender_->send(its_command, static_cast<std::uint32_t>(its_eventgroups_size));
}
}
@@ -1474,15 +1474,37 @@ void routing_manager_proxy::send_register_event(client_t _client,
}
void routing_manager_proxy::on_subscribe_ack(client_t _client,
- service_t _service, instance_t _instance, eventgroup_t _eventgroup) {
+ service_t _service, instance_t _instance, eventgroup_t _eventgroup, event_t _event) {
(void)_client;
- host_->on_subscription_error(_service, _instance, _eventgroup, 0x0 /*OK*/);
+ if (_event == ANY_EVENT) {
+ auto its_eventgroup = find_eventgroup(_service, _instance, _eventgroup);
+ if (its_eventgroup) {
+ for (auto its_event : its_eventgroup->get_events()) {
+ host_->on_subscription_error(_service, _instance, _eventgroup, 0x0 /*OK*/);
+ host_->on_subscription_status(_service, _instance, _eventgroup, its_event->get_event(), 0x0 /*OK*/);
+ }
+ }
+ } else {
+ host_->on_subscription_error(_service, _instance, _eventgroup, 0x0 /*OK*/);
+ host_->on_subscription_status(_service, _instance, _eventgroup, _event, 0x0 /*OK*/);
+ }
}
void routing_manager_proxy::on_subscribe_nack(client_t _client,
- service_t _service, instance_t _instance, eventgroup_t _eventgroup) {
+ service_t _service, instance_t _instance, eventgroup_t _eventgroup, event_t _event) {
(void)_client;
- host_->on_subscription_error(_service, _instance, _eventgroup, 0x7 /*Rejected*/);
+ if (_event == ANY_EVENT) {
+ auto its_eventgroup = find_eventgroup(_service, _instance, _eventgroup);
+ if (its_eventgroup) {
+ for (auto its_event : its_eventgroup->get_events()) {
+ host_->on_subscription_error(_service, _instance, _eventgroup, 0x7 /*Rejected*/);
+ host_->on_subscription_status(_service, _instance, _eventgroup, its_event->get_event(), 0x7 /*Rejected*/);
+ }
+ }
+ } else {
+ host_->on_subscription_error(_service, _instance, _eventgroup, 0x7 /*Rejected*/);
+ host_->on_subscription_status(_service, _instance, _eventgroup, _event, 0x7 /*Rejected*/);
+ }
}
void routing_manager_proxy::on_identify_response(client_t _client, service_t _service,
@@ -1575,7 +1597,7 @@ void routing_manager_proxy::send_pending_commands() {
void routing_manager_proxy::init_receiver() {
std::stringstream its_client;
- its_client << VSOMEIP_BASE_PATH << std::hex << client_;
+ its_client << utility::get_base_path(configuration_) << std::hex << client_;
#ifdef _WIN32
::_unlink(its_client.str().c_str());
int port = VSOMEIP_INTERNAL_BASE_PORT + client_;
@@ -1615,21 +1637,21 @@ void routing_manager_proxy::init_receiver() {
#endif
}
-void routing_manager_proxy::notify_remote_initally(service_t _service, instance_t _instance,
- eventgroup_t _eventgroup) {
+void routing_manager_proxy::notify_remote_initially(service_t _service, instance_t _instance,
+ eventgroup_t _eventgroup, const std::set<event_t> &_events_to_exclude) {
auto its_eventgroup = find_eventgroup(_service, _instance, _eventgroup);
if (its_eventgroup) {
- std::set<std::shared_ptr<event> > its_events
- = its_eventgroup->get_events();
- for (auto e : its_events) {
- if (e->is_field() && e->is_set()) {
+ auto service_info = find_service(_service, _instance);
+ for (const auto &e : its_eventgroup->get_events()) {
+ if (e->is_field() && e->is_set()
+ && _events_to_exclude.find(e->get_event())
+ == _events_to_exclude.end()) {
std::shared_ptr<message> its_notification
= runtime::get()->create_notification();
its_notification->set_service(_service);
its_notification->set_instance(_instance);
its_notification->set_method(e->get_event());
its_notification->set_payload(e->get_payload());
- auto service_info = find_service(_service, _instance);
if (service_info) {
its_notification->set_interface_version(service_info->get_major());
}
@@ -1706,13 +1728,11 @@ void routing_manager_proxy::register_application_timeout_cbk(
}
void routing_manager_proxy::send_registered_ack() {
- byte_t its_command[VSOMEIP_COMMAND_HEADER_SIZE];
- its_command[VSOMEIP_COMMAND_TYPE_POS] = VSOMEIP_REGISTERED_ACK;
+ byte_t its_command[VSOMEIP_COMMAND_HEADER_SIZE] = {
+ VSOMEIP_REGISTERED_ACK, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
client_t client = get_client();
std::memcpy(&its_command[VSOMEIP_COMMAND_CLIENT_POS], &client,
sizeof(client));
- std::memset(&its_command[VSOMEIP_COMMAND_SIZE_POS_MIN], 0,
- sizeof(uint32_t));
{
std::lock_guard<std::mutex> its_lock(sender_mutex_);
if (sender_) {
diff --git a/implementation/routing/src/routing_manager_stub.cpp b/implementation/routing/src/routing_manager_stub.cpp
index 526d6ce..2ce4d63 100644
--- a/implementation/routing/src/routing_manager_stub.cpp
+++ b/implementation/routing/src/routing_manager_stub.cpp
@@ -154,11 +154,6 @@ void routing_manager_stub::stop() {
}
#endif
}
-
- {
- std::lock_guard<std::mutex> its_lock(routing_info_mutex_);
- broadcast_routing_stop();
- }
}
const std::shared_ptr<configuration> routing_manager_stub::get_configuration() const {
@@ -232,6 +227,8 @@ void routing_manager_stub::on_message(const byte_t *_data, length_t _size,
client_t its_client_from_header;
client_t its_target_client;
client_t its_subscriber;
+ bool its_is_valid_crc(true);
+
its_command = _data[VSOMEIP_COMMAND_TYPE_POS];
std::memcpy(&its_client, &_data[VSOMEIP_COMMAND_CLIENT_POS],
@@ -411,8 +408,11 @@ void routing_manager_stub::on_message(const byte_t *_data, length_t _size,
its_data[VSOMEIP_CLIENT_POS_MIN],
its_data[VSOMEIP_CLIENT_POS_MAX]);
std::memcpy(&its_instance, &_data[_size - sizeof(instance_t)
- - sizeof(bool) - sizeof(bool)], sizeof(its_instance));
- std::memcpy(&its_reliable, &_data[_size - sizeof(bool)], sizeof(its_reliable));
+ - sizeof(bool) - sizeof(bool) - sizeof(bool)], sizeof(its_instance));
+ std::memcpy(&its_reliable, &_data[_size - sizeof(bool) - sizeof(bool)], sizeof(its_reliable));
+
+ std::memcpy(&its_is_valid_crc, &_data[_size - sizeof(bool)], sizeof(its_is_valid_crc));
+
if (utility::is_request(its_data[VSOMEIP_MESSAGE_TYPE_POS])) {
if (!configuration_->is_client_allowed(its_client_from_header,
its_service, its_instance)) {
@@ -434,11 +434,11 @@ void routing_manager_stub::on_message(const byte_t *_data, length_t _size,
return;
}
}
- // reduce by size of instance, flush and reliable flag
+ // reduce by size of instance, flush, reliable and is_valid_crc flag
const std::uint32_t its_message_size = its_size -
static_cast<std::uint32_t>(sizeof(its_instance)
- + sizeof(bool) + sizeof(bool));
- host_->on_message(its_service, its_instance, its_data, its_message_size, its_reliable);
+ + sizeof(bool) + sizeof(bool) + sizeof(bool));
+ host_->on_message(its_service, its_instance, its_data, its_message_size, its_reliable, its_is_valid_crc);
break;
}
case VSOMEIP_NOTIFY: {
@@ -447,8 +447,8 @@ void routing_manager_stub::on_message(const byte_t *_data, length_t _size,
its_data[VSOMEIP_SERVICE_POS_MIN],
its_data[VSOMEIP_SERVICE_POS_MAX]);
std::memcpy(&its_instance, &_data[_size - sizeof(instance_t)
- - sizeof(bool) - sizeof(bool)], sizeof(its_instance));
- // reduce by size of instance, flush and reliable flag
+ - sizeof(bool) - sizeof(bool) - sizeof(bool)], sizeof(its_instance));
+ // reduce by size of instance, flush, reliable and is_valid_crc flag
const std::uint32_t its_message_size = its_size -
static_cast<uint32_t>(sizeof(its_instance)
+ sizeof(bool) + sizeof(bool));
@@ -461,10 +461,10 @@ void routing_manager_stub::on_message(const byte_t *_data, length_t _size,
its_data[VSOMEIP_SERVICE_POS_MIN],
its_data[VSOMEIP_SERVICE_POS_MAX]);
std::memcpy(&its_instance, &_data[_size - sizeof(instance_t) -
- sizeof(bool) - sizeof(bool) - sizeof(client_t)],
+ sizeof(bool) - sizeof(bool) - sizeof(bool) - sizeof(client_t)],
sizeof(its_instance));
std::memcpy(&its_target_client, &_data[_size - sizeof(client_t)], sizeof(client_t));
- // reduce by size of instance, flush, reliable flag and target client
+ // reduce by size of instance, flush, reliable flag, is_valid_crc and target client
const std::uint32_t its_message_size = its_size -
static_cast<uint32_t>(sizeof(its_instance)
+ sizeof(bool) + sizeof(bool) + sizeof(client_t));
@@ -708,7 +708,8 @@ void routing_manager_stub::client_registration_func(void) {
if (its_connection != connection_matrix_.end()) {
for (auto its_client : its_connection->second) {
if (its_client != r.first &&
- its_client != VSOMEIP_ROUTING_CLIENT) {
+ its_client != VSOMEIP_ROUTING_CLIENT &&
+ its_client != get_client()) {
create_client_routing_info(its_client);
insert_client_routing_info(its_client,
routing_info_entry_e::RIE_DEL_CLIENT, r.first);
@@ -735,7 +736,7 @@ void routing_manager_stub::client_registration_func(void) {
void routing_manager_stub::init_routing_endpoint() {
std::stringstream its_endpoint_path;
- its_endpoint_path << VSOMEIP_BASE_PATH << VSOMEIP_ROUTING_CLIENT;
+ its_endpoint_path << utility::get_base_path(configuration_) << VSOMEIP_ROUTING_CLIENT;
endpoint_path_ = its_endpoint_path.str();
client_t routing_host_id = configuration_->get_id(configuration_->get_routing_host());
if (configuration_->is_security_enabled() && get_client() != routing_host_id) {
@@ -893,7 +894,7 @@ void routing_manager_stub::send_client_routing_info(const client_t _target) {
#if 0
std::stringstream msg;
- msg << "rms::send_routing_info ";
+ msg << "rms::send_routing_info to (" << std::hex << _target << "): ";
for (uint32_t i = 0; i < its_size; ++i)
msg << std::hex << std::setw(2) << std::setfill('0') << (int)its_command[i] << " ";
VSOMEIP_INFO << msg.str();
@@ -908,6 +909,9 @@ void routing_manager_stub::send_client_routing_info(const client_t _target) {
}
client_routing_info_.erase(_target);
+ } else {
+ VSOMEIP_ERROR << "Send routing info to client 0x" << std::hex << _target
+ << " failed: No valid endpoint!";
}
}
@@ -1009,10 +1013,13 @@ void routing_manager_stub::inform_requesters(client_t _hoster, service_t _servic
}
}
}
- create_client_routing_info(its_client.first);
- insert_client_routing_info(its_client.first, _entry, _hoster,
- _service, _instance, _major, _minor);
- send_client_routing_info(its_client.first);
+ if (its_client.first != VSOMEIP_ROUTING_CLIENT &&
+ its_client.first != get_client()) {
+ create_client_routing_info(its_client.first);
+ insert_client_routing_info(its_client.first, _entry, _hoster,
+ _service, _instance, _major, _minor);
+ send_client_routing_info(its_client.first);
+ }
}
}
}
@@ -1022,39 +1029,6 @@ bool routing_manager_stub::is_already_connected(client_t _source, client_t _sink
return connection_matrix_[_source].find(_sink) != connection_matrix_[_source].end();
}
-void routing_manager_stub::broadcast_routing_stop() {
- std::vector<byte_t> its_command;
-
- // Routing command
- its_command.push_back(VSOMEIP_ROUTING_INFO);
-
- // Sender client
- client_t client = get_client();
- for (uint32_t i = 0; i < sizeof(client_t); ++i) {
- its_command.push_back(
- reinterpret_cast<const byte_t*>(&client)[i]);
- }
-
- // Overall size ~> 1 indicates routing stop
- uint32_t size = 0x1;
- for (uint32_t i = 0; i < sizeof(uint32_t); ++i) {
- its_command.push_back(
- reinterpret_cast<const byte_t*>(&size)[i]);
- }
-
- // Stop Placeholder
- its_command.push_back(0x0);
-
- for (auto& info : routing_info_) {
- if (info.first != VSOMEIP_ROUTING_CLIENT && info.first != host_->get_client()) {
- std::shared_ptr<endpoint> its_endpoint = host_->find_local(info.first);
- if (its_endpoint) {
- its_endpoint->send(&its_command[0], uint32_t(its_command.size()), true);
- }
- }
- }
-}
-
void routing_manager_stub::broadcast(const std::vector<byte_t> &_command) const {
std::lock_guard<std::mutex> its_guard(routing_info_mutex_);
for (auto a : routing_info_) {
@@ -1288,7 +1262,7 @@ void routing_manager_stub::create_local_receiver() {
return;
}
std::stringstream its_local_receiver_path;
- its_local_receiver_path << VSOMEIP_BASE_PATH << std::hex << host_->get_client();
+ its_local_receiver_path << utility::get_base_path(configuration_) << std::hex << host_->get_client();
local_receiver_path_ = its_local_receiver_path.str();
#if _WIN32
::_unlink(local_receiver_path_.c_str());
@@ -1491,6 +1465,27 @@ void routing_manager_stub::update_registration(client_t _client,
<< (_type == registration_type_e::REGISTER ?
"registering." : "deregistering.");
+ if (_type == registration_type_e::DEREGISTER) {
+ // If we receive a DEREGISTER client command
+ // the endpoint error handler is not longer needed
+ // as the client is going down anyways.
+
+ // Normally the handler is removed in "remove_local"
+ // anyways, but as some time takes place until
+ // the client DEREGISTER command is consumed
+ // and therefore "remove_local" is finally called
+ // it was possible the same client registers itself
+ // again in very short time and then could "overtake"
+ // the occurring error in the endpoint and was then
+ // erroneously unregistered even that error has
+ // nothing to do with the newly registered client.
+
+ auto its_endpoint = host_->find_local(_client);
+ if (its_endpoint) {
+ its_endpoint->register_error_handler(nullptr);
+ }
+ }
+
std::lock_guard<std::mutex> its_lock(client_registration_mutex_);
pending_client_registrations_[_client].push_back(_type);
client_registration_condition_.notify_one();
@@ -1509,6 +1504,7 @@ void routing_manager_stub::handle_requests(const client_t _client, std::set<serv
if (!_requests.size()) {
return;
}
+ bool service_available(false);
std::lock_guard<std::mutex> its_guard(routing_info_mutex_);
create_client_routing_info(_client);
for (auto request : _requests) {
@@ -1522,6 +1518,7 @@ void routing_manager_stub::handle_requests(const client_t _client, std::set<serv
found_client.first != host_->get_client()) {
if (!is_already_connected(found_client.first, _client)) {
if (_client == found_client.first) {
+ service_available = true;
insert_client_routing_info(found_client.first,
routing_info_entry_e::RIE_ADD_CLIENT, _client);
} else {
@@ -1535,6 +1532,7 @@ void routing_manager_stub::handle_requests(const client_t _client, std::set<serv
if (_client != VSOMEIP_ROUTING_CLIENT &&
_client != host_->get_client()) {
for (auto instance : found_service->second) {
+ service_available = true;
insert_client_routing_info(_client,
routing_info_entry_e::RIE_ADD_SERVICE_INSTANCE,
found_client.first, request.service_, instance.first,
@@ -1549,6 +1547,7 @@ void routing_manager_stub::handle_requests(const client_t _client, std::set<serv
found_client.first != host_->get_client()) {
if (!is_already_connected(found_client.first, _client)) {
if (_client == found_client.first) {
+ service_available = true;
insert_client_routing_info(found_client.first,
routing_info_entry_e::RIE_ADD_CLIENT, _client);
} else {
@@ -1561,6 +1560,7 @@ void routing_manager_stub::handle_requests(const client_t _client, std::set<serv
}
if (_client != VSOMEIP_ROUTING_CLIENT &&
_client != host_->get_client()) {
+ service_available = true;
insert_client_routing_info(_client,
routing_info_entry_e::RIE_ADD_SERVICE_INSTANCE,
found_client.first, request.service_, request.instance_,
@@ -1573,7 +1573,9 @@ void routing_manager_stub::handle_requests(const client_t _client, std::set<serv
}
}
}
- send_client_routing_info(_client);
+ if (service_available) {
+ send_client_routing_info(_client);
+ }
}
#ifndef _WIN32
@@ -1627,8 +1629,10 @@ void routing_manager_stub::on_client_id_timer_expired(boost::system::error_code
}
}
for (auto client : erroneous_clients) {
- VSOMEIP_WARNING << "Routinger Manager 0x" << std::hex << get_client()
- << " : Release died Client 0x" << std::hex << client;
+ VSOMEIP_WARNING << "Expected client 0x" << std::hex
+ << client << " hasn't reconnected to the routing manager. "
+ << "Release identifier as client went offline while no"
+ << "routing manager was running.";
host_->handle_client_error(client);
}
}
diff --git a/implementation/runtime/include/application_impl.hpp b/implementation/runtime/include/application_impl.hpp
index 2dcc95b..f38cd2c 100644
--- a/implementation/runtime/include/application_impl.hpp
+++ b/implementation/runtime/include/application_impl.hpp
@@ -23,6 +23,7 @@
#include <vsomeip/application.hpp>
#include "../../routing/include/routing_manager_host.hpp"
+#include "../../configuration/include/internal.hpp"
namespace vsomeip {
@@ -154,6 +155,11 @@ public:
eventgroup_t _eventgroup, client_t _client, bool _subscribed);
VSOMEIP_EXPORT void on_subscription_error(service_t _service, instance_t _instance,
eventgroup_t _eventgroup, uint16_t _error);
+ VSOMEIP_EXPORT void on_subscription_status(service_t _service, instance_t _instance,
+ eventgroup_t _eventgroup, event_t _event, uint16_t _error);
+ VSOMEIP_EXPORT void register_subscription_status_handler(service_t _service,
+ instance_t _instance, eventgroup_t _eventgroup, event_t _event,
+ subscription_status_handler_t _handler);
// service_discovery_host
VSOMEIP_EXPORT routing_manager * get_routing_manager() const;
@@ -230,6 +236,12 @@ private:
eventgroup_t _eventgroup, event_t _event);
bool check_for_active_subscription(service_t _service, instance_t _instance,
event_t _event);
+
+ void deliver_subscription_state(service_t _service, instance_t _instance,
+ eventgroup_t _eventgroup, event_t _event, uint16_t _error);
+
+ bool check_subscription_state(service_t _service, instance_t _instance,
+ eventgroup_t _eventgroup, event_t _event);
//
// Attributes
//
@@ -333,6 +345,13 @@ private:
bool stopped_called_;
+ std::map<service_t, std::map<instance_t, std::map<eventgroup_t,
+ std::map<event_t, subscription_status_handler_t > > > > subscription_status_handlers_;
+ std::mutex subscription_status_handlers_mutex_;
+
+ std::mutex subscriptions_state_mutex_;
+ std::map<std::tuple<service_t, instance_t, eventgroup_t, event_t>,
+ subscription_state_e> subscription_state_;
};
diff --git a/implementation/runtime/src/application_impl.cpp b/implementation/runtime/src/application_impl.cpp
index 3ae0d61..988d48f 100644
--- a/implementation/runtime/src/application_impl.cpp
+++ b/implementation/runtime/src/application_impl.cpp
@@ -13,6 +13,8 @@
#include <vsomeip/defines.hpp>
#include <vsomeip/runtime.hpp>
+#include <vsomeip/plugins/application_plugin.hpp>
+#include <vsomeip/plugins/pre_configuration_plugin.hpp>
#include "../include/application_impl.hpp"
#include "../../configuration/include/configuration.hpp"
@@ -24,6 +26,7 @@
#include "../../utility/include/utility.hpp"
#include "../../tracing/include/trace_connector.hpp"
#include "../../tracing/include/enumeration_types.hpp"
+#include "../../plugin/include/plugin_manager.hpp"
namespace vsomeip {
@@ -75,19 +78,27 @@ bool application_impl::init() {
}
}
+ std::string configuration_path;
+ plugin_manager::get()->load_plugins();
+ auto its_pre_config_plugin = plugin_manager::get()->get_plugin(plugin_type_e::PRE_CONFIGURATION_PLUGIN);
+ if (its_pre_config_plugin) {
+ configuration_path = std::dynamic_pointer_cast<pre_configuration_plugin>(its_pre_config_plugin)->
+ get_configuration_path();
+ }
+
// load configuration from module
std::string config_module = "";
const char *its_config_module = getenv(VSOMEIP_ENV_CONFIGURATION_MODULE);
if (nullptr != its_config_module) {
// TODO: Add loading of custom configuration module
} else { // load default module
- std::shared_ptr<configuration> *its_configuration =
- static_cast<std::shared_ptr<configuration> *>(utility::load_library(
- VSOMEIP_CFG_LIBRARY,
- VSOMEIP_CFG_RUNTIME_SYMBOL_STRING));
-
- if (its_configuration && (*its_configuration)) {
- configuration_ = (*its_configuration);
+ auto its_plugin = plugin_manager::get()->get_plugin(
+ plugin_type_e::CONFIGURATION_PLUGIN);
+ if (its_plugin) {
+ configuration_ = std::dynamic_pointer_cast<configuration>(its_plugin);
+ if (configuration_path.length()) {
+ configuration_->set_configuration_path(configuration_path);
+ }
configuration_->load(name_);
VSOMEIP_INFO << "Default configuration module loaded.";
} else {
@@ -212,6 +223,24 @@ bool application_impl::init() {
signals_.async_wait(its_signal_handler);
}
#endif
+
+ auto its_plugins = configuration_->get_plugins(name_);
+ auto its_app_plugin_info = its_plugins.find(plugin_type_e::APPLICATION_PLUGIN);
+ if (its_app_plugin_info != its_plugins.end()) {
+ auto its_application_plugin = plugin_manager::get()->get_plugin(plugin_type_e::APPLICATION_PLUGIN);
+ if (!its_application_plugin) {
+ VSOMEIP_INFO << std::hex << "Client 0x" << get_client()
+ << " : loading application plugin: " << its_app_plugin_info->second;
+ its_application_plugin = plugin_manager::get()->load_plugin(
+ its_app_plugin_info->second, plugin_type_e::APPLICATION_PLUGIN,
+ VSOMEIP_APPLICATION_PLUGIN_VERSION);
+ }
+ if (its_application_plugin) {
+ std::dynamic_pointer_cast<application_plugin>(its_application_plugin)->
+ on_application_state_change(name_, application_plugin_state_e::STATE_INITIALIZED);
+ }
+ }
+
return is_initialized_;
}
@@ -227,7 +256,7 @@ void application_impl::start() {
}
if (stopped_) {
utility::release_client_id(client_);
- utility::auto_configuration_exit(client_);
+ utility::auto_configuration_exit(client_, configuration_);
{
std::lock_guard<std::mutex> its_lock_start_stop(block_stop_mutex_);
@@ -275,6 +304,16 @@ void application_impl::start() {
}
}
+ auto its_plugins = configuration_->get_plugins(name_);
+ auto its_app_plugin_info = its_plugins.find(plugin_type_e::APPLICATION_PLUGIN);
+ if (its_app_plugin_info != its_plugins.end()) {
+ auto its_application_plugin = plugin_manager::get()->get_plugin(plugin_type_e::APPLICATION_PLUGIN);
+ if (its_application_plugin) {
+ std::dynamic_pointer_cast<application_plugin>(its_application_plugin)->
+ on_application_state_change(name_, application_plugin_state_e::STATE_STARTED);
+ }
+ }
+
app_counter_mutex__.lock();
app_counter__++;
app_counter_mutex__.unlock();
@@ -290,7 +329,7 @@ void application_impl::start() {
}
utility::release_client_id(client_);
- utility::auto_configuration_exit(client_);
+ utility::auto_configuration_exit(client_, configuration_);
{
std::lock_guard<std::mutex> its_lock_start_stop(block_stop_mutex_);
@@ -338,6 +377,16 @@ void application_impl::stop() {
block = false;
}
}
+ auto its_plugins = configuration_->get_plugins(name_);
+ auto its_app_plugin_info = its_plugins.find(plugin_type_e::APPLICATION_PLUGIN);
+ if (its_app_plugin_info != its_plugins.end()) {
+ auto its_application_plugin = plugin_manager::get()->get_plugin(plugin_type_e::APPLICATION_PLUGIN);
+ if (its_application_plugin) {
+ std::dynamic_pointer_cast<application_plugin>(its_application_plugin)->
+ on_application_state_change(name_, application_plugin_state_e::STATE_STOPPED);
+ }
+ }
+
stop_cv_.notify_one();
if (block) {
@@ -400,8 +449,10 @@ void application_impl::subscribe(service_t _service, instance_t _instance,
send_back_cached_eventgroup(_service, _instance, _eventgroup);
}
- routing_->subscribe(client_, _service, _instance, _eventgroup, _major,
- _event, _subscription_type);
+ if (check_subscription_state(_service, _instance, _eventgroup, _event)) {
+ routing_->subscribe(client_, _service, _instance, _eventgroup, _major,
+ _event, _subscription_type);
+ }
}
}
@@ -793,6 +844,133 @@ void application_impl::unregister_subscription_handler(service_t _service,
unregister_message_handler(_service, _instance, ANY_METHOD - 1);
}
+void application_impl::on_subscription_status(service_t _service,
+ instance_t _instance, eventgroup_t _eventgroup, event_t _event,
+ uint16_t _error) {
+ bool entry_found(false);
+ {
+ auto its_tuple = std::make_tuple(_service, _instance, _eventgroup, _event);
+ std::lock_guard<std::mutex> its_lock(subscriptions_state_mutex_);
+ auto its_subscription_state = subscription_state_.find(its_tuple);
+ if (its_subscription_state == subscription_state_.end()) {
+ its_tuple = std::make_tuple(_service, _instance, _eventgroup, ANY_EVENT);
+ auto its_any_subscription_state = subscription_state_.find(its_tuple);
+ if (its_any_subscription_state == subscription_state_.end()) {
+ VSOMEIP_TRACE << std::hex << get_client( )
+ << " application_impl::on_subscription_status: "
+ << "Received a subscription status without subscribe for "
+ << std::hex << _service << "/" << _instance << "/"
+ << _eventgroup << "/" << _event << "/error=" << _error;
+ } else {
+ entry_found = true;
+ }
+ } else {
+ entry_found = true;
+ }
+ if (entry_found) {
+ if (_error) {
+ subscription_state_[its_tuple] =
+ subscription_state_e::SUBSCRIPTION_NOT_ACKNOWLEDGED;
+ } else {
+ subscription_state_[its_tuple] =
+ subscription_state_e::SUBSCRIPTION_ACKNOWLEDGED;
+ }
+ }
+ }
+
+ if (entry_found) {
+ deliver_subscription_state(_service, _instance, _eventgroup, _event, _error);
+ }
+}
+
+void application_impl::deliver_subscription_state(service_t _service, instance_t _instance,
+ eventgroup_t _eventgroup, event_t _event, uint16_t _error) {
+ std::vector<subscription_status_handler_t> handlers;
+ {
+ std::lock_guard<std::mutex> its_lock(subscription_status_handlers_mutex_);
+ auto found_service = subscription_status_handlers_.find(_service);
+ if (found_service != subscription_status_handlers_.end()) {
+ auto found_instance = found_service->second.find(_instance);
+ if (found_instance != found_service->second.end()) {
+ auto found_eventgroup = found_instance->second.find(_eventgroup);
+ if (found_eventgroup != found_instance->second.end()) {
+ auto found_event = found_eventgroup->second.find(_event);
+ if (found_event != found_eventgroup->second.end()) {
+ handlers.push_back(found_event->second);
+ } else {
+ auto its_any_event = found_eventgroup->second.find(ANY_EVENT);
+ if (its_any_event != found_eventgroup->second.end()) {
+ handlers.push_back(its_any_event->second);
+ }
+ }
+ }
+ }
+ found_instance = found_service->second.find(ANY_INSTANCE);
+ if (found_instance != found_service->second.end()) {
+ auto found_eventgroup = found_instance->second.find(_eventgroup);
+ if (found_eventgroup != found_instance->second.end()) {
+ auto found_event = found_eventgroup->second.find(_event);
+ if (found_event != found_eventgroup->second.end()) {
+ handlers.push_back(found_event->second);
+ } else {
+ auto its_any_event = found_eventgroup->second.find(ANY_EVENT);
+ if (its_any_event != found_eventgroup->second.end()) {
+ handlers.push_back(its_any_event->second);
+ }
+ }
+ }
+ }
+ }
+ found_service = subscription_status_handlers_.find(ANY_SERVICE);
+ if (found_service != subscription_status_handlers_.end()) {
+ auto found_instance = found_service->second.find(_instance);
+ if (found_instance != found_service->second.end()) {
+ auto found_eventgroup = found_instance->second.find(_eventgroup);
+ if (found_eventgroup != found_instance->second.end()) {
+ auto found_event = found_eventgroup->second.find(_event);
+ if (found_event != found_eventgroup->second.end()) {
+ handlers.push_back(found_event->second);
+ } else {
+ auto its_any_event = found_eventgroup->second.find(ANY_EVENT);
+ if (its_any_event != found_eventgroup->second.end()) {
+ handlers.push_back(its_any_event->second);
+ }
+ }
+ }
+ }
+ found_instance = found_service->second.find(ANY_INSTANCE);
+ if (found_instance != found_service->second.end()) {
+ auto found_eventgroup = found_instance->second.find(_eventgroup);
+ if (found_eventgroup != found_instance->second.end()) {
+ auto found_event = found_eventgroup->second.find(_event);
+ if (found_event != found_eventgroup->second.end()) {
+ handlers.push_back(found_event->second);
+ } else {
+ auto its_any_event = found_eventgroup->second.find(ANY_EVENT);
+ if (its_any_event != found_eventgroup->second.end()) {
+ handlers.push_back(its_any_event->second);
+ }
+ }
+ }
+ }
+ }
+ }
+ for (auto &handler : handlers) {
+ std::unique_lock<std::mutex> handlers_lock(handlers_mutex_);
+ std::shared_ptr<sync_handler> its_sync_handler
+ = std::make_shared<sync_handler>([handler, _service,
+ _instance, _eventgroup,
+ _event, _error]() {
+ handler(_service, _instance,
+ _eventgroup, _event, _error);
+ });
+ handlers_.push_back(its_sync_handler);
+ }
+ if (handlers.size()) {
+ dispatcher_condition_.notify_all();
+ }
+}
+
void application_impl::on_subscription_error(service_t _service,
instance_t _instance, eventgroup_t _eventgroup, uint16_t _error) {
error_handler_t handler = nullptr;
@@ -824,6 +1002,35 @@ void application_impl::on_subscription_error(service_t _service,
}
}
+void application_impl::register_subscription_status_handler(service_t _service,
+ instance_t _instance, eventgroup_t _eventgroup, event_t _event,
+ subscription_status_handler_t _handler) {
+ std::lock_guard<std::mutex> its_lock(subscription_status_handlers_mutex_);
+ if (_handler) {
+ subscription_status_handlers_[_service][_instance][_eventgroup][_event] = _handler;
+ } else {
+ auto its_service = subscription_status_handlers_.find(_service);
+ if (its_service != subscription_status_handlers_.end()) {
+ auto its_instance = its_service->second.find(_instance);
+ if (its_instance != its_service->second.end()) {
+ auto its_eventgroup = its_instance->second.find(_eventgroup);
+ if (its_eventgroup != its_instance->second.end()) {
+ its_eventgroup->second.erase(_event);
+ if (its_eventgroup->second.size() == 0) {
+ its_instance->second.erase(_eventgroup);
+ if (its_instance->second.size() == 0) {
+ its_service->second.erase(_instance);
+ if (its_service->second.size() == 0) {
+ subscription_status_handlers_.erase(_service);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
void application_impl::register_subscription_error_handler(service_t _service,
instance_t _instance, eventgroup_t _eventgroup,
error_handler_t _handler) {
@@ -1062,18 +1269,30 @@ void application_impl::on_availability(service_t _service, instance_t _instance,
}
}
if (!_is_available) {
- std::lock_guard<std::mutex> its_lock(subscriptions_mutex_);
- auto found_service = subscriptions_.find(_service);
- if (found_service != subscriptions_.end()) {
- auto found_instance = found_service->second.find(_instance);
- if (found_instance != found_service->second.end()) {
- for (auto &event : found_instance->second) {
- for (auto &eventgroup : event.second) {
- eventgroup.second = false;
+ {
+ std::lock_guard<std::mutex> its_lock(subscriptions_mutex_);
+ auto found_service = subscriptions_.find(_service);
+ if (found_service != subscriptions_.end()) {
+ auto found_instance = found_service->second.find(_instance);
+ if (found_instance != found_service->second.end()) {
+ for (auto &event : found_instance->second) {
+ for (auto &eventgroup : event.second) {
+ eventgroup.second = false;
+ }
}
}
}
}
+ {
+ std::lock_guard<std::mutex> its_lock(subscriptions_state_mutex_);
+ for (auto &its_subscription_state : subscription_state_) {
+ if (std::get<0>(its_subscription_state.first) == _service &&
+ std::get<1>(its_subscription_state.first) == _instance) {
+ its_subscription_state.second =
+ subscription_state_e::SUBSCRIPTION_NOT_ACKNOWLEDGED;
+ }
+ }
+ }
}
if (its_handlers.size()) {
@@ -1494,6 +1713,13 @@ void application_impl::remove_subscription(service_t _service,
instance_t _instance,
eventgroup_t _eventgroup,
event_t _event) {
+
+ {
+ auto its_tuple = std::make_tuple(_service, _instance, _eventgroup, _event);
+ std::lock_guard<std::mutex> its_lock(subscriptions_state_mutex_);
+ subscription_state_.erase(its_tuple);
+ }
+
std::lock_guard<std::mutex> its_lock(subscriptions_mutex_);
auto found_service = subscriptions_.find(_service);
@@ -1568,4 +1794,36 @@ bool application_impl::check_for_active_subscription(service_t _service,
return false;
}
+bool application_impl::check_subscription_state(service_t _service, instance_t _instance,
+ eventgroup_t _eventgroup, event_t _event) {
+ bool is_acknowledged(false);
+ bool should_subscribe(true);
+ {
+ auto its_tuple = std::make_tuple(_service, _instance, _eventgroup, _event);
+ std::lock_guard<std::mutex> its_lock(subscriptions_state_mutex_);
+ auto its_subscription_state = subscription_state_.find(its_tuple);
+ if (its_subscription_state != subscription_state_.end()) {
+ if (its_subscription_state->second !=
+ subscription_state_e::SUBSCRIPTION_NOT_ACKNOWLEDGED) {
+ // only return true if subscription is NACK
+ // as only then we need to subscribe!
+ should_subscribe = false;
+ if (its_subscription_state->second ==
+ subscription_state_e::SUBSCRIPTION_ACKNOWLEDGED) {
+ is_acknowledged = true;
+ }
+ }
+ } else {
+ subscription_state_[its_tuple] = subscription_state_e::IS_SUBSCRIBING;
+ }
+ }
+
+ if (!should_subscribe && is_acknowledged) {
+ // Deliver subscription state only if ACK has already received
+ deliver_subscription_state(_service, _instance, _eventgroup, _event, 0 /* OK */);
+ }
+
+ return should_subscribe;
+}
+
} // namespace vsomeip
diff --git a/implementation/service_discovery/include/runtime.hpp b/implementation/service_discovery/include/runtime.hpp
index 468d5ba..f99fec8 100644
--- a/implementation/service_discovery/include/runtime.hpp
+++ b/implementation/service_discovery/include/runtime.hpp
@@ -18,7 +18,6 @@ class service_discovery_host;
class runtime {
public:
- static std::shared_ptr<runtime> get();
virtual ~runtime() {
}
diff --git a/implementation/service_discovery/include/runtime_impl.hpp b/implementation/service_discovery/include/runtime_impl.hpp
index 4a8557f..dcdb7d7 100644
--- a/implementation/service_discovery/include/runtime_impl.hpp
+++ b/implementation/service_discovery/include/runtime_impl.hpp
@@ -6,14 +6,17 @@
#ifndef VSOMEIP_SD_RUNTIME_IMPL_HPP
#define VSOMEIP_SD_RUNTIME_IMPL_HPP
+#include <vsomeip/plugin.hpp>
#include "runtime.hpp"
namespace vsomeip {
namespace sd {
-class runtime_impl: public runtime {
+class runtime_impl
+ : public runtime,
+ public plugin_impl<runtime_impl> {
public:
- static std::shared_ptr<runtime> get();
+ runtime_impl();
virtual ~runtime_impl();
std::shared_ptr<service_discovery> create_service_discovery(
diff --git a/implementation/service_discovery/include/service_discovery.hpp b/implementation/service_discovery/include/service_discovery.hpp
index 19f3c93..703bf22 100644
--- a/implementation/service_discovery/include/service_discovery.hpp
+++ b/implementation/service_discovery/include/service_discovery.hpp
@@ -63,6 +63,8 @@ public:
std::shared_ptr<serviceinfo> _info) = 0;
virtual void stop_offer_service(service_t _service, instance_t _instance,
std::shared_ptr<serviceinfo> _info) = 0;
+
+ virtual void set_diagnosis_mode(const bool _activate) = 0;
};
} // namespace sd
diff --git a/implementation/service_discovery/include/service_discovery_host.hpp b/implementation/service_discovery/include/service_discovery_host.hpp
index 0e1de9e..e1e0ccd 100644
--- a/implementation/service_discovery/include/service_discovery_host.hpp
+++ b/implementation/service_discovery/include/service_discovery_host.hpp
@@ -81,9 +81,6 @@ public:
virtual void expire_subscriptions(const boost::asio::ip::address &_address) = 0;
virtual void expire_services(const boost::asio::ip::address &_address) = 0;
- virtual void on_reboot(const boost::asio::ip::address &_address) = 0;
-
-
virtual bool on_subscribe_accepted(service_t _service, instance_t _instance,
eventgroup_t _eventgroup, std::shared_ptr<endpoint_definition> _target,
const std::chrono::steady_clock::time_point &_expiration) = 0;
diff --git a/implementation/service_discovery/include/service_discovery_impl.hpp b/implementation/service_discovery/include/service_discovery_impl.hpp
index 910fc61..b7be7ff 100644
--- a/implementation/service_discovery/include/service_discovery_impl.hpp
+++ b/implementation/service_discovery/include/service_discovery_impl.hpp
@@ -91,6 +91,8 @@ public:
void stop_offer_service(service_t _service, instance_t _instance,
std::shared_ptr<serviceinfo> _info);
+ void set_diagnosis_mode(const bool _activate);
+
private:
std::pair<session_t, bool> get_session(const boost::asio::ip::address &_address);
void increment_session(const boost::asio::ip::address &_address);
@@ -353,6 +355,8 @@ private:
std::string sd_multicast_;
boost::asio::ip::address current_remote_address_;
+
+ std::atomic<bool> is_diagnosis_;
};
} // namespace sd
diff --git a/implementation/service_discovery/src/ipv4_option_impl.cpp b/implementation/service_discovery/src/ipv4_option_impl.cpp
index b12d60e..00bf7b5 100644
--- a/implementation/service_discovery/src/ipv4_option_impl.cpp
+++ b/implementation/service_discovery/src/ipv4_option_impl.cpp
@@ -49,7 +49,7 @@ bool ipv4_option_impl::serialize(vsomeip::serializer *_to) const {
bool ipv4_option_impl::deserialize(vsomeip::deserializer *_from) {
bool is_successful = option_impl::deserialize(_from)
&& length_ == VSOMEIP_SD_IPV4_OPTION_LENGTH;
- uint8_t its_reserved;
+ uint8_t its_reserved(static_cast<std::uint8_t>(layer_four_protocol_e::UNKNOWN));
_from->deserialize(address_.data(), 4);
_from->deserialize(its_reserved);
_from->deserialize(its_reserved);
diff --git a/implementation/service_discovery/src/ipv6_option_impl.cpp b/implementation/service_discovery/src/ipv6_option_impl.cpp
index ac9ebed..94c8fe4 100755
--- a/implementation/service_discovery/src/ipv6_option_impl.cpp
+++ b/implementation/service_discovery/src/ipv6_option_impl.cpp
@@ -49,7 +49,7 @@ bool ipv6_option_impl::serialize(vsomeip::serializer *_to) const {
bool ipv6_option_impl::deserialize(vsomeip::deserializer *_from) {
bool is_successful = option_impl::deserialize(_from)
&& length_ == VSOMEIP_SD_IPV6_OPTION_LENGTH;;
- uint8_t its_reserved;
+ uint8_t its_reserved(static_cast<std::uint8_t>(layer_four_protocol_e::UNKNOWN));
_from->deserialize(address_.data(), 16);
_from->deserialize(its_reserved);
_from->deserialize(its_reserved);
diff --git a/implementation/service_discovery/src/runtime.cpp b/implementation/service_discovery/src/runtime.cpp
deleted file mode 100644
index 54276fd..0000000
--- a/implementation/service_discovery/src/runtime.cpp
+++ /dev/null
@@ -1,40 +0,0 @@
-// 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/runtime_impl.hpp"
-#include "../../configuration/include/internal.hpp"
-
-#ifdef _WIN32
-extern "C"
-{
- __declspec(dllexport) std::shared_ptr<vsomeip::sd::runtime> VSOMEIP_SD_RUNTIME_SYMBOL;
-}
-#else
-std::shared_ptr<vsomeip::sd::runtime> VSOMEIP_SD_RUNTIME_SYMBOL(vsomeip::sd::runtime::get());
-#endif
-
-#ifdef _WIN32
-#define CCALL __cdecl
-#pragma section(".CRT$XCU",read)
-#define INITIALIZER(f) \
- static void __cdecl f(void); \
- __declspec(allocate(".CRT$XCU")) void(__cdecl*f##_)(void) = f; \
- static void __cdecl f(void)
-
-INITIALIZER(init_vsomeip_sd) {
- VSOMEIP_SD_RUNTIME_SYMBOL = vsomeip::sd::runtime::get();
-}
-#endif
-
-namespace vsomeip {
-namespace sd {
-
-std::shared_ptr<runtime> runtime::get() {
- return runtime_impl::get();
-}
-
-} // namespace sd
-} // namespace vsomeip
-
diff --git a/implementation/service_discovery/src/runtime_impl.cpp b/implementation/service_discovery/src/runtime_impl.cpp
index b2ed34d..90743b8 100644
--- a/implementation/service_discovery/src/runtime_impl.cpp
+++ b/implementation/service_discovery/src/runtime_impl.cpp
@@ -12,13 +12,13 @@
#include "../include/runtime_impl.hpp"
#include "../include/service_discovery_impl.hpp"
+VSOMEIP_PLUGIN(vsomeip::sd::runtime_impl)
+
namespace vsomeip {
namespace sd {
-std::shared_ptr<runtime> runtime_impl::get() {
- static std::shared_ptr<runtime> the_runtime =
- std::make_shared<runtime_impl>();
- return the_runtime;
+runtime_impl::runtime_impl()
+ : plugin_impl("vsomeip SD plug-in", 1, plugin_type_e::SD_RUNTIME_PLUGIN) {
}
runtime_impl::~runtime_impl() {
diff --git a/implementation/service_discovery/src/service_discovery_impl.cpp b/implementation/service_discovery/src/service_discovery_impl.cpp
index 79e60bd..e8937ed 100644
--- a/implementation/service_discovery/src/service_discovery_impl.cpp
+++ b/implementation/service_discovery/src/service_discovery_impl.cpp
@@ -33,6 +33,7 @@
#include "../../message/include/serializer.hpp"
#include "../../routing/include/eventgroupinfo.hpp"
#include "../../routing/include/serviceinfo.hpp"
+#include "../../plugin/include/plugin_manager.hpp"
namespace vsomeip {
namespace sd {
@@ -62,7 +63,8 @@ service_discovery_impl::service_discovery_impl(service_discovery_host *_host)
find_debounce_time_(VSOMEIP_SD_DEFAULT_FIND_DEBOUNCE_TIME),
find_debounce_timer_(_host->get_io()),
main_phase_timer_(_host->get_io()),
- is_suspended_(true) {
+ is_suspended_(false),
+ is_diagnosis_(false) {
std::chrono::seconds smallest_ttl(DEFAULT_TTL);
smallest_ttl_ = std::chrono::duration_cast<std::chrono::milliseconds>(smallest_ttl);
@@ -82,7 +84,7 @@ boost::asio::io_service & service_discovery_impl::get_io() {
}
void service_discovery_impl::init() {
- runtime_ = runtime::get();
+ runtime_ = std::dynamic_pointer_cast<sd::runtime>(plugin_manager::get()->get_plugin(plugin_type_e::SD_RUNTIME_PLUGIN));
std::shared_ptr < configuration > its_configuration =
host_->get_configuration();
@@ -151,33 +153,7 @@ void service_discovery_impl::start() {
}
void service_discovery_impl::stop() {
- boost::system::error_code ec;
is_suspended_ = true;
- {
- std::lock_guard<std::mutex> its_lock(main_phase_timer_mutex_);
- main_phase_timer_.cancel(ec);
- }
- {
- std::lock_guard<std::mutex> its_lock(offer_debounce_timer_mutex_);
- offer_debounce_timer_.cancel(ec);
- }
- {
- std::lock_guard<std::mutex> its_lock(find_debounce_timer_mutex_);
- find_debounce_timer_.cancel(ec);
- }
- {
- std::lock_guard<std::mutex> its_lock(repetition_phase_timers_mutex_);
- for(const auto &t : repetition_phase_timers_) {
- t.first->cancel(ec);
- }
- }
- {
- std::lock_guard<std::mutex> its_lock(find_repetition_phase_timers_mutex_);
- for(const auto &t : find_repetition_phase_timers_) {
- t.first->cancel(ec);
- }
- }
-
}
void service_discovery_impl::request_service(service_t _service,
@@ -849,20 +825,23 @@ void service_discovery_impl::insert_offer_entries(
uint32_t its_size(_size);
for (const auto its_service : _services) {
for (const auto its_instance : its_service.second) {
- // Only insert services with configured endpoint(s)
- if ((_ignore_phase || its_instance.second->is_in_mainphase())
- && (its_instance.second->get_endpoint(false)
- || its_instance.second->get_endpoint(true))) {
- if (i >= _start) {
- if (!insert_offer_service(_message, its_service.first,
- its_instance.first, its_instance.second, its_size)) {
- _start = i;
- _done = false;
- return;
+ if ((!is_suspended_)
+ && ((!is_diagnosis_) || (is_diagnosis_ && !host_->get_configuration()->is_someip(its_service.first, its_instance.first)))) {
+ // Only insert services with configured endpoint(s)
+ if ((_ignore_phase || its_instance.second->is_in_mainphase())
+ && (its_instance.second->get_endpoint(false)
+ || its_instance.second->get_endpoint(true))) {
+ if (i >= _start) {
+ if (!insert_offer_service(_message, its_service.first,
+ its_instance.first, its_instance.second, its_size)) {
+ _start = i;
+ _done = false;
+ return;
+ }
}
}
+ i++;
}
- i++;
}
}
_start = i;
@@ -1073,7 +1052,6 @@ void service_discovery_impl::on_message(const byte_t *_data, length_t _length,
VSOMEIP_INFO << "Reboot detected: IP=" << _sender.to_string();
host_->expire_subscriptions(_sender);
host_->expire_services(_sender);
- host_->on_reboot(_sender);
}
std::chrono::milliseconds expired = stop_ttl_timer();
@@ -1226,9 +1204,11 @@ void service_discovery_impl::process_serviceentry(
its_request->set_sent_counter(std::uint8_t(repetitions_max_ + 1));
}
unsubscribe_all(its_service, its_instance);
- host_->del_routing_info(its_service, its_instance,
- (its_reliable_port != ILLEGAL_PORT),
- (its_unreliable_port != ILLEGAL_PORT));
+ if (!is_diagnosis_ && !is_suspended_) {
+ host_->del_routing_info(its_service, its_instance,
+ (its_reliable_port != ILLEGAL_PORT),
+ (its_unreliable_port != ILLEGAL_PORT));
+ }
}
}
@@ -1567,7 +1547,8 @@ bool service_discovery_impl::insert_offer_service(
if (its_reliable) {
insert_option(_message, its_entry, unicast_,
its_reliable->get_local_port(), true);
- if (0 == _info->get_ttl()) {
+ if ((0 == _info->get_ttl() && !is_diagnosis_)
+ && (0 == _info->get_ttl() && !is_suspended_)) {
host_->del_routing_info(_service,
_instance, true, false);
}
@@ -1576,7 +1557,8 @@ bool service_discovery_impl::insert_offer_service(
if (its_unreliable) {
insert_option(_message, its_entry, unicast_,
its_unreliable->get_local_port(), false);
- if (0 == _info->get_ttl()) {
+ if ((0 == _info->get_ttl() && !is_diagnosis_)
+ && (0 == _info->get_ttl() && !is_suspended_)) {
host_->del_routing_info(_service,
_instance, false, true);
}
@@ -1833,8 +1815,6 @@ void service_discovery_impl::process_eventgroupentry(
}
break;
case option_type_e::CONFIGURATION: {
- if (entry_type_e::SUBSCRIBE_EVENTGROUP == its_type) {
- }
break;
}
case option_type_e::UNKNOWN:
@@ -1944,7 +1924,7 @@ void service_discovery_impl::handle_eventgroup_subscription(service_t _service,
} else if (_is_second_reliable) { // tcp unicast
its_second_target = its_second_subscriber;
// check if TCP connection is established by client
- if( !is_tcp_connected(_service, _instance, its_second_target) && _ttl > 0) {
+ if(_ttl > 0 && !is_tcp_connected(_service, _instance, its_second_target)) {
insert_subscription_nack(its_message, _service, _instance,
_eventgroup, _counter, _major, _reserved);
VSOMEIP_ERROR << "TCP connection to target2 : [" << its_second_target->get_address().to_string()
@@ -2465,10 +2445,28 @@ void service_discovery_impl::on_offer_debounce_timer_expired(
services_t repetition_phase_offers;
bool new_offers(false);
{
+ std::vector<services_t::iterator> non_someip_services;
std::lock_guard<std::mutex> its_lock(collected_offers_mutex_);
if (collected_offers_.size()) {
- repetition_phase_offers = collected_offers_;
- collected_offers_.clear();
+ if (is_diagnosis_) {
+ for (services_t::iterator its_service = collected_offers_.begin();
+ its_service != collected_offers_.end(); its_service++) {
+ for (auto its_instance : its_service->second) {
+ if (!host_->get_configuration()->is_someip(
+ its_service->first, its_instance.first)) {
+ non_someip_services.push_back(its_service);
+ }
+ }
+ }
+ for (auto its_service : non_someip_services) {
+ repetition_phase_offers.insert(*its_service);
+ collected_offers_.erase(its_service);
+ }
+ } else {
+ repetition_phase_offers = collected_offers_;
+ collected_offers_.clear();
+ }
+
new_offers = true;
}
}
@@ -2877,5 +2875,9 @@ bool service_discovery_impl::check_source_address(
return is_valid;
}
+void service_discovery_impl::set_diagnosis_mode(const bool _activate) {
+ is_diagnosis_ = _activate;
+}
+
} // namespace sd
} // namespace vsomeip
diff --git a/implementation/tracing/include/trace_header.hpp b/implementation/tracing/include/trace_header.hpp
index 95e0d83..11ccbdd 100644
--- a/implementation/tracing/include/trace_header.hpp
+++ b/implementation/tracing/include/trace_header.hpp
@@ -12,7 +12,7 @@
#include <boost/asio/ip/address_v4.hpp>
-#define VSOMEIP_TRACE_HEADER_SIZE 8
+#define VSOMEIP_TRACE_HEADER_SIZE 10
namespace vsomeip {
@@ -28,10 +28,13 @@ enum class protocol_e : uint8_t {
};
struct trace_header {
- bool prepare(const std::shared_ptr<endpoint> &_endpoint, bool _is_sending);
- bool prepare(const endpoint* _endpoint, bool _is_sending);
+ bool prepare(const std::shared_ptr<endpoint> &_endpoint, bool _is_sending,
+ instance_t _instance);
+ bool prepare(const endpoint* _endpoint, bool _is_sending,
+ instance_t _instance);
void prepare(const boost::asio::ip::address_v4 &_address,
- std::uint16_t _port, protocol_e _protocol, bool _is_sending);
+ std::uint16_t _port, protocol_e _protocol, bool _is_sending,
+ instance_t _instance);
byte_t data_[VSOMEIP_TRACE_HEADER_SIZE];
};
diff --git a/implementation/tracing/src/trace_connector.cpp b/implementation/tracing/src/trace_connector.cpp
index 08bbfd1..8734748 100644
--- a/implementation/tracing/src/trace_connector.cpp
+++ b/implementation/tracing/src/trace_connector.cpp
@@ -244,8 +244,8 @@ void trace_connector::trace(const byte_t *_header, uint16_t _header_size,
DltContext *dlt_context = it->second;
DLT_TRACE_NETWORK_SEGMENTED(*dlt_context,
DLT_NW_TRACE_IPC,
- _header_size, (void * )_header,
- _data_size, (void * )_data);
+ _header_size, static_cast<void *>(const_cast<byte_t *>(_header)),
+ _data_size, static_cast<void *>(const_cast<byte_t *>(_data)));
}
}
}
diff --git a/implementation/tracing/src/trace_header.cpp b/implementation/tracing/src/trace_header.cpp
index c92ce06..d78e600 100644
--- a/implementation/tracing/src/trace_header.cpp
+++ b/implementation/tracing/src/trace_header.cpp
@@ -13,11 +13,13 @@
namespace vsomeip {
namespace tc {
-bool trace_header::prepare(const std::shared_ptr<endpoint> &_endpoint, bool _is_sending) {
- return prepare(_endpoint.get(), _is_sending);
+bool trace_header::prepare(const std::shared_ptr<endpoint> &_endpoint,
+ bool _is_sending, instance_t _instance) {
+ return prepare(_endpoint.get(), _is_sending, _instance);
}
-bool trace_header::prepare(const endpoint *_endpoint, bool _is_sending) {
+bool trace_header::prepare(const endpoint *_endpoint, bool _is_sending,
+ instance_t _instance) {
if (_endpoint) {
const client_endpoint* its_client_endpoint =
dynamic_cast<const client_endpoint*>(_endpoint);
@@ -40,7 +42,8 @@ bool trace_header::prepare(const endpoint *_endpoint, bool _is_sending) {
its_protocol = protocol_e::udp;
}
}
- prepare(its_address.to_v4(), its_port, its_protocol, _is_sending);
+ prepare(its_address.to_v4(), its_port, its_protocol, _is_sending,
+ _instance);
return true;
}
}
@@ -50,7 +53,7 @@ bool trace_header::prepare(const endpoint *_endpoint, bool _is_sending) {
void trace_header::prepare(const boost::asio::ip::address_v4 &_address,
std::uint16_t _port, protocol_e _protocol,
- bool _is_sending) {
+ bool _is_sending, instance_t _instance) {
unsigned long its_address_as_long = _address.to_ulong();
data_[0] = VSOMEIP_LONG_BYTE0(its_address_as_long);
data_[1] = VSOMEIP_LONG_BYTE1(its_address_as_long);
@@ -60,6 +63,8 @@ void trace_header::prepare(const boost::asio::ip::address_v4 &_address,
data_[5] = VSOMEIP_WORD_BYTE1(_port);
data_[6] = static_cast<byte_t>(_protocol);
data_[7] = static_cast<byte_t>(_is_sending);
+ data_[8] = VSOMEIP_WORD_BYTE0(_instance);
+ data_[9] = VSOMEIP_WORD_BYTE1(_instance);
}
} // namespace tc
diff --git a/implementation/utility/include/utility.hpp b/implementation/utility/include/utility.hpp
index e48be1a..9245f90 100644
--- a/implementation/utility/include/utility.hpp
+++ b/implementation/utility/include/utility.hpp
@@ -20,9 +20,6 @@ class configuration;
class utility {
public:
- static void * load_library(const std::string &_path,
- const std::string &_symbol);
-
static inline bool is_request(std::shared_ptr<message> _message) {
return (_message ? is_request(_message->get_message_type()) : false);
}
@@ -76,16 +73,21 @@ public:
static bool VSOMEIP_IMPORT_EXPORT is_file(const std::string &_path);
static bool VSOMEIP_IMPORT_EXPORT is_folder(const std::string &_path);
+ static const std::string get_base_path(const std::shared_ptr<configuration> &_config);
+ static const std::string get_shm_name(const std::shared_ptr<configuration> &_config);
+
static CriticalSection its_local_configuration_mutex__;
static struct configuration_data_t *the_configuration_data__;
static bool auto_configuration_init(const std::shared_ptr<configuration> &_config);
- static void auto_configuration_exit(client_t _client);
+ static void auto_configuration_exit(client_t _client,
+ const std::shared_ptr<configuration> &_config);
static bool is_routing_manager_host(client_t _client);
static void set_routing_manager_host(client_t _client);
- static bool is_used_client_id(client_t _client);
+ static bool is_used_client_id(client_t _client,
+ const std::shared_ptr<configuration> &_config);
static client_t request_client_id(const std::shared_ptr<configuration> &_config,
const std::string &_name, client_t _client);
static void release_client_id(client_t _client);
diff --git a/implementation/utility/src/utility.cpp b/implementation/utility/src/utility.cpp
index f4f4449..81d8aba 100644
--- a/implementation/utility/src/utility.cpp
+++ b/implementation/utility/src/utility.cpp
@@ -15,10 +15,6 @@
#include <sys/stat.h>
-#ifndef _WIN32
- #include <fcntl.h>
-#endif
-
#include <vsomeip/constants.hpp>
#include <vsomeip/defines.hpp>
@@ -54,46 +50,6 @@ uint32_t utility::get_payload_size(const byte_t *_data, uint32_t _size) {
return (its_size);
}
-void * utility::load_library(const std::string &_path,
- const std::string &_symbol) {
- void * its_symbol = 0;
-
-#ifdef _WIN32
- std::string path = _path.substr(0, _path.length() - 5).substr(3) + ".dll";
-
- HINSTANCE hDLL = LoadLibrary(path.c_str());
- if (hDLL != NULL) {
- //loadedLibraries_.insert(itsLibrary);
- std::cout << "Loading interface library \"" << path << "\" succeeded." << std::endl;
-
- typedef UINT(CALLBACK* LPFNDLLFUNC1)(DWORD, UINT);
-
- LPFNDLLFUNC1 lpfnDllFunc1 = (LPFNDLLFUNC1)GetProcAddress(hDLL, _symbol.c_str());
- if (!lpfnDllFunc1)
- {
- FreeLibrary(hDLL);
- std::cerr << "Loading symbol \"" << _symbol << "\" failed (" << GetLastError() << ")" << std::endl;
- }
- else
- {
- its_symbol = lpfnDllFunc1;
- }
-
- }
- else {
- std::cerr << "Loading interface library \"" << path << "\" failed (" << GetLastError() << ")" << std::endl;
- }
-#else
- void *handle = dlopen(_path.c_str(), RTLD_LAZY | RTLD_GLOBAL);
- if (0 != handle) {
- its_symbol = dlsym(handle, _symbol.c_str());
- } else {
- VSOMEIP_ERROR << "Loading failed: (" << dlerror() << ")";
- }
-#endif
- return (its_symbol);
-}
-
bool utility::exists(const std::string &_path) {
struct stat its_stat;
return (stat(_path.c_str(), &its_stat) == 0);
@@ -117,6 +73,16 @@ bool utility::is_folder(const std::string &_path) {
return false;
}
+const std::string utility::get_base_path(
+ const std::shared_ptr<configuration> &_config) {
+ return std::string(VSOMEIP_BASE_PATH + _config->get_network() + "-");
+}
+
+const std::string utility::get_shm_name(
+ const std::shared_ptr<configuration> &_config) {
+ return std::string("/" + _config->get_network());
+}
+
// pointer to shared memory
configuration_data_t *utility::the_configuration_data__(nullptr);
// critical section to protect shared memory pointers, handles and ref count in this process
@@ -161,7 +127,7 @@ bool utility::auto_configuration_init(const std::shared_ptr<configuration> &_con
PAGE_READWRITE, // read/write access
0, // maximum object size (high-order DWORD)
sizeof(configuration_data_t), // maximum object size (low-order DWORD)
- VSOMEIP_SHM_NAME); // name of mapping object
+ utility::get_shm_name(_config).c_str());// name of mapping object
if (its_descriptor && GetLastError() == ERROR_ALREADY_EXISTS) {
@@ -200,7 +166,7 @@ bool utility::auto_configuration_init(const std::shared_ptr<configuration> &_con
PAGE_READWRITE, // read/write access
0, // maximum object size (high-order DWORD)
sizeof(configuration_data_t), // maximum object size (low-order DWORD)
- VSOMEIP_SHM_NAME); // name of mapping object
+ utility::get_shm_name(_config).c_str());// name of mapping object
if (its_descriptor) {
void *its_segment = (LPTSTR)MapViewOfFile(its_descriptor, // handle to map object
@@ -254,7 +220,7 @@ bool utility::auto_configuration_init(const std::shared_ptr<configuration> &_con
}
#else
const mode_t previous_mask(::umask(static_cast<mode_t>(_config->get_umask())));
- int its_descriptor = shm_open(VSOMEIP_SHM_NAME, O_RDWR | O_CREAT | O_EXCL,
+ int its_descriptor = shm_open(utility::get_shm_name(_config).c_str(), O_RDWR | O_CREAT | O_EXCL,
static_cast<mode_t>(_config->get_permissions_shm()));
::umask(previous_mask);
if (its_descriptor > -1) {
@@ -326,7 +292,7 @@ bool utility::auto_configuration_init(const std::shared_ptr<configuration> &_con
}
} else if (errno == EEXIST) {
const mode_t previous_mask(::umask(static_cast<mode_t>(_config->get_umask())));
- its_descriptor = shm_open(VSOMEIP_SHM_NAME, O_RDWR,
+ its_descriptor = shm_open(utility::get_shm_name(_config).c_str(), O_RDWR,
static_cast<mode_t>(_config->get_permissions_shm()));
::umask(previous_mask);
if (-1 == its_descriptor) {
@@ -383,7 +349,8 @@ bool utility::auto_configuration_init(const std::shared_ptr<configuration> &_con
return (the_configuration_data__ != nullptr);
}
-void utility::auto_configuration_exit(client_t _client) {
+void utility::auto_configuration_exit(client_t _client,
+ const std::shared_ptr<configuration> &_config) {
std::unique_lock<CriticalSection> its_lock(its_local_configuration_mutex__);
if (the_configuration_data__) {
#ifdef _WIN32
@@ -426,7 +393,7 @@ void utility::auto_configuration_exit(client_t _client) {
"munmap succeeded.";
the_configuration_data__ = nullptr;
if (unlink_shm) {
- shm_unlink(VSOMEIP_SHM_NAME);
+ shm_unlink(utility::get_shm_name(_config).c_str());
}
}
@@ -435,7 +402,8 @@ void utility::auto_configuration_exit(client_t _client) {
}
}
-bool utility::is_used_client_id(client_t _client) {
+bool utility::is_used_client_id(client_t _client,
+ const std::shared_ptr<configuration> &_config) {
for (int i = 0;
i < the_configuration_data__->max_used_client_ids_index_;
i++) {
@@ -445,7 +413,7 @@ bool utility::is_used_client_id(client_t _client) {
}
#ifndef _WIN32
std::stringstream its_client;
- its_client << VSOMEIP_BASE_PATH << std::hex << _client;
+ its_client << utility::get_base_path(_config) << std::hex << _client;
if (exists(its_client.str())) {
if (-1 == ::unlink(its_client.str().c_str())) {
VSOMEIP_WARNING << "unlink failed for " << its_client.str() << ". Client identifier 0x"
@@ -477,7 +445,7 @@ std::set<client_t> utility::get_used_client_ids() {
}
}
#endif
- for (int i = 0;
+ for (int i = 1;
i < the_configuration_data__->max_used_client_ids_index_;
i++) {
clients.insert(the_configuration_data__->used_client_ids_[i]);
@@ -499,6 +467,7 @@ client_t utility::request_client_id(const std::shared_ptr<configuration> &_confi
std::unique_lock<CriticalSection> its_lock(its_local_configuration_mutex__);
if (the_configuration_data__ != nullptr) {
+ const std::string its_name = _config->get_routing_host();
#ifdef _WIN32
DWORD waitResult = WaitForSingleObject(configuration_data_mutex, INFINITE);
assert(waitResult == WAIT_OBJECT_0);
@@ -513,17 +482,18 @@ client_t utility::request_client_id(const std::shared_ptr<configuration> &_confi
}
pid_t pid = getpid();
- if (the_configuration_data__->pid_ != 0) {
- if (pid != the_configuration_data__->pid_) {
- if (kill(the_configuration_data__->pid_, 0) == -1) {
- VSOMEIP_WARNING << "Routing Manager seems to be inactive. Taking over...";
- the_configuration_data__->routing_manager_host_ = 0x0000;
+ if (its_name == "" || _name == its_name) {
+ if (the_configuration_data__->pid_ != 0) {
+ if (pid != the_configuration_data__->pid_) {
+ if (kill(the_configuration_data__->pid_, 0) == -1) {
+ VSOMEIP_WARNING << "Routing Manager seems to be inactive. Taking over...";
+ the_configuration_data__->routing_manager_host_ = 0x0000;
+ }
}
}
}
#endif
- const std::string its_name = _config->get_routing_host();
bool set_client_as_manager_host(false);
if (its_name != "" && its_name == _name) {
if (the_configuration_data__->routing_manager_host_ == 0x0000) {
@@ -566,17 +536,17 @@ client_t utility::request_client_id(const std::shared_ptr<configuration> &_confi
if (its_preconfigured_client_id == _client) {
// preconfigured client id for application name present in json
// and requested
- if (!is_used_client_id(_client)) {
+ if (!is_used_client_id(_client, _config)) {
use_autoconfig = false;
}
} else {
// preconfigured client id for application name present in
// json, but different client id requested
- if (!is_used_client_id(its_preconfigured_client_id)) {
+ if (!is_used_client_id(its_preconfigured_client_id, _config)) {
// assign preconfigured client id if not already used
_client = its_preconfigured_client_id;
use_autoconfig = false;
- } else if (!is_used_client_id(_client)) {
+ } else if (!is_used_client_id(_client, _config)) {
// if preconfigured client id is already used and
// requested is unused assign requested
use_autoconfig = false;
@@ -586,11 +556,11 @@ client_t utility::request_client_id(const std::shared_ptr<configuration> &_confi
}
if (use_autoconfig) {
- if (_client == ILLEGAL_CLIENT || is_used_client_id(_client)) {
+ if (_client == ILLEGAL_CLIENT || is_used_client_id(_client, _config)) {
_client = the_configuration_data__->client_base_;
}
int increase_count = 0;
- while (is_used_client_id(_client)
+ while (is_used_client_id(_client, _config)
|| !is_bigger_last_assigned_client_id(_client)
|| _config->is_configured_client_id(_client)) {
if ((_client & 0xFF) + 1 > VSOMEIP_MAX_CLIENTS) {
diff --git a/interface/vsomeip/application.hpp b/interface/vsomeip/application.hpp
index 0b71329..f8591df 100644
--- a/interface/vsomeip/application.hpp
+++ b/interface/vsomeip/application.hpp
@@ -312,7 +312,7 @@ public:
*/
virtual void subscribe(service_t _service, instance_t _instance,
eventgroup_t _eventgroup, major_version_t _major = DEFAULT_MAJOR,
- subscription_type_e _subscription_type = subscription_type_e::SU_RELIABLE_AND_UNRELIABLE,
+ subscription_type_e _subscription_type = subscription_type_e::SU_PREFER_RELIABLE,
event_t _event = ANY_EVENT) = 0;
/**
@@ -839,6 +839,28 @@ public:
*/
virtual void unsubscribe(service_t _service, instance_t _instance,
eventgroup_t _eventgroup, event_t _event) = 0;
+
+
+ /**
+ *
+ * \brief Registers a subscription status listener.
+ *
+ * When registered such a handler it will be called for
+ * every application::subscribe call.
+ *
+ * This method is intended to replace the application::
+ * register_subscription_error_handler call in future releases.
+ *
+ * \param _service Service identifier of the service that is subscribed to.
+ * \param _instance Instance identifier of the service that is subscribed to.
+ * \param _eventgroup Eventgroup identifier of the eventgroup is subscribed to.
+ * \param _event Event indentifier of the event is subscribed to.
+ * \param _handler A subscription status handler which will be called by vSomeIP
+ * as a follow of application::subscribe.
+ */
+ virtual void register_subscription_status_handler(service_t _service,
+ instance_t _instance, eventgroup_t _eventgroup, event_t _event,
+ subscription_status_handler_t _handler) = 0;
};
/** @} */
diff --git a/interface/vsomeip/enumeration_types.hpp b/interface/vsomeip/enumeration_types.hpp
index d906f1a..74358c6 100644
--- a/interface/vsomeip/enumeration_types.hpp
+++ b/interface/vsomeip/enumeration_types.hpp
@@ -59,6 +59,7 @@ enum class routing_state_e : uint8_t {
RS_SUSPENDED = 0x01,
RS_RESUMED = 0x02,
RS_SHUTDOWN = 0x03,
+ RS_DIAGNOSIS = 0x04,
RS_UNKNOWN = 0xFF
};
diff --git a/interface/vsomeip/handler.hpp b/interface/vsomeip/handler.hpp
index f2c0628..507ac3c 100644
--- a/interface/vsomeip/handler.hpp
+++ b/interface/vsomeip/handler.hpp
@@ -20,6 +20,8 @@ typedef std::function< void (const std::shared_ptr< message > &) > message_handl
typedef std::function< void (service_t, instance_t, bool) > availability_handler_t;
typedef std::function< bool (client_t, bool) > subscription_handler_t;
typedef std::function< void (const uint16_t) > error_handler_t;
+typedef std::function< void (const service_t, const instance_t, const eventgroup_t,
+ const event_t, const uint16_t) > subscription_status_handler_t;
} // namespace vsomeip
diff --git a/interface/vsomeip/message_base.hpp b/interface/vsomeip/message_base.hpp
index 1518b9e..60c80e6 100644
--- a/interface/vsomeip/message_base.hpp
+++ b/interface/vsomeip/message_base.hpp
@@ -192,6 +192,17 @@ public:
* \brief Set whether or not the message is an initial event.
*/
VSOMEIP_EXPORT virtual void set_initial(bool _is_initial) = 0;
+
+ /**
+ * \brief Return whether or not the CRC value received is valid.
+ */
+ VSOMEIP_EXPORT virtual bool is_valid_crc() const = 0;
+
+ /**
+ * \brief Set whether or not the CRC value received is valid.
+ */
+ VSOMEIP_EXPORT virtual void set_is_valid_crc(bool _is_valid_crc) = 0;
+
};
/** @} */
diff --git a/interface/vsomeip/plugin.hpp b/interface/vsomeip/plugin.hpp
new file mode 100644
index 0000000..4d608f1
--- /dev/null
+++ b/interface/vsomeip/plugin.hpp
@@ -0,0 +1,89 @@
+// Copyright (C) 2016-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 VSOMEIP_PLUGIN_HPP
+#define VSOMEIP_PLUGIN_HPP
+
+#include <memory>
+
+#if WIN32
+ #if VSOMEIP_DLL_COMPILATION_PLUGIN
+ #define VSOMEIP_IMPORT_EXPORT_PLUGIN __declspec(dllexport)
+ #else
+ #define VSOMEIP_IMPORT_EXPORT_PLUGIN __declspec(dllimport)
+ #endif
+#else
+ #define VSOMEIP_IMPORT_EXPORT_PLUGIN
+#endif
+
+#define VSOMEIP_PLUGIN_INIT_SYMBOL "vsomeip_plugin_init"
+
+namespace vsomeip {
+
+enum class plugin_type_e : uint8_t {
+ APPLICATION_PLUGIN,
+ PRE_CONFIGURATION_PLUGIN,
+ CONFIGURATION_PLUGIN,
+ SD_RUNTIME_PLUGIN
+};
+
+class plugin;
+typedef std::shared_ptr<plugin> (*create_plugin_func)();
+typedef create_plugin_func (*plugin_init_func)();
+
+/**
+ * Base class for all plug-ins
+ */
+class VSOMEIP_IMPORT_EXPORT_PLUGIN plugin {
+public:
+ virtual ~plugin() {}
+
+ virtual uint32_t get_plugin_version() const = 0;
+ virtual const std::string &get_plugin_name() const = 0;
+ virtual plugin_type_e get_plugin_type() const = 0;
+};
+
+template<class Plugin_>
+class plugin_impl : public plugin {
+public:
+ static std::shared_ptr<plugin> get_plugin() {
+ return std::make_shared<Plugin_>();
+ }
+
+ plugin_impl(const std::string &_name, uint32_t _version,
+ plugin_type_e _type) {
+ name_ = _name;
+ version_ = _version;
+ type_ = _type;
+ }
+
+ const std::string &get_plugin_name() const {
+ return name_;
+ }
+
+ uint32_t get_plugin_version() const {
+ return version_;
+ }
+
+ plugin_type_e get_plugin_type() const {
+ return type_;
+ }
+
+private:
+ uint32_t version_;
+ std::string name_;
+ plugin_type_e type_;
+};
+
+#define VSOMEIP_PLUGIN(class_name) \
+ extern "C" { \
+ VSOMEIP_EXPORT vsomeip::create_plugin_func vsomeip_plugin_init() { \
+ return class_name::get_plugin; \
+ } \
+ }
+
+} // namespace vsomeip
+
+#endif // VSOMEIP_PLUGIN_HPP
diff --git a/interface/vsomeip/plugins/application_plugin.hpp b/interface/vsomeip/plugins/application_plugin.hpp
new file mode 100644
index 0000000..3d5cce1
--- /dev/null
+++ b/interface/vsomeip/plugins/application_plugin.hpp
@@ -0,0 +1,42 @@
+// Copyright (C) 2016-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 VSOMEIP_APPLICATION_PLUGIN_HPP
+#define VSOMEIP_APPLICATION_PLUGIN_HPP
+
+#include <string>
+#include <memory>
+
+#include <vsomeip/export.hpp>
+
+// Version should be incremented on breaking API change
+#define VSOMEIP_APPLICATION_PLUGIN_VERSION 1
+
+namespace vsomeip {
+
+enum class application_plugin_state_e : uint8_t {
+ STATE_INITIALIZED,
+ STATE_STARTED,
+ STATE_STOPPED
+};
+
+/**
+ * The application plug-in can be used to extend application behavior
+ * via an module/plug-in.
+ */
+class application_plugin {
+public:
+ virtual ~application_plugin() {}
+
+ // Called by vSomeIP to inform an application plug-in about its actual state
+ // Call should not be blocked from plug-in as there is no threading.
+ // The caller thread of "application::init/::start/::stop" will inform the plug-in.
+ virtual void on_application_state_change(const std::string _application_name,
+ const application_plugin_state_e _app_state) = 0;
+};
+
+}
+
+#endif // VSOMEIP_APPLICATION_PLUGIN_HPP
diff --git a/interface/vsomeip/plugins/pre_configuration_plugin.hpp b/interface/vsomeip/plugins/pre_configuration_plugin.hpp
new file mode 100644
index 0000000..6155796
--- /dev/null
+++ b/interface/vsomeip/plugins/pre_configuration_plugin.hpp
@@ -0,0 +1,29 @@
+// Copyright (C) 2016-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 VSOMEIP_PRE_CONFIGURATION_PLUGIN_HPP
+#define VSOMEIP_PRE_CONFIGURATION_PLUGIN_HPP
+
+#include <vsomeip/export.hpp>
+
+// Version should be incremented on breaking API change
+#define VSOMEIP_PRE_CONFIGURATION_PLUGIN_VERSION 1
+
+namespace vsomeip {
+/**
+ * The pre configuration plug-in can be used to extend configuration load behavior
+ * via an module/plug-in.
+ */
+class pre_configuration_plugin {
+public:
+ virtual ~pre_configuration_plugin() {}
+
+ // Plug-In should return a valid path to a vSomeIP configuration.
+ // vSomeIP will use this path for config loading if such a plug-in is availablel.
+ virtual std::string get_configuration_path() = 0;
+};
+}
+
+#endif // VSOMEIP_PRE_CONFIGURATION_PLUGIN_HPP
diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt
new file mode 100644
index 0000000..2ecebc1
--- /dev/null
+++ b/plugins/CMakeLists.txt
@@ -0,0 +1,8 @@
+# Copyright (C) 2016-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/.
+
+cmake_minimum_required (VERSION 2.8)
+
+add_subdirectory ( mgu ) \ No newline at end of file
diff --git a/plugins/mgu/CMakeLists.txt b/plugins/mgu/CMakeLists.txt
new file mode 100644
index 0000000..16a2873
--- /dev/null
+++ b/plugins/mgu/CMakeLists.txt
@@ -0,0 +1,58 @@
+# Copyright (C) 2016-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/.
+
+cmake_minimum_required (VERSION 2.8)
+
+set (VSOMEIP_DIAGNOSIS_PLUGIN_MAJOR_VERSION 1)
+set (VSOMEIP_DIAGNOSIS_PLUGIN_MINOR_VERSION 0)
+set (VSOMEIP_DIAGNOSIS_PLUGIN_PATCH_VERSION 0)
+
+if(DEFINED VSOMEIP_VERSION)
+ set (VSOMEIP_DIAGNOSIS_PLUGIN_VERSION ${VSOMEIP_VERSION}-${VSOMEIP_DIAGNOSIS_PLUGIN_MAJOR_VERSION}.${VSOMEIP_DIAGNOSIS_PLUGIN_MINOR_VERSION}.${VSOMEIP_DIAGNOSIS_PLUGIN_PATCH_VERSION})
+else()
+ find_package (vsomeip 2.7.0 REQUIRED)
+ set (VSOMEIP_DIAGNOSIS_PLUGIN_VERSION ${vsomeip_VERSION}-${VSOMEIP_DIAGNOSIS_PLUGIN_MAJOR_VERSION}.${VSOMEIP_DIAGNOSIS_PLUGIN_MINOR_VERSION}.${VSOMEIP_DIAGNOSIS_PLUGIN_PATCH_VERSION})
+endif()
+message(STATUS "vsomeip-diagnosis-plugin-mgu: " ${VSOMEIP_DIAGNOSIS_PLUGIN_VERSION})
+
+# Offer the user the choice of overriding the installation directories
+set (INSTALL_LIB_DIR lib CACHE PATH "Installation directory for libraries")
+set (INSTALL_BIN_DIR bin CACHE PATH "Installation directory for executables")
+set (INSTALL_INCLUDE_DIR include CACHE PATH "Installation directory for header files")
+
+include_directories (
+ include
+ ${VSOMEIP_INCLUDE_DIRS}
+)
+
+# OS
+if (${CMAKE_SYSTEM_NAME} MATCHES "Linux")
+ set(OS "LINUX")
+ set(DL_LIBRARY "dl")
+ set(NO_DEPRECATED "")
+ set(OPTIMIZE "")
+ set(OS_CXX_FLAGS "-D_GLIBCXX_USE_NANOSLEEP -pthread -O -Wall -Wextra -Wformat -Wformat-security -Wconversion -fexceptions -fstrict-aliasing -fstack-protector -fasynchronous-unwind-tables -fno-omit-frame-pointer -D_FORTIFY_SOURCE=2")
+endif (${CMAKE_SYSTEM_NAME} MATCHES "Linux")
+
+set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D${OS} ${OS_CXX_FLAGS} -g ${OPTIMIZE} -std=c++0x ${NO_DEPRECATED}")
+set(USE_RT "rt")
+
+# MGU diagnosis job plugin library
+file(GLOB vsomeip-diagnosis-plugin-mgu_SRC
+ "src/diagnosis_plugin_mgu.cpp"
+)
+list(SORT vsomeip-diagnosis-plugin-mgu_SRC)
+
+add_library(vsomeip-diagnosis-plugin-mgu SHARED ${vsomeip-diagnosis-plugin-mgu_SRC})
+set_target_properties (vsomeip-diagnosis-plugin-mgu PROPERTIES VERSION ${VSOMEIP_DIAGNOSIS_PLUGIN_VERSION} SOVERSION ${VSOMEIP_DIAGNOSIS_PLUGIN_MAJOR_VERSION})
+target_link_libraries(vsomeip-diagnosis-plugin-mgu vsomeip)
+
+install (
+ TARGETS vsomeip-diagnosis-plugin-mgu
+ LIBRARY DESTINATION "${INSTALL_LIB_DIR}" COMPONENT shlib
+ RUNTIME DESTINATION "${INSTALL_BIN_DIR}" COMPONENT bin
+)
+
+################################################################################################### \ No newline at end of file
diff --git a/plugins/mgu/include/diagnosis_plugin_mgu.hpp b/plugins/mgu/include/diagnosis_plugin_mgu.hpp
new file mode 100644
index 0000000..2520636
--- /dev/null
+++ b/plugins/mgu/include/diagnosis_plugin_mgu.hpp
@@ -0,0 +1,53 @@
+// Copyright (C) 2016-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 VSOMEIP_DIAGNOSIS_PLUGIN_MGU_HPP
+#define VSOMEIP_DIAGNOSIS_PLUGIN_MGU_HPP
+
+#include <mutex>
+
+#include <vsomeip/application.hpp>
+#include <vsomeip/runtime.hpp>
+#include <vsomeip/message.hpp>
+#include <vsomeip/payload.hpp>
+#include <vsomeip/plugins/application_plugin.hpp>
+
+namespace vsomeip {
+namespace mgu {
+
+class diagnosis_plugin_mgu
+ : public application_plugin,
+ public plugin_impl<diagnosis_plugin_mgu>,
+ public std::enable_shared_from_this<diagnosis_plugin_mgu> {
+public:
+ diagnosis_plugin_mgu();
+ VSOMEIP_EXPORT void on_application_state_change(
+ const std::string _application_name,
+ const application_plugin_state_e _app_state);
+private:
+ void on_message(const std::shared_ptr<vsomeip::message> &_request);
+ void on_state(vsomeip::state_type_e _state);
+
+ std::string application_name_;
+ std::mutex application_name_mutex_;
+
+ static const uint32_t error_ok_;
+ static const uint32_t error_out_of_range_;
+ static const uint32_t error_communication_error_;
+ static const uint8_t communication_type_mask_;
+ static const uint8_t expected_payload_length_;
+ static const uint8_t communication_type_payload_offset_;
+ static const vsomeip::service_t diag_job_service_id_;
+ static const vsomeip::instance_t diag_job_instance_id_;
+ static const vsomeip::major_version_t diag_job_major_;
+ static const vsomeip::minor_version_t diag_job_minor_;
+ static const vsomeip::method_t diag_job_rx_on_tx_on_;
+ static const vsomeip::method_t diag_job_rx_on_tx_off_;
+};
+
+} // namespace mgu
+} // namespace vsomeip
+
+#endif // VSOMEIP_DIAGNOSIS_PLUGIN_MGU_HPP
diff --git a/plugins/mgu/src/diagnosis_plugin_mgu.cpp b/plugins/mgu/src/diagnosis_plugin_mgu.cpp
new file mode 100644
index 0000000..aa8c57d
--- /dev/null
+++ b/plugins/mgu/src/diagnosis_plugin_mgu.cpp
@@ -0,0 +1,144 @@
+// Copyright (C) 2016-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 <vsomeip/plugin.hpp>
+#include <byteswap.h>
+
+#include "../include/diagnosis_plugin_mgu.hpp"
+
+VSOMEIP_PLUGIN(vsomeip::mgu::diagnosis_plugin_mgu)
+
+namespace vsomeip {
+namespace mgu {
+
+const uint32_t diagnosis_plugin_mgu::error_ok_ = 256;
+const uint32_t diagnosis_plugin_mgu::error_out_of_range_ = 257;
+const uint32_t diagnosis_plugin_mgu::error_communication_error_ = 576;
+const uint8_t diagnosis_plugin_mgu::communication_type_mask_ = 2;
+const uint8_t diagnosis_plugin_mgu::expected_payload_length_ = sizeof(uint32_t) + sizeof(uint8_t);
+const uint8_t diagnosis_plugin_mgu::communication_type_payload_offset_ = sizeof(uint32_t);
+const vsomeip::service_t diagnosis_plugin_mgu::diag_job_service_id_ = 0xFE9F;
+const vsomeip::instance_t diagnosis_plugin_mgu::diag_job_instance_id_ = 0x80;
+const vsomeip::major_version_t diagnosis_plugin_mgu::diag_job_major_ = 0x0;
+const vsomeip::minor_version_t diagnosis_plugin_mgu::diag_job_minor_ = 0x1;
+const vsomeip::method_t diagnosis_plugin_mgu::diag_job_rx_on_tx_on_ = 0x1;
+const vsomeip::method_t diagnosis_plugin_mgu::diag_job_rx_on_tx_off_ = 0x2;
+
+diagnosis_plugin_mgu::diagnosis_plugin_mgu()
+ : plugin_impl("diagnosis job plug-in mgu",
+ VSOMEIP_APPLICATION_PLUGIN_VERSION,
+ vsomeip::plugin_type_e::APPLICATION_PLUGIN) {
+}
+
+void diagnosis_plugin_mgu::on_application_state_change(const std::string _application_name,
+ const vsomeip::application_plugin_state_e _app_state) {
+
+ std::shared_ptr<vsomeip::application> application = nullptr;
+ {
+ std::lock_guard<std::mutex> lock(application_name_mutex_);
+ application_name_ = _application_name;
+ application = runtime::get()->get_application(application_name_);
+ }
+ if (application) {
+ switch (_app_state) {
+ case vsomeip::application_plugin_state_e::STATE_INITIALIZED:
+ if (application->is_routing()) {
+ application->register_state_handler(
+ std::bind(&diagnosis_plugin_mgu::on_state,
+ this, std::placeholders::_1));
+ application->register_message_handler(diag_job_service_id_,
+ diag_job_instance_id_, vsomeip::ANY_METHOD,
+ std::bind(&diagnosis_plugin_mgu::on_message,
+ this, std::placeholders::_1));
+ }
+ break;
+
+ case vsomeip::application_plugin_state_e::STATE_STARTED:
+ break;
+ case vsomeip::application_plugin_state_e::STATE_STOPPED:
+ if (application->is_routing()) {
+ application->stop_offer_service(
+ diag_job_service_id_, diag_job_instance_id_, diag_job_major_, diag_job_minor_);
+ application->unregister_message_handler(
+ diag_job_service_id_, diag_job_instance_id_, vsomeip::ANY_METHOD);
+ application->unregister_state_handler();
+ }
+ break;
+ }
+ }
+}
+
+void diagnosis_plugin_mgu::on_message(const std::shared_ptr<vsomeip::message> &_request) {
+ std::shared_ptr<vsomeip::application> application = nullptr;
+ {
+ std::lock_guard<std::mutex> lock(application_name_mutex_);
+ application = runtime::get()->get_application(application_name_);
+ }
+ if (application && application->is_routing()) {
+ vsomeip::routing_state_e state = vsomeip::routing_state_e::RS_UNKNOWN;
+ switch (_request->get_method()) {
+ case diag_job_rx_on_tx_on_:
+ state = vsomeip::routing_state_e::RS_RUNNING;
+ break;
+ case diag_job_rx_on_tx_off_:
+ state = vsomeip::routing_state_e::RS_DIAGNOSIS;
+ break;
+ default:
+ break;
+ }
+ // Only reply if one of the 2 well known message are called!
+ if (state != vsomeip::routing_state_e::RS_UNKNOWN) {
+ uint32_t error;
+ auto payload = _request->get_payload();
+ // Check for correct data length
+ if (payload->get_length() == expected_payload_length_) {
+ // Check if bit 1 is set
+ if (payload->get_data()[communication_type_payload_offset_]
+ & communication_type_mask_) {
+ application->set_routing_state(state);
+ error = bswap_32(error_ok_);
+ } else {
+ error = bswap_32(error_out_of_range_);
+ }
+ } else {
+ error = bswap_32(error_communication_error_);
+ }
+
+ auto its_payload = vsomeip::runtime::get()->create_payload();
+ std::vector<byte_t> its_payload_data;
+ // Set error return type
+ for (uint8_t i = 0; i < sizeof(error); ++i) {
+ its_payload_data.push_back(reinterpret_cast<const byte_t*>(&error)[i]);
+ }
+
+ // Copy handle from request-payload!
+ for (uint8_t i = 0; i < sizeof(uint32_t); ++i) {
+ its_payload_data.push_back(payload->get_data()[i]);
+ }
+
+ // Create & send response
+ its_payload->set_data(its_payload_data);
+ std::shared_ptr<vsomeip::message> its_response =
+ vsomeip::runtime::get()->create_response(_request);
+ its_response->set_payload(its_payload);
+ application->send(its_response, true);
+ }
+ }
+}
+
+void diagnosis_plugin_mgu::on_state(vsomeip::state_type_e _state) {
+ std::shared_ptr<vsomeip::application> application = nullptr;
+ {
+ std::lock_guard<std::mutex> lock(application_name_mutex_);
+ application = runtime::get()->get_application(application_name_);
+ }
+ if (application && _state == vsomeip::state_type_e::ST_REGISTERED) {
+ application->offer_service(diag_job_service_id_, diag_job_instance_id_,
+ diag_job_major_, diag_job_minor_);
+ }
+}
+
+} // namespace mgu
+} // namespace vsomeip
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index fde4c84..8e88a05 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -76,6 +76,7 @@ if(NOT ${TESTS_BAT})
vsomeip-cfg
${Boost_LIBRARIES}
${DL_LIBRARY}
+ ${TEST_LINK_LIBRARIES}
)
# The following will make sure that ${TEST_CONFIGURATION_CONFIG_FILE} is copied
@@ -1299,6 +1300,78 @@ if(NOT ${TESTS_BAT})
${PROJECT_BINARY_DIR}/test/${TEST_SUBSCRIBE_NOTIFY_SLAVE_STARTER}
${TEST_SUBSCRIBE_NOTIFY_SERVICE}
)
+
+ # subscribe_notify_test_one_event_two_eventgroups
+ set(TEST_SUBSCRIBE_NOTIFY_ONE_EVENT_TWO_EVENTGROUPS_NAME subscribe_notify_test_one_event_two_eventgroups)
+
+ # service
+ set(TEST_SUBSCRIBE_NOTIFY_ONE_EVENT_TWO_EVENTGROUPS_SERVICE ${TEST_SUBSCRIBE_NOTIFY_ONE_EVENT_TWO_EVENTGROUPS_NAME}_service)
+ add_executable(${TEST_SUBSCRIBE_NOTIFY_ONE_EVENT_TWO_EVENTGROUPS_SERVICE}
+ subscribe_notify_tests/${TEST_SUBSCRIBE_NOTIFY_ONE_EVENT_TWO_EVENTGROUPS_SERVICE}.cpp)
+ target_link_libraries(${TEST_SUBSCRIBE_NOTIFY_ONE_EVENT_TWO_EVENTGROUPS_SERVICE}
+ vsomeip
+ ${Boost_LIBRARIES}
+ ${DL_LIBRARY}
+ ${TEST_LINK_LIBRARIES}
+ )
+ # client
+ set(TEST_SUBSCRIBE_NOTIFY_ONE_EVENT_TWO_EVENTGROUPS_CLIENT ${TEST_SUBSCRIBE_NOTIFY_ONE_EVENT_TWO_EVENTGROUPS_NAME}_client)
+ add_executable(${TEST_SUBSCRIBE_NOTIFY_ONE_EVENT_TWO_EVENTGROUPS_CLIENT}
+ subscribe_notify_tests/${TEST_SUBSCRIBE_NOTIFY_ONE_EVENT_TWO_EVENTGROUPS_CLIENT}.cpp)
+ target_link_libraries(${TEST_SUBSCRIBE_NOTIFY_ONE_EVENT_TWO_EVENTGROUPS_CLIENT}
+ vsomeip
+ ${Boost_LIBRARIES}
+ ${DL_LIBRARY}
+ ${TEST_LINK_LIBRARIES}
+ )
+
+ set(TEST_SUBSCRIBE_NOTIFY_ONE_EVENT_TWO_EVENTGROUPS_MASTER_CONFIG_FILE
+ ${TEST_SUBSCRIBE_NOTIFY_ONE_EVENT_TWO_EVENTGROUPS_NAME}_master.json)
+ configure_file(
+ ${PROJECT_SOURCE_DIR}/test/subscribe_notify_tests/conf/${TEST_SUBSCRIBE_NOTIFY_ONE_EVENT_TWO_EVENTGROUPS_MASTER_CONFIG_FILE}.in
+ ${PROJECT_SOURCE_DIR}/test/subscribe_notify_tests/${TEST_SUBSCRIBE_NOTIFY_ONE_EVENT_TWO_EVENTGROUPS_MASTER_CONFIG_FILE}
+ @ONLY)
+ copy_to_builddir(
+ ${PROJECT_SOURCE_DIR}/test/subscribe_notify_tests/${TEST_SUBSCRIBE_NOTIFY_ONE_EVENT_TWO_EVENTGROUPS_MASTER_CONFIG_FILE}
+ ${PROJECT_BINARY_DIR}/test/${TEST_SUBSCRIBE_NOTIFY_ONE_EVENT_TWO_EVENTGROUPS_MASTER_CONFIG_FILE}
+ ${TEST_SUBSCRIBE_NOTIFY_ONE_EVENT_TWO_EVENTGROUPS_SERVICE}
+ )
+
+ set(TEST_SUBSCRIBE_NOTIFY_ONE_EVENT_TWO_EVENTGROUPS_SLAVE_UDP_CONFIG_FILE
+ ${TEST_SUBSCRIBE_NOTIFY_ONE_EVENT_TWO_EVENTGROUPS_NAME}_udp_slave.json)
+ configure_file(
+ ${PROJECT_SOURCE_DIR}/test/subscribe_notify_tests/conf/${TEST_SUBSCRIBE_NOTIFY_ONE_EVENT_TWO_EVENTGROUPS_SLAVE_UDP_CONFIG_FILE}.in
+ ${PROJECT_SOURCE_DIR}/test/subscribe_notify_tests/${TEST_SUBSCRIBE_NOTIFY_ONE_EVENT_TWO_EVENTGROUPS_SLAVE_UDP_CONFIG_FILE}
+ @ONLY)
+ copy_to_builddir(
+ ${PROJECT_SOURCE_DIR}/test/subscribe_notify_tests/${TEST_SUBSCRIBE_NOTIFY_ONE_EVENT_TWO_EVENTGROUPS_SLAVE_UDP_CONFIG_FILE}
+ ${PROJECT_BINARY_DIR}/test/${TEST_SUBSCRIBE_NOTIFY_ONE_EVENT_TWO_EVENTGROUPS_SLAVE_UDP_CONFIG_FILE}
+ ${TEST_SUBSCRIBE_NOTIFY_ONE_EVENT_TWO_EVENTGROUPS_CLIENT}
+ )
+ set(TEST_SUBSCRIBE_NOTIFY_ONE_EVENT_TWO_EVENTGROUPS_SLAVE_TCP_CONFIG_FILE
+ ${TEST_SUBSCRIBE_NOTIFY_ONE_EVENT_TWO_EVENTGROUPS_NAME}_tcp_slave.json)
+ configure_file(
+ ${PROJECT_SOURCE_DIR}/test/subscribe_notify_tests/conf/${TEST_SUBSCRIBE_NOTIFY_ONE_EVENT_TWO_EVENTGROUPS_SLAVE_TCP_CONFIG_FILE}.in
+ ${PROJECT_SOURCE_DIR}/test/subscribe_notify_tests/${TEST_SUBSCRIBE_NOTIFY_ONE_EVENT_TWO_EVENTGROUPS_SLAVE_TCP_CONFIG_FILE}
+ @ONLY)
+ copy_to_builddir(
+ ${PROJECT_SOURCE_DIR}/test/subscribe_notify_tests/${TEST_SUBSCRIBE_NOTIFY_ONE_EVENT_TWO_EVENTGROUPS_SLAVE_TCP_CONFIG_FILE}
+ ${PROJECT_BINARY_DIR}/test/${TEST_SUBSCRIBE_NOTIFY_ONE_EVENT_TWO_EVENTGROUPS_SLAVE_TCP_CONFIG_FILE}
+ ${TEST_SUBSCRIBE_NOTIFY_ONE_EVENT_TWO_EVENTGROUPS_CLIENT}
+ )
+
+ set(TEST_SUBSCRIBE_NOTIFY_ONE_EVENT_TWO_EVENTGROUPS_MASTER_STARTER
+ ${TEST_SUBSCRIBE_NOTIFY_ONE_EVENT_TWO_EVENTGROUPS_NAME}_master_starter.sh)
+ copy_to_builddir(${PROJECT_SOURCE_DIR}/test/subscribe_notify_tests/${TEST_SUBSCRIBE_NOTIFY_ONE_EVENT_TWO_EVENTGROUPS_MASTER_STARTER}
+ ${PROJECT_BINARY_DIR}/test/${TEST_SUBSCRIBE_NOTIFY_ONE_EVENT_TWO_EVENTGROUPS_MASTER_STARTER}
+ ${TEST_SUBSCRIBE_NOTIFY_ONE_EVENT_TWO_EVENTGROUPS_SERVICE}
+ )
+ set(TEST_SUBSCRIBE_NOTIFY_ONE_EVENT_TWO_EVENTGROUPS_SLAVE_STARTER
+ ${TEST_SUBSCRIBE_NOTIFY_ONE_EVENT_TWO_EVENTGROUPS_NAME}_slave_starter.sh)
+ copy_to_builddir(${PROJECT_SOURCE_DIR}/test/subscribe_notify_tests/${TEST_SUBSCRIBE_NOTIFY_ONE_EVENT_TWO_EVENTGROUPS_SLAVE_STARTER}
+ ${PROJECT_BINARY_DIR}/test/${TEST_SUBSCRIBE_NOTIFY_ONE_EVENT_TWO_EVENTGROUPS_SLAVE_STARTER}
+ ${TEST_SUBSCRIBE_NOTIFY_ONE_EVENT_TWO_EVENTGROUPS_SERVICE}
+ )
endif()
##############################################################################
@@ -1760,6 +1833,8 @@ if(NOT ${TESTS_BAT})
add_dependencies(${TEST_CLIENT_ID_SERVICE} gtest)
add_dependencies(${TEST_CLIENT_ID_UTILITY} gtest)
add_dependencies(${TEST_SUBSCRIBE_NOTIFY_SERVICE} gtest)
+ add_dependencies(${TEST_SUBSCRIBE_NOTIFY_ONE_EVENT_TWO_EVENTGROUPS_SERVICE} gtest)
+ add_dependencies(${TEST_SUBSCRIBE_NOTIFY_ONE_EVENT_TWO_EVENTGROUPS_CLIENT} gtest)
add_dependencies(${TEST_SUBSCRIBE_NOTIFY_ONE_SERVICE} gtest)
add_dependencies(${TEST_CPU_LOAD_SERVICE} gtest)
add_dependencies(${TEST_CPU_LOAD_CLIENT} gtest)
@@ -1800,6 +1875,8 @@ if(NOT ${TESTS_BAT})
add_dependencies(build_tests ${TEST_CLIENT_ID_SERVICE})
add_dependencies(build_tests ${TEST_CLIENT_ID_UTILITY})
add_dependencies(build_tests ${TEST_SUBSCRIBE_NOTIFY_SERVICE})
+ add_dependencies(build_tests ${TEST_SUBSCRIBE_NOTIFY_ONE_EVENT_TWO_EVENTGROUPS_SERVICE})
+ add_dependencies(build_tests ${TEST_SUBSCRIBE_NOTIFY_ONE_EVENT_TWO_EVENTGROUPS_CLIENT})
add_dependencies(build_tests ${TEST_SUBSCRIBE_NOTIFY_ONE_SERVICE})
add_dependencies(build_tests ${TEST_CPU_LOAD_SERVICE})
add_dependencies(build_tests ${TEST_CPU_LOAD_CLIENT})
@@ -1826,10 +1903,7 @@ endif()
if(NOT ${TESTS_BAT})
add_test(NAME ${TEST_CONFIGURATION}
- COMMAND ${TEST_CONFIGURATION} --someip ${TEST_CONFIGURATION_CONFIG_FILE}
- )
- add_test(NAME ${TEST_CONFIGURATION}_deprecated_config_file
- COMMAND ${TEST_CONFIGURATION} --someip ${TEST_CONFIGURATION_DEPRECATED_CONFIG_FILE}
+ COMMAND ${TEST_CONFIGURATION}
)
# application test
@@ -1998,6 +2072,14 @@ if(NOT ${TESTS_BAT})
COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_SUBSCRIBE_NOTIFY_MASTER_STARTER} UDP ${TEST_SUBSCRIBE_NOTIFY_DIFF_IDS_DIFF_PORTS_AUTOCONFIG_MASTER_CONFIG_FILE})
set_tests_properties(${TEST_SUBSCRIBE_NOTIFY_NAME}_diff_client_ids_diff_ports_same_service_id_udp PROPERTIES TIMEOUT 120)
+ add_test(NAME ${TEST_SUBSCRIBE_NOTIFY_ONE_EVENT_TWO_EVENTGROUPS_NAME}_udp
+ COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_SUBSCRIBE_NOTIFY_ONE_EVENT_TWO_EVENTGROUPS_MASTER_STARTER} UDP ${TEST_SUBSCRIBE_NOTIFY_ONE_EVENT_TWO_EVENTGROUPS_MASTER_CONFIG_FILE})
+ set_tests_properties(${TEST_SUBSCRIBE_NOTIFY_ONE_EVENT_TWO_EVENTGROUPS_NAME}_udp PROPERTIES TIMEOUT 120)
+
+ add_test(NAME ${TEST_SUBSCRIBE_NOTIFY_ONE_EVENT_TWO_EVENTGROUPS_NAME}_tcp
+ COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_SUBSCRIBE_NOTIFY_ONE_EVENT_TWO_EVENTGROUPS_MASTER_STARTER} TCP ${TEST_SUBSCRIBE_NOTIFY_ONE_EVENT_TWO_EVENTGROUPS_MASTER_CONFIG_FILE})
+ set_tests_properties(${TEST_SUBSCRIBE_NOTIFY_ONE_EVENT_TWO_EVENTGROUPS_NAME}_tcp PROPERTIES TIMEOUT 120)
+
# subscribe notify one id tests
add_test(NAME ${TEST_SUBSCRIBE_NOTIFY_ONE_NAME}_diff_client_ids_diff_ports_udp
COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_SUBSCRIBE_NOTIFY_ONE_MASTER_STARTER} UDP ${TEST_SUBSCRIBE_NOTIFY_ONE_DIFF_IDS_DIFF_PORTS_MASTER_CONFIG_FILE})
diff --git a/test/client_id_tests/client_id_test_utility.cpp b/test/client_id_tests/client_id_test_utility.cpp
index 02b3b0e..f4e66c0 100644
--- a/test/client_id_tests/client_id_test_utility.cpp
+++ b/test/client_id_tests/client_id_test_utility.cpp
@@ -8,10 +8,11 @@
#include <unistd.h> // for access()
#include <sstream>
-#include "../../implementation/utility/include/utility.hpp"
-#include "../../implementation/configuration/include/configuration.hpp"
#include <vsomeip/constants.hpp>
+#include "../../implementation/utility/include/utility.hpp"
+#include "../../implementation/configuration/include/configuration.hpp"
+#include "../../implementation/plugin/include/plugin_manager.hpp"
using namespace vsomeip;
@@ -31,22 +32,26 @@ static const vsomeip::client_t APPLICATION_OUT_LOW_CLIENT_ID = 0x6011;
static const std::string APPLICATION_OUT_HIGH_NAME = "client_id_test_utility_service_out_high";
static const vsomeip::client_t APPLICATION_OUT_HIGH_CLIENT_ID = 0x6411;
-
-
class client_id_utility_test: public ::testing::Test {
public:
client_id_utility_test() :
- configuration_(vsomeip::configuration::get()),
client_id_routing_manager_(0x0) {
+
+ std::shared_ptr<vsomeip::configuration> its_configuration;
+ auto its_plugin = vsomeip::plugin_manager::get()->get_plugin(
+ vsomeip::plugin_type_e::CONFIGURATION_PLUGIN);
+ if (its_plugin) {
+ configuration_ = std::dynamic_pointer_cast<vsomeip::configuration>(its_plugin);
+ }
}
protected:
virtual void SetUp() {
- ASSERT_FALSE(file_exist(std::string("/dev/shm").append(VSOMEIP_SHM_NAME)));
+ ASSERT_FALSE(file_exist(std::string("/dev/shm").append(utility::get_shm_name(configuration_))));
ASSERT_TRUE(static_cast<bool>(configuration_));
configuration_->load(APPLICATION_NAME_ROUTING_MANAGER);
utility::auto_configuration_init(configuration_);
- EXPECT_TRUE(file_exist(std::string("/dev/shm").append(VSOMEIP_SHM_NAME)));
+ EXPECT_TRUE(file_exist(std::string("/dev/shm").append(utility::get_shm_name(configuration_))));
client_id_routing_manager_ = utility::request_client_id(
configuration_, APPLICATION_NAME_ROUTING_MANAGER, 0x0);
@@ -55,8 +60,8 @@ protected:
}
virtual void TearDown() {
- utility::auto_configuration_exit(client_id_routing_manager_);
- EXPECT_FALSE(file_exist(std::string("/dev/shm").append(VSOMEIP_SHM_NAME)));
+ utility::auto_configuration_exit(client_id_routing_manager_, configuration_);
+ EXPECT_FALSE(file_exist(std::string("/dev/shm").append(utility::get_shm_name(configuration_))));
}
bool file_exist(const std::string &_path) {
diff --git a/test/configuration_tests/configuration-test-deprecated.json b/test/configuration_tests/configuration-test-deprecated.json
index 87f3279..ad4c0d6 100644
--- a/test/configuration_tests/configuration-test-deprecated.json
+++ b/test/configuration_tests/configuration-test-deprecated.json
@@ -1,21 +1,88 @@
{
"unicast" : "10.0.2.15",
+ "diagnosis" : "85",
"logging" :
{
"level" : "debug",
"console" : "true",
"file" : { "enable" : "true", "path" : "/home/someip/another-file.log" },
- "dlt" : "false"
+ "dlt" : "false",
+ "version" : {
+ "enable" : "false",
+ "interval" : "15"
+ }
+ },
+ "watchdog" :
+ {
+ "enable" : "true",
+ "timeout" : "1234",
+ "allowed_missing_pongs" : "7"
+ },
+ "file-permissions" :
+ {
+ "permissions-shm" : "444",
+ "umask" : "222"
+ },
+ "supports_selective_broadcasts" :
+ {
+ "address" : "160.160.160.160"
+ },
+ "tracing" :
+ {
+ "enable" : "true",
+ "sd_enable" : "true",
+ "channels" :
+ [
+ {
+ "name" : "testname",
+ "id" : "testid"
+ },
+ {
+ "name" : "testname2",
+ "id" : "testid2"
+ }
+ ],
+ "filters" :
+ [
+ {
+ "channel" : "testname",
+ "services" : ["0x1111",2222],
+ "methods" : ["0x1111",2222],
+ "clients" : ["0x1111",2222]
+ },
+ {
+ "channel" : "testname2",
+ "services" : ["0x3333",4444],
+ "methods" : ["0x3333",4444],
+ "clients" : ["0x3333",4444]
+ }
+ ]
},
"applications" :
[
{
"name" : "my_application",
- "id" : "0x7788"
+ "id" : "0x7788",
+ "max_dispatchers" : "25",
+ "max_dispatch_time" : "1234",
+ "threads" : "12",
+ "request_debounce_time" : "5000",
+ "plugins" :
+ [
+ {
+ "application_plugin" : "testlibraryname"
+ },
+ {
+ "intentionally_wrong_plugin" : "wrong"
+ }
+ ]
},
{
"name" : "other_application",
- "id" : "0x9933"
+ "id" : "0x9933",
+ "threads" : "0",
+ "threads" : "256",
+ "request_debounce_time" : "10001"
}
],
"servicegroups" :
@@ -37,7 +104,7 @@
{
"service" : "0x1234",
"instance" : "0x0022",
- "reliable" : { "port" : "30506", "magic_cookies" : "false" },
+ "reliable" : { "port" : "30506", "enable-magic-cookies" : "true" },
"unreliable" : "31000",
"events" :
[
@@ -77,6 +144,24 @@
"service" : "0x1234",
"instance" : "0x0023",
"reliable" : "30503"
+ },
+ {
+ "service" : "0x7809",
+ "instance" : "0x1",
+ "multicast" :
+ {
+ "address" : "224.212.244.225",
+ "port" : "1234"
+ },
+ "eventgroups" :
+ [
+ {
+ "eventgroup" : "0x1111",
+ "threshold" : "8",
+ "is_multicast" : "true",
+ "events" : [ "0x778", "0x77A" ]
+ }
+ ]
}
]
},
@@ -105,6 +190,15 @@
"instance" : "0x0022",
"reliable" : "30505",
"unreliable" : "30507"
+ },
+ {
+ "service" : "0x3333",
+ "instance" : "0x1"
+ },
+ {
+ "service" : "0x3555",
+ "instance" : "0x1",
+ "protocol" : "other"
}
]
},
@@ -122,6 +216,38 @@
]
}
],
+ "internal_services" :
+ [
+ {
+ "first" : "0xF100",
+ "last" : "0xF109"
+ },
+ {
+ "first" : {
+ "service" : "0xF300",
+ "instance" : "0x1"
+ },
+ "last" : {
+ "service" : "0xF300",
+ "instance" : "0x10"
+ }
+ }
+ ],
+ "clients" :
+ [
+ {
+ "service" : "0x8888",
+ "instance" : "0x1",
+ "unreliable" : [ "0x11", "0x10" ],
+ "reliable" : [ "0x11", "0x10" ]
+ },
+ {
+ "service" : "8888",
+ "instance" : "1",
+ "unreliable" : [ 40000, 40001 ],
+ "reliable" : [ 40000, 40001 ]
+ }
+ ],
"max-payload-size-local" : "15000",
"max-payload-size-reliable" : "17000",
"buffer-shrink-threshold" : "11",
@@ -148,12 +274,75 @@
]
}
],
+ "security" :
+ {
+ "check_credentials" : "true",
+ "policies" :
+ [
+ {
+ "client" : "0x1277",
+ "credentials" : { "uid" : "1000", "gid" : "1000" },
+ "allow" :
+ {
+ "offers":
+ [
+ {
+ "service" : "0x1234",
+ "instance" : "0x5678"
+ },
+ {
+ "service" : "0x1235",
+ "instance" : "0x5678"
+ }
+ ]
+ }
+ },
+ {
+ "client" : { "first" : "0x1343", "last" : "0x1346" },
+ "allow" :
+ {
+ "requests":
+ [
+ {
+ "service" : "0x1234",
+ "instance" : "0x5678"
+ }
+ ]
+ }
+ },
+ {
+ "client" : { "first" : "0x1443", "last" : "0x1446" },
+ "deny" :
+ {
+ "requests":
+ [
+ {
+ "service" : "0x1234",
+ "instance" : "0x5678"
+ }
+ ],
+ "offers":
+ [
+ {
+ "service" : "0x1234",
+ "instance" : "0x5678"
+ },
+ {
+ "service" : "0x1235",
+ "instance" : "0x5678"
+ }
+ ]
+ }
+ }
+ ]
+ },
"routing" : "my_application",
"service-discovery" :
{
"enable" : "true",
"protocol" : "udp",
"multicast" : "224.212.244.223",
- "port" : "30666"
+ "port" : "30666",
+ "offer_debounce_time" : "1000"
}
}
diff --git a/test/configuration_tests/configuration-test.cpp b/test/configuration_tests/configuration-test.cpp
index 5eb9015..8693d4d 100644
--- a/test/configuration_tests/configuration-test.cpp
+++ b/test/configuration_tests/configuration-test.cpp
@@ -6,11 +6,17 @@
#include <cstdlib>
#include <iostream>
+#include <gtest/gtest.h>
+
#include <vsomeip/constants.hpp>
+#include <vsomeip/plugins/application_plugin.hpp>
#include "../implementation/configuration/include/configuration.hpp"
+#include "../implementation/configuration/include/configuration_impl.hpp"
#include "../implementation/logging/include/logger.hpp"
+#include "../implementation/plugin/include/plugin_manager.hpp"
+
#define CONFIGURATION_FILE "configuration-test.json"
#define DEPRECATED_CONFIGURATION_FILE "configuration-test-deprecated.json"
@@ -24,6 +30,16 @@
#define EXPECTED_ROUTING_MANAGER_HOST "my_application"
+// Logging
+#define EXPECTED_VERSION_LOGGING_ENABLED false
+#define EXPECTED_VERSION_LOGGING_INTERVAL 15
+
+// Application
+#define EXPECTED_APPLICATION_MAX_DISPATCHERS 25
+#define EXPECTED_APPLICATION_MAX_DISPATCH_TIME 1234
+#define EXPECTED_APPLICATION_THREADS 12
+#define EXPECTED_APPLICATION_REQUEST_DEBOUNCE_TIME 5000
+
// Services
#define EXPECTED_UNICAST_ADDRESS_1234_0022 EXPECTED_UNICAST_ADDRESS
#define EXPECTED_RELIABLE_PORT_1234_0022 30506
@@ -67,11 +83,11 @@
#define EXPECTED_DEPRECATED_REQUEST_RESPONSE_DELAY 2001
template<class T>
-void check(const T &_is, const T &_expected, const std::string &_test) {
+::testing::AssertionResult check(const T &_is, const T &_expected, const std::string &_test) {
if (_is == _expected) {
- VSOMEIP_INFO << "Test \"" << _test << "\" succeeded.";
+ return ::testing::AssertionSuccess() << "Test \"" << _test << "\" succeeded.";
} else {
- VSOMEIP_ERROR << "Test \"" << _test << "\" failed! ("
+ return ::testing::AssertionFailure() << "Test \"" << _test << "\" failed! ("
<< _is << " != " << _expected << ")";
}
}
@@ -81,6 +97,12 @@ void check_file(const std::string &_config_file,
bool _expected_has_console,
bool _expected_has_file,
bool _expected_has_dlt,
+ bool _expected_version_logging_enabled,
+ uint32_t _expected_version_logging_interval,
+ uint32_t _expected_application_max_dispatcher,
+ uint32_t _expected_application_max_dispatch_time,
+ uint32_t _expected_application_threads,
+ uint32_t _expected_application_request_debounce_time,
const std::string &_expected_logfile,
const std::string &_expected_loglevel,
const std::string &_expected_unicast_address_1234_0022,
@@ -111,16 +133,26 @@ void check_file(const std::string &_config_file,
vsomeip::ttl_t _expected_request_response_delay) {
// 0. Create configuration object
- std::shared_ptr<vsomeip::configuration> its_configuration
- = vsomeip::configuration::get();
+ std::shared_ptr<vsomeip::configuration> its_configuration;
+ auto its_plugin = vsomeip::plugin_manager::get()->get_plugin(
+ vsomeip::plugin_type_e::CONFIGURATION_PLUGIN);
+ if (its_plugin) {
+ its_configuration = std::dynamic_pointer_cast<vsomeip::configuration>(its_plugin);
+ }
// 1. Did we get a configuration object?
if (0 == its_configuration) {
- VSOMEIP_ERROR << "No configuration object. "
+ ADD_FAILURE() << "No configuration object. "
"Either memory overflow or loading error detected!";
return;
}
+ vsomeip::cfg::configuration_impl its_copied_config(
+ static_cast<vsomeip::cfg::configuration_impl&>(*its_configuration));
+ vsomeip::cfg::configuration_impl* its_new_config =
+ new vsomeip::cfg::configuration_impl(its_copied_config);
+ delete its_new_config;
+
// 2. Set environment variable to config file and load it
#ifndef _WIN32
setenv("VSOMEIP_CONFIGURATION", _config_file.c_str(), 1);
@@ -129,11 +161,20 @@ void check_file(const std::string &_config_file,
#endif
its_configuration->load(EXPECTED_ROUTING_MANAGER_HOST);
+ its_configuration->set_configuration_path("/my/test/path");
+
// 3. Check host address
boost::asio::ip::address its_host_unicast_address
= its_configuration->get_unicast_address();
- check<std::string>(its_host_unicast_address.to_string(),
- _expected_unicast_address, "UNICAST ADDRESS");
+ EXPECT_TRUE(check<std::string>(its_host_unicast_address.to_string(),
+ _expected_unicast_address, "UNICAST ADDRESS"));
+ EXPECT_TRUE(its_configuration->is_v4());
+ EXPECT_FALSE(its_configuration->is_v6());
+
+ // check diagnosis prefix
+ EXPECT_NE(0x54, its_configuration->get_diagnosis_address());
+ EXPECT_EQ(0x55, its_configuration->get_diagnosis_address());
+ EXPECT_NE(0x56, its_configuration->get_diagnosis_address());
// 4. Check logging
bool has_console = its_configuration->has_console_log();
@@ -142,13 +183,113 @@ void check_file(const std::string &_config_file,
std::string logfile = its_configuration->get_logfile();
boost::log::trivial::severity_level loglevel
= its_configuration->get_loglevel();
+ bool has_version_logging = its_configuration->log_version();
+ std::uint32_t version_logging_interval = its_configuration->get_log_version_interval();
+
+ EXPECT_TRUE(check<bool>(has_console, _expected_has_console, "HAS CONSOLE"));
+ EXPECT_TRUE(check<bool>(has_file, _expected_has_file, "HAS FILE"));
+ EXPECT_TRUE(check<bool>(has_dlt, _expected_has_dlt, "HAS DLT"));
+ EXPECT_TRUE(check<std::string>(logfile, _expected_logfile, "LOGFILE"));
+ EXPECT_TRUE(check<std::string>(boost::log::trivial::to_string(loglevel),
+ _expected_loglevel, "LOGLEVEL"));
+ EXPECT_TRUE(check<bool>(has_version_logging, _expected_version_logging_enabled,
+ "VERSION LOGGING"));
+ EXPECT_TRUE(check<uint32_t>(version_logging_interval,
+ _expected_version_logging_interval,
+ "VERSION LOGGING INTERVAL"));
+
+ // watchdog
+ EXPECT_TRUE(its_configuration->is_watchdog_enabled());
+ EXPECT_EQ(1234u, its_configuration->get_watchdog_timeout());
+ EXPECT_EQ(7u, its_configuration->get_allowed_missing_pongs());
+
+ // file permissions
+ EXPECT_EQ(0444u, its_configuration->get_permissions_shm());
+ EXPECT_EQ(0222u, its_configuration->get_umask());
+
+ // selective broadcasts
+ EXPECT_TRUE(its_configuration->supports_selective_broadcasts(
+ boost::asio::ip::address::from_string("160.160.160.160")));
+
+ // tracing
+ std::shared_ptr<vsomeip::cfg::trace> its_trace = its_configuration->get_trace();
+ EXPECT_TRUE(its_trace->is_enabled_);
+ EXPECT_TRUE(its_trace->is_sd_enabled_);
+ EXPECT_EQ(2u, its_trace->channels_.size());
+ EXPECT_EQ(2u, its_trace->filter_rules_.size());
+ for (const auto &c : its_trace->channels_) {
+ EXPECT_TRUE(c->name_ == std::string("testname") || c->name_ == std::string("testname2"));
+ if (c->name_ == std::string("testname")) {
+ EXPECT_EQ(std::string("testid"), c->id_);
+ } else if (c->name_ == std::string("testname2")) {
+ EXPECT_EQ(std::string("testid2"), c->id_);
+ }
+ }
+ for (const auto &f : its_trace->filter_rules_) {
+ EXPECT_TRUE(f->channel_ == std::string("testname") || f->channel_ == std::string("testname2"));
+ if (f->channel_ == std::string("testname")) {
+ EXPECT_EQ(2u, f->services_.size());
+ EXPECT_EQ(2u, f->methods_.size());
+ EXPECT_EQ(2u, f->clients_.size());
+ for (const vsomeip::service_t s : f->services_) {
+ EXPECT_TRUE(s == vsomeip::service_t(0x1111) || s == vsomeip::service_t(2222));
+ }
+ for (const vsomeip::method_t s : f->methods_) {
+ EXPECT_TRUE(s == vsomeip::method_t(0x1111) || s == vsomeip::method_t(2222));
+ }
+ for (const vsomeip::client_t s : f->clients_) {
+ EXPECT_TRUE(s == vsomeip::client_t(0x1111) || s == vsomeip::client_t(2222));
+ }
+ } else if (f->channel_ == std::string("testname2")) {
+ EXPECT_EQ(2u, f->services_.size());
+ EXPECT_EQ(2u, f->methods_.size());
+ EXPECT_EQ(2u, f->clients_.size());
+ for (const vsomeip::service_t s : f->services_) {
+ EXPECT_TRUE(s == vsomeip::service_t(0x3333) || s == vsomeip::service_t(4444));
+ }
+ for (const vsomeip::method_t s : f->methods_) {
+ EXPECT_TRUE(s == vsomeip::method_t(0x3333) || s == vsomeip::method_t(4444));
+ }
+ for (const vsomeip::client_t s : f->clients_) {
+ EXPECT_TRUE(s == vsomeip::client_t(0x3333) || s == vsomeip::client_t(4444));
+ }
+ }
+ }
+
+ // Applications
+ std::size_t max_dispatchers = its_configuration->get_max_dispatchers(
+ EXPECTED_ROUTING_MANAGER_HOST);
+ std::size_t max_dispatch_time = its_configuration->get_max_dispatch_time(
+ EXPECTED_ROUTING_MANAGER_HOST);
+ std::size_t io_threads = its_configuration->get_io_thread_count(
+ EXPECTED_ROUTING_MANAGER_HOST);
+ std::size_t request_time = its_configuration->get_request_debouncing(
+ EXPECTED_ROUTING_MANAGER_HOST);
+
+ EXPECT_TRUE(check<std::size_t>(max_dispatchers,
+ _expected_application_max_dispatcher, "MAX DISPATCHERS"));
+ EXPECT_TRUE(check<std::size_t>(max_dispatch_time,
+ _expected_application_max_dispatch_time, "MAX DISPATCH TIME"));
+ EXPECT_TRUE(check<std::size_t>(io_threads, _expected_application_threads,
+ "IO THREADS"));
+ EXPECT_TRUE(check<std::size_t>(request_time,
+ _expected_application_request_debounce_time, "REQUEST DEBOUNCE TIME"));
+
+ EXPECT_EQ(0x9933, its_configuration->get_id("other_application"));
+
+ std::map<vsomeip::plugin_type_e, std::string> its_plugins =
+ its_configuration->get_plugins(EXPECTED_ROUTING_MANAGER_HOST);
+ EXPECT_EQ(1u, its_plugins.size());
+ for (const auto plugin : its_plugins) {
+ EXPECT_EQ(vsomeip::plugin_type_e::APPLICATION_PLUGIN, plugin.first);
+ EXPECT_EQ(std::string("libtestlibraryname.so."
+ + std::to_string(VSOMEIP_APPLICATION_PLUGIN_VERSION)),
+ plugin.second);
+ }
+ EXPECT_EQ(vsomeip::plugin_type_e::CONFIGURATION_PLUGIN, its_plugin->get_plugin_type());
+ EXPECT_EQ("vsomeip cfg plugin", its_plugin->get_plugin_name());
+ EXPECT_EQ(1u, its_plugin->get_plugin_version());
- check<bool>(has_console, _expected_has_console, "HAS CONSOLE");
- check<bool>(has_file, _expected_has_file, "HAS FILE");
- check<bool>(has_dlt, _expected_has_dlt, "HAS DLT");
- check<std::string>(logfile, _expected_logfile, "LOGFILE");
- check<std::string>(boost::log::trivial::to_string(loglevel),
- _expected_loglevel, "LOGLEVEL");
// 5. Services
std::string its_unicast_address
@@ -158,15 +299,15 @@ void check_file(const std::string &_config_file,
uint16_t its_unreliable_port
= its_configuration->get_unreliable_port(0x1234, 0x0022);
- check<std::string>(its_unicast_address,
+ EXPECT_TRUE(check<std::string>(its_unicast_address,
_expected_unicast_address_1234_0022,
- "UNICAST_ADDRESS_1234_0022");
- check<uint16_t>(its_reliable_port,
+ "UNICAST_ADDRESS_1234_0022"));
+ EXPECT_TRUE(check<uint16_t>(its_reliable_port,
_expected_reliable_port_1234_0022,
- "RELIABLE_PORT_1234_0022");
- check<uint16_t>(its_unreliable_port,
+ "RELIABLE_PORT_1234_0022"));
+ EXPECT_TRUE(check<uint16_t>(its_unreliable_port,
_expected_unreliable_port_1234_0022,
- "UNRELIABLE_PORT_1234_0022");
+ "UNRELIABLE_PORT_1234_0022"));
its_unicast_address
= its_configuration->get_unicast_address(0x1234, 0x0023);
@@ -175,15 +316,15 @@ void check_file(const std::string &_config_file,
its_unreliable_port
= its_configuration->get_unreliable_port(0x1234, 0x0023);
- check<std::string>(its_unicast_address,
+ EXPECT_TRUE(check<std::string>(its_unicast_address,
_expected_unicast_address_1234_0023,
- "UNICAST_ADDRESS_1234_0023");
- check<uint16_t>(its_reliable_port,
+ "UNICAST_ADDRESS_1234_0023"));
+ EXPECT_TRUE(check<uint16_t>(its_reliable_port,
_expected_reliable_port_1234_0023,
- "RELIABLE_PORT_1234_0023");
- check<uint16_t>(its_unreliable_port,
+ "RELIABLE_PORT_1234_0023"));
+ EXPECT_TRUE(check<uint16_t>(its_unreliable_port,
_expected_unreliable_port_1234_0023,
- "UNRELIABLE_PORT_1234_0023");
+ "UNRELIABLE_PORT_1234_0023"));
its_unicast_address
= its_configuration->get_unicast_address(0x2277, 0x0022);
@@ -192,15 +333,15 @@ void check_file(const std::string &_config_file,
its_unreliable_port
= its_configuration->get_unreliable_port(0x2277, 0x0022);
- check<std::string>(its_unicast_address,
+ EXPECT_TRUE(check<std::string>(its_unicast_address,
_expected_unicast_address_2277_0022,
- "UNICAST_ADDRESS_2277_0022");
- check<uint16_t>(its_reliable_port,
+ "UNICAST_ADDRESS_2277_0022"));
+ EXPECT_TRUE(check<uint16_t>(its_reliable_port,
_expected_reliable_port_2277_0022,
- "RELIABLE_PORT_2277_0022");
- check<uint16_t>(its_unreliable_port,
+ "RELIABLE_PORT_2277_0022"));
+ EXPECT_TRUE(check<uint16_t>(its_unreliable_port,
_expected_unreliable_port_2277_0022,
- "UNRELIABLE_PORT_2277_0022");
+ "UNRELIABLE_PORT_2277_0022"));
its_unicast_address
= its_configuration->get_unicast_address(0x2266, 0x0022);
@@ -209,15 +350,15 @@ void check_file(const std::string &_config_file,
its_unreliable_port
= its_configuration->get_unreliable_port(0x2266, 0x0022);
- check<std::string>(its_unicast_address,
+ EXPECT_TRUE(check<std::string>(its_unicast_address,
_expected_unicast_address_2266_0022,
- "UNICAST_ADDRESS_2266_0022");
- check<uint16_t>(its_reliable_port,
+ "UNICAST_ADDRESS_2266_0022"));
+ EXPECT_TRUE(check<uint16_t>(its_reliable_port,
_expected_reliable_port_2266_0022,
- "RELIABLE_PORT_2266_0022");
- check<uint16_t>(its_unreliable_port,
+ "RELIABLE_PORT_2266_0022"));
+ EXPECT_TRUE(check<uint16_t>(its_unreliable_port,
_expected_unreliable_port_2266_0022,
- "UNRELIABLE_PORT_2266_0022");
+ "UNRELIABLE_PORT_2266_0022"));
its_unicast_address
= its_configuration->get_unicast_address(0x4466, 0x0321);
@@ -226,15 +367,74 @@ void check_file(const std::string &_config_file,
its_unreliable_port
= its_configuration->get_unreliable_port(0x4466, 0x0321);
- check<std::string>(its_unicast_address,
+ EXPECT_TRUE(check<std::string>(its_unicast_address,
_expected_unicast_address_4466_0321,
- "UNICAST_ADDRESS_4466_0321");
- check<uint16_t>(its_reliable_port,
+ "UNICAST_ADDRESS_4466_0321"));
+ EXPECT_TRUE(check<uint16_t>(its_reliable_port,
_expected_reliable_port_4466_0321,
- "RELIABLE_PORT_4466_0321");
- check<uint16_t>(its_unreliable_port,
+ "RELIABLE_PORT_4466_0321"));
+ EXPECT_TRUE(check<uint16_t>(its_unreliable_port,
_expected_unreliable_port_4466_0321,
- "UNRELIABLE_PORT_4466_0321");
+ "UNRELIABLE_PORT_4466_0321"));
+
+ std::string its_multicast_address;
+ std::uint16_t its_multicast_port;
+ its_configuration->get_multicast(0x7809, 0x1, 0x1111,
+ its_multicast_address, its_multicast_port);
+ EXPECT_EQ(1234u, its_multicast_port);
+ EXPECT_EQ(std::string("224.212.244.225"), its_multicast_address);
+ EXPECT_EQ(8u, its_configuration->get_threshold(0x7809, 0x1, 0x1111));
+
+ EXPECT_TRUE(its_configuration->is_offered_remote(0x1234,0x0022));
+ EXPECT_FALSE(its_configuration->is_offered_remote(0x3333,0x1));
+
+ EXPECT_TRUE(its_configuration->has_enabled_magic_cookies("10.0.2.15", 30506));
+ EXPECT_FALSE(its_configuration->has_enabled_magic_cookies("10.0.2.15", 30503));
+
+ std::set<std::pair<vsomeip::service_t, vsomeip::instance_t>> its_remote_services =
+ its_configuration->get_remote_services();
+ EXPECT_EQ(1u, its_remote_services.size());
+ for (const auto &p : its_remote_services) {
+ EXPECT_EQ(0x4466, p.first);
+ EXPECT_EQ(0x321, p.second);
+ }
+
+ EXPECT_TRUE(its_configuration->is_someip(0x3333,0x1));
+ EXPECT_FALSE(its_configuration->is_someip(0x3555,0x1));
+
+ // Internal services
+ EXPECT_TRUE(its_configuration->is_local_service(0x1234, 0x0022));
+ EXPECT_TRUE(its_configuration->is_local_service(0x3333,0x1));
+ // defined range, service level only
+ EXPECT_FALSE(its_configuration->is_local_service(0xF0FF,0x1));
+ EXPECT_TRUE(its_configuration->is_local_service(0xF100,0x1));
+ EXPECT_TRUE(its_configuration->is_local_service(0xF101,0x23));
+ EXPECT_TRUE(its_configuration->is_local_service(0xF109,0xFFFF));
+ EXPECT_FALSE(its_configuration->is_local_service(0xF10a,0x1));
+ // defined range, service and instance level
+ EXPECT_FALSE(its_configuration->is_local_service(0xF2FF,0xFFFF));
+ EXPECT_TRUE(its_configuration->is_local_service(0xF300,0x1));
+ EXPECT_TRUE(its_configuration->is_local_service(0xF300,0x5));
+ EXPECT_TRUE(its_configuration->is_local_service(0xF300,0x10));
+ EXPECT_FALSE(its_configuration->is_local_service(0xF300,0x11));
+ EXPECT_FALSE(its_configuration->is_local_service(0xF301,0x11));
+
+ // clients
+ std::map<bool, std::set<uint16_t>> used_ports;
+ used_ports[true].insert(0x11);
+ used_ports[false].insert(0x10);
+ std::uint16_t port_to_use(0x0);
+ EXPECT_TRUE(its_configuration->get_client_port(0x8888, 0x1, true, used_ports, port_to_use));
+ EXPECT_EQ(0x10, port_to_use);
+ EXPECT_TRUE(its_configuration->get_client_port(0x8888, 0x1, false, used_ports, port_to_use));
+ EXPECT_EQ(0x11, port_to_use);
+
+ used_ports[true].insert(0x10);
+ used_ports[false].insert(0x11);
+ EXPECT_FALSE(its_configuration->get_client_port(0x8888, 0x1, true, used_ports, port_to_use));
+ EXPECT_EQ(vsomeip::ILLEGAL_PORT, port_to_use);
+ EXPECT_FALSE(its_configuration->get_client_port(0x8888, 0x1, false, used_ports, port_to_use));
+ EXPECT_EQ(vsomeip::ILLEGAL_PORT, port_to_use);
// payload sizes
// use 17000 instead of 1500 as configured max-local-payload size will be
@@ -243,11 +443,42 @@ void check_file(const std::string &_config_file,
17000u + 16u + + VSOMEIP_COMMAND_HEADER_SIZE
+ sizeof(vsomeip::instance_t) + sizeof(bool) + sizeof(bool)
+ sizeof(vsomeip::client_t));
- check<std::uint32_t>(max_local_message_size, its_configuration->get_max_message_size_local(), "max-local-message-size");
- check<std::uint32_t>(11u, its_configuration->get_buffer_shrink_threshold(), "buffer shrink threshold");
- check<std::uint32_t>(14999u + 16u, its_configuration->get_max_message_size_reliable("10.10.10.10", 7777), "max-message-size-reliable1");
- check<std::uint32_t>(17000u + 16, its_configuration->get_max_message_size_reliable("11.11.11.11", 4711), "max-message-size-reliable2");
- check<std::uint32_t>(15001u + 16, its_configuration->get_max_message_size_reliable("10.10.10.11", 7778), "max-message-size-reliable3");
+ EXPECT_EQ(max_local_message_size, its_configuration->get_max_message_size_local());
+ EXPECT_EQ(11u, its_configuration->get_buffer_shrink_threshold());
+ EXPECT_EQ(14999u + 16u, its_configuration->get_max_message_size_reliable("10.10.10.10", 7777));
+ EXPECT_EQ(17000u + 16, its_configuration->get_max_message_size_reliable("11.11.11.11", 4711));
+ EXPECT_EQ(15001u + 16, its_configuration->get_max_message_size_reliable("10.10.10.11", 7778));
+
+ // security
+ EXPECT_TRUE(its_configuration->is_security_enabled());
+ EXPECT_TRUE(its_configuration->is_offer_allowed(0x1277, 0x1234, 0x5678));
+ EXPECT_FALSE(its_configuration->is_offer_allowed(0x1277, 0x1234, 0x5679));
+ EXPECT_FALSE(its_configuration->is_offer_allowed(0x1277, 0x1233, 0x5679));
+ EXPECT_FALSE(its_configuration->is_offer_allowed(0x1266, 0x1233, 0x5679));
+ // explicitly denied offers
+ EXPECT_FALSE(its_configuration->is_offer_allowed(0x1443, 0x1234, 0x5678));
+ EXPECT_FALSE(its_configuration->is_offer_allowed(0x1443, 0x1235, 0x5678));
+ EXPECT_TRUE(its_configuration->is_offer_allowed(0x1443, 0x1234, 0x5679));
+ EXPECT_TRUE(its_configuration->is_offer_allowed(0x1443, 0x1300, 0x1));
+ EXPECT_TRUE(its_configuration->is_offer_allowed(0x1443, 0x1300, 0x2));
+
+ EXPECT_TRUE(its_configuration->is_client_allowed(0x1343, 0x1234, 0x5678));
+ EXPECT_TRUE(its_configuration->is_client_allowed(0x1346, 0x1234, 0x5678));
+ EXPECT_FALSE(its_configuration->is_client_allowed(0x1347, 0x1234, 0x5678));
+ EXPECT_FALSE(its_configuration->is_client_allowed(0x1342, 0x1234, 0x5678));
+ EXPECT_FALSE(its_configuration->is_client_allowed(0x1343, 0x1234, 0x5679));
+ EXPECT_FALSE(its_configuration->is_client_allowed(0x1343, 0x1230, 0x5678));
+ // explicitly denied requests
+ EXPECT_FALSE(its_configuration->is_client_allowed(0x1443, 0x1234, 0x5678));
+ EXPECT_FALSE(its_configuration->is_client_allowed(0x1446, 0x1234, 0x5678));
+ EXPECT_TRUE(its_configuration->is_client_allowed(0x1443, 0x1234, 0x5679));
+ EXPECT_TRUE(its_configuration->is_client_allowed(0x1443, 0x1234, 0x5679));
+ EXPECT_FALSE(its_configuration->is_client_allowed(0x1442, 0x1234, 0x5678));
+ EXPECT_FALSE(its_configuration->is_client_allowed(0x1447, 0x1234, 0x5678));
+
+ EXPECT_TRUE(its_configuration->check_credentials(0x1277, 1000, 1000));
+ EXPECT_FALSE(its_configuration->check_credentials(0x1277, 1001, 1001));
+ EXPECT_FALSE(its_configuration->check_credentials(0x1278, 1000, 1000));
// 6. Service discovery
bool enabled = its_configuration->is_sd_enabled();
@@ -263,32 +494,36 @@ void check_file(const std::string &_config_file,
int32_t cyclic_offer_delay = its_configuration->get_sd_cyclic_offer_delay();
int32_t request_response_delay = its_configuration->get_sd_request_response_delay();
- check<bool>(enabled, _expected_enabled, "SD ENABLED");
- check<std::string>(protocol, _expected_protocol, "SD PROTOCOL");
- check<std::string>(multicast, _expected_multicast, "SD MULTICAST");
- check<uint16_t>(port, _expected_port, "SD PORT");
-
- check<int32_t>(initial_delay_min, _expected_initial_delay_min, "SD INITIAL DELAY MIN");
- check<int32_t>(initial_delay_max, _expected_initial_delay_max, "SD INITIAL DELAY MAX");
- check<int32_t>(repetitions_base_delay, _expected_repetitions_base_delay, "SD REPETITION BASE DELAY");
- check<uint8_t>(repetitions_max,_expected_repetitions_max, "SD REPETITION MAX");
- check<vsomeip::ttl_t>(ttl, _expected_ttl, "SD TTL");
- check<int32_t>(cyclic_offer_delay, _expected_cyclic_offer_delay, "SD CYCLIC OFFER DELAY");
- check<int32_t>(request_response_delay, _expected_request_response_delay, "SD RESPONSE REQUEST DELAY");
+ EXPECT_TRUE(check<bool>(enabled, _expected_enabled, "SD ENABLED"));
+ EXPECT_TRUE(check<std::string>(protocol, _expected_protocol, "SD PROTOCOL"));
+ EXPECT_TRUE(check<std::string>(multicast, _expected_multicast, "SD MULTICAST"));
+ EXPECT_TRUE(check<uint16_t>(port, _expected_port, "SD PORT"));
+
+ EXPECT_TRUE(check<int32_t>(initial_delay_min, _expected_initial_delay_min, "SD INITIAL DELAY MIN"));
+ EXPECT_TRUE(check<int32_t>(initial_delay_max, _expected_initial_delay_max, "SD INITIAL DELAY MAX"));
+ EXPECT_TRUE(check<int32_t>(repetitions_base_delay, _expected_repetitions_base_delay, "SD REPETITION BASE DELAY"));
+ EXPECT_TRUE(check<uint8_t>(repetitions_max,_expected_repetitions_max, "SD REPETITION MAX"));
+ EXPECT_TRUE(check<vsomeip::ttl_t>(ttl, _expected_ttl, "SD TTL"));
+ EXPECT_TRUE(check<int32_t>(cyclic_offer_delay, _expected_cyclic_offer_delay, "SD CYCLIC OFFER DELAY"));
+ EXPECT_TRUE(check<int32_t>(request_response_delay, _expected_request_response_delay, "SD RESPONSE REQUEST DELAY"));
+ EXPECT_EQ(1000u, its_configuration->get_sd_offer_debounce_time());
+
+ ASSERT_TRUE(vsomeip::plugin_manager::get()->unload_plugin(vsomeip::plugin_type_e::CONFIGURATION_PLUGIN));
}
-
-
-int main() {
+TEST(configuration_test, check_config_file) {
// Check current configuration file format
- std::cout << "/////////////////////////////////" << std::endl
- << "// CHECKING CONFIGURATION FILE //" << std::endl
- << "/////////////////////////////////" << std::endl;
check_file(CONFIGURATION_FILE,
EXPECTED_UNICAST_ADDRESS,
EXPECTED_HAS_CONSOLE,
EXPECTED_HAS_FILE,
EXPECTED_HAS_DLT,
+ EXPECTED_VERSION_LOGGING_ENABLED,
+ EXPECTED_VERSION_LOGGING_INTERVAL,
+ EXPECTED_APPLICATION_MAX_DISPATCHERS,
+ EXPECTED_APPLICATION_MAX_DISPATCH_TIME,
+ EXPECTED_APPLICATION_THREADS,
+ EXPECTED_APPLICATION_REQUEST_DEBOUNCE_TIME,
EXPECTED_LOGFILE,
EXPECTED_LOGLEVEL,
EXPECTED_UNICAST_ADDRESS_1234_0022,
@@ -317,16 +552,21 @@ int main() {
EXPECTED_TTL,
EXPECTED_CYCLIC_OFFER_DELAY,
EXPECTED_REQUEST_RESPONSE_DELAY);
+}
+TEST(configuration_test, check_deprecated_config_file) {
// Check deprecated configuration file format
- std::cout << "////////////////////////////////////////////" << std::endl
- << "// CHECKING DEPRECATED CONFIGURATION FILE //" << std::endl
- << "////////////////////////////////////////////" << std::endl;
check_file(DEPRECATED_CONFIGURATION_FILE,
EXPECTED_UNICAST_ADDRESS,
EXPECTED_HAS_CONSOLE,
EXPECTED_HAS_FILE,
EXPECTED_HAS_DLT,
+ EXPECTED_VERSION_LOGGING_ENABLED,
+ EXPECTED_VERSION_LOGGING_INTERVAL,
+ EXPECTED_APPLICATION_MAX_DISPATCHERS,
+ EXPECTED_APPLICATION_MAX_DISPATCH_TIME,
+ EXPECTED_APPLICATION_THREADS,
+ EXPECTED_APPLICATION_REQUEST_DEBOUNCE_TIME,
EXPECTED_LOGFILE,
EXPECTED_LOGLEVEL,
EXPECTED_UNICAST_ADDRESS_1234_0022,
@@ -355,9 +595,9 @@ int main() {
EXPECTED_DEPRECATED_TTL,
EXPECTED_CYCLIC_OFFER_DELAY,
EXPECTED_DEPRECATED_REQUEST_RESPONSE_DELAY);
-
- return 0;
}
-
-
+int main(int argc, char** argv) {
+ ::testing::InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
+}
diff --git a/test/configuration_tests/configuration-test.json b/test/configuration_tests/configuration-test.json
index afa3c41..1509ad4 100644
--- a/test/configuration_tests/configuration-test.json
+++ b/test/configuration_tests/configuration-test.json
@@ -1,21 +1,88 @@
{
"unicast" : "10.0.2.15",
+ "diagnosis" : "0x55",
"logging" :
{
"level" : "debug",
"console" : "true",
"file" : { "enable" : "true", "path" : "/home/someip/another-file.log" },
- "dlt" : "false"
+ "dlt" : "false",
+ "version" : {
+ "enable" : "false",
+ "interval" : "15"
+ }
+ },
+ "watchdog" :
+ {
+ "enable" : "true",
+ "timeout" : "1234",
+ "allowed_missing_pongs" : "7"
+ },
+ "file-permissions" :
+ {
+ "permissions-shm" : "0444",
+ "umask" : "0222"
+ },
+ "supports_selective_broadcasts" :
+ {
+ "address" : "160.160.160.160"
+ },
+ "tracing" :
+ {
+ "enable" : "true",
+ "sd_enable" : "true",
+ "channels" :
+ [
+ {
+ "name" : "testname",
+ "id" : "testid"
+ },
+ {
+ "name" : "testname2",
+ "id" : "testid2"
+ }
+ ],
+ "filters" :
+ [
+ {
+ "channel" : "testname",
+ "services" : ["0x1111",2222],
+ "methods" : ["0x1111",2222],
+ "clients" : ["0x1111",2222]
+ },
+ {
+ "channel" : "testname2",
+ "services" : ["0x3333",4444],
+ "methods" : ["0x3333",4444],
+ "clients" : ["0x3333",4444]
+ }
+ ]
},
"applications" :
[
{
"name" : "my_application",
- "id" : "0x7788"
+ "id" : "0x7788",
+ "max_dispatchers" : "25",
+ "max_dispatch_time" : "1234",
+ "threads" : "12",
+ "request_debounce_time" : "5000",
+ "plugins" :
+ [
+ {
+ "application_plugin" : "testlibraryname"
+ },
+ {
+ "intentionally_wrong_plugin" : "wrong"
+ }
+ ]
},
{
"name" : "other_application",
- "id" : "0x9933"
+ "id" : "0x9933",
+ "threads" : "0",
+ "threads" : "256",
+ "request_debounce_time" : "10001"
}
],
"services" :
@@ -24,7 +91,7 @@
"service" : "0x1234",
"instance" : "0x0022",
"unicast" : "local",
- "reliable" : { "port" : "30506", "magic_cookies" : "false" },
+ "reliable" : { "port" : "30506", "enable-magic-cookies" : "true" },
"unreliable" : "31000",
"events" :
[
@@ -83,6 +150,65 @@
"unicast" : "10.0.2.23",
"reliable" : "30506",
"unreliable" : "30444"
+ },
+ {
+ "service" : "0x3333",
+ "instance" : "0x1"
+ },
+ {
+ "service" : "0x7809",
+ "instance" : "0x1",
+ "multicast" :
+ {
+ "address" : "224.212.244.225",
+ "port" : "1234"
+ },
+ "eventgroups" :
+ [
+ {
+ "eventgroup" : "0x1111",
+ "threshold" : "8",
+ "is_multicast" : "true",
+ "events" : [ "0x778", "0x77A" ]
+ }
+ ]
+ },
+ {
+ "service" : "0x3555",
+ "instance" : "0x1",
+ "protocol" : "other"
+ }
+ ],
+ "internal_services" :
+ [
+ {
+ "first" : "0xF100",
+ "last" : "0xF109"
+ },
+ {
+ "first" : {
+ "service" : "0xF300",
+ "instance" : "0x1"
+ },
+ "last" : {
+ "service" : "0xF300",
+ "instance" : "0x10"
+ }
+ }
+ ],
+ "clients" :
+ [
+ {
+ "service" : "0x8888",
+ "instance" : "0x1",
+ "unreliable" : [ "0x11", "0x10" ],
+ "reliable" : [ "0x11", "0x10" ]
+ },
+ {
+ "service" : "8888",
+ "instance" : "1",
+ "unreliable" : [ 40000, 40001 ],
+ "reliable" : [ 40000, 40001 ]
}
],
"max-payload-size-local" : "15000",
@@ -111,6 +237,68 @@
]
}
],
+ "security" :
+ {
+ "check_credentials" : "true",
+ "policies" :
+ [
+ {
+ "client" : "0x1277",
+ "credentials" : { "uid" : "1000", "gid" : "1000" },
+ "allow" :
+ {
+ "offers":
+ [
+ {
+ "service" : "0x1234",
+ "instance" : "0x5678"
+ },
+ {
+ "service" : "0x1235",
+ "instance" : "0x5678"
+ }
+ ]
+ }
+ },
+ {
+ "client" : { "first" : "0x1343", "last" : "0x1346" },
+ "allow" :
+ {
+ "requests":
+ [
+ {
+ "service" : "0x1234",
+ "instance" : "0x5678"
+ }
+ ]
+ }
+ },
+ {
+ "client" : { "first" : "0x1443", "last" : "0x1446" },
+ "deny" :
+ {
+ "requests":
+ [
+ {
+ "service" : "0x1234",
+ "instance" : "0x5678"
+ }
+ ],
+ "offers":
+ [
+ {
+ "service" : "0x1234",
+ "instance" : "0x5678"
+ },
+ {
+ "service" : "0x1235",
+ "instance" : "0x5678"
+ }
+ ]
+ }
+ }
+ ]
+ },
"routing" : "my_application",
"service-discovery" :
{
@@ -124,6 +312,7 @@
"repetitions_max" : "4",
"ttl" : "13",
"cyclic_offer_delay" : "2132",
- "request_response_delay" : "1111"
+ "request_response_delay" : "1111",
+ "offer_debounce_time" : "1000"
}
} \ No newline at end of file
diff --git a/test/initial_event_tests/initial_event_test_client.cpp b/test/initial_event_tests/initial_event_test_client.cpp
index 8f843c6..9e1314f 100644
--- a/test/initial_event_tests/initial_event_test_client.cpp
+++ b/test/initial_event_tests/initial_event_test_client.cpp
@@ -197,11 +197,15 @@ public:
case vsomeip::subscription_type_e::SU_RELIABLE:
case vsomeip::subscription_type_e::SU_PREFER_UNRELIABLE:
case vsomeip::subscription_type_e::SU_PREFER_RELIABLE:
- case vsomeip::subscription_type_e::SU_RELIABLE_AND_UNRELIABLE:
if (all_notifications_received()) {
notify = true;
}
break;
+ case vsomeip::subscription_type_e::SU_RELIABLE_AND_UNRELIABLE:
+ if (all_notifications_received_tcp_and_udp()) {
+ notify = true;
+ }
+ break;
}
if(notify && !dont_exit_) {
@@ -222,24 +226,30 @@ public:
if (v.second == initial_event_test::notifications_to_send) {
return true;
} else {
- if (initial_event_strict_checking_) {
- return false;
- } else {
- if (v.second >= initial_event_test::notifications_to_send) {
- VSOMEIP_WARNING
- << "[" << std::setw(4) << std::setfill('0') << std::hex
- << client_number_ << "] "
- << " Received multiple initial events from service/instance: "
- << std::setw(4) << std::setfill('0') << std::hex << v.first.first
- << "."
- << std::setw(4) << std::setfill('0') << std::hex << v.first.second
- << " number of received events: " << v.second
- << ". This is caused by StopSubscribe/Subscribe messages and/or"
- << " service offered via UDP and TCP";
- return true;
- } else {
- return false;
+ if (v.second >= initial_event_test::notifications_to_send) {
+ VSOMEIP_WARNING
+ << "[" << std::setw(4) << std::setfill('0') << std::hex
+ << client_number_ << "] "
+ << " Received multiple initial events from service/instance: "
+ << std::setw(4) << std::setfill('0') << std::hex << v.first.first
+ << "."
+ << std::setw(4) << std::setfill('0') << std::hex << v.first.second
+ << " number of received events: " << v.second
+ << ". This is caused by StopSubscribe/Subscribe messages and/or"
+ << " service offered via UDP and TCP";
+ if (initial_event_strict_checking_) {
+ ADD_FAILURE() << "[" << std::setw(4) << std::setfill('0') << std::hex
+ << client_number_ << "] "
+ << " Received multiple initial events from service/instance: "
+ << std::setw(4) << std::setfill('0') << std::hex << v.first.first
+ << "."
+ << std::setw(4) << std::setfill('0') << std::hex << v.first.second
+ << " number of received events: " << v.second;
}
+ return initial_event_strict_checking_ ? false : true;
+
+ } else {
+ return false;
}
}
}
@@ -262,6 +272,15 @@ public:
<< ". This is caused by StopSubscribe/Subscribe messages and/or"
<< " service offered via UDP and TCP";
received_twice++;
+ } else if (initial_event_strict_checking_ &&
+ v.second > initial_event_test::notifications_to_send * 2) {
+ ADD_FAILURE() << "[" << std::setw(4) << std::setfill('0') << std::hex
+ << client_number_ << "] "
+ << " Received multiple initial events from service/instance: "
+ << std::setw(4) << std::setfill('0') << std::hex << v.first.first
+ << "."
+ << std::setw(4) << std::setfill('0') << std::hex << v.first.second
+ << " number of received events: " << v.second;
} else if (v.second == initial_event_test::notifications_to_send * 2) {
received_twice++;
} else if(v.second == initial_event_test::notifications_to_send) {
@@ -280,6 +299,11 @@ public:
<< " Normal: " << received_normal
<< " Twice: " << received_twice;
return true;
+ } else if (initial_event_strict_checking_ && (
+ received_twice > ((service_infos_.size() - 1) * events_to_subscribe_)/ 2)) {
+ ADD_FAILURE() << "[" << std::setw(4) << std::setfill('0') << std::hex
+ << client_number_ << "] "
+ << " Received too much initial events twice: " << received_twice;
}
return false;
}
diff --git a/test/readme.txt b/test/readme.txt
index 6b191d5..9f7985a 100644
--- a/test/readme.txt
+++ b/test/readme.txt
@@ -374,6 +374,12 @@ There are multiple versions of this test which differ in the used subscription
method and port setup (use ctest -N to see all). For manual start the desired
description method has to be passed to the starter script as first parameter.
+The subscribe_notify_test_one_event_two_eventgroups_* tests are testing the
+requirement that for events which are member of multiple eventgroups initial
+events shall be sent per eventgroup. However normal updates of the event should
+be sent only once even if a remote subscriber is subscribed to multiple of the
+event's eventgroups (TR_SOMEIP_00570).
+
CPU load test
-------------
diff --git a/test/subscribe_notify_one_tests/subscribe_notify_one_test_service.cpp b/test/subscribe_notify_one_tests/subscribe_notify_one_test_service.cpp
index 9849613..b035b96 100644
--- a/test/subscribe_notify_one_tests/subscribe_notify_one_test_service.cpp
+++ b/test/subscribe_notify_one_tests/subscribe_notify_one_test_service.cpp
@@ -12,6 +12,7 @@
#include <map>
#include <algorithm>
#include <unordered_set>
+#include <atomic>
#include <gtest/gtest.h>
@@ -35,7 +36,9 @@ public:
wait_for_stop_(true),
stop_thread_(std::bind(&subscribe_notify_one_test_service::wait_for_stop, this)),
wait_for_notify_(true),
- notify_thread_(std::bind(&subscribe_notify_one_test_service::notify_one, this)) {
+ notify_thread_(std::bind(&subscribe_notify_one_test_service::notify_one, this)),
+ subscription_state_handler_called_(0),
+ subscription_error_occured_(false) {
if (!app_->init()) {
ADD_FAILURE() << "Couldn't initialize application";
return;
@@ -80,6 +83,14 @@ public:
app_->request_service(i.service_id, i.instance_id, vsomeip::DEFAULT_MAJOR, vsomeip::DEFAULT_MINOR, true);
+ auto handler = std::bind(&subscribe_notify_one_test_service::on_subscription_state_change, this,
+ std::placeholders::_1, std::placeholders::_2,
+ std::placeholders::_3, std::placeholders::_4, std::placeholders::_5);
+ app_->register_subscription_status_handler(i.service_id, i.instance_id, i.eventgroup_id, vsomeip::ANY_EVENT, handler);
+ app_->register_subscription_status_handler(vsomeip::ANY_SERVICE, i.instance_id, i.eventgroup_id, vsomeip::ANY_EVENT, handler);
+ app_->register_subscription_status_handler(i.service_id, vsomeip::ANY_INSTANCE, i.eventgroup_id, vsomeip::ANY_EVENT, handler);
+ app_->register_subscription_status_handler(vsomeip::ANY_SERVICE, vsomeip::ANY_INSTANCE, i.eventgroup_id, vsomeip::ANY_EVENT, handler);
+
std::set<vsomeip::eventgroup_t> its_eventgroups;
its_eventgroups.insert(i.eventgroup_id);
app_->request_event(i.service_id, i.instance_id, i.event_id, its_eventgroups, false);
@@ -143,6 +154,22 @@ public:
}
}
+ void on_subscription_state_change(const vsomeip::service_t _service, const vsomeip::instance_t _instance,
+ const vsomeip::eventgroup_t _eventgroup, const vsomeip::event_t _event, const uint16_t _error) {
+ (void)_service;
+ (void)_instance;
+ (void)_eventgroup;
+ (void)_event;
+ if (!_error) {
+ subscription_state_handler_called_++;
+ } else {
+ subscription_error_occured_ = true;
+ VSOMEIP_WARNING << std::hex << app_->get_client()
+ << " : on_subscription_state_change: for service " << std::hex
+ << _service << " received a subscription error!";
+ }
+ }
+
bool on_subscription(vsomeip::client_t _client, bool _subscribed) {
// check if all other services have subscribed:
// -1 for placeholder in array and -1 for the service itself
@@ -285,6 +312,7 @@ public:
VSOMEIP_DEBUG << "[" << std::setw(4) << std::setfill('0') << std::hex
<< service_info_.service_id << "] Subscribing";
// subscribe to events of other services
+ uint32_t subscribe_count = 0;
for(const subscribe_notify_one_test::service_info& i: subscribe_notify_one_test::service_infos) {
if ((i.service_id == service_info_.service_id
&& i.instance_id == service_info_.instance_id)
@@ -292,6 +320,7 @@ public:
continue;
}
+ ++subscribe_count;
app_->subscribe(i.service_id, i.instance_id, i.eventgroup_id,
vsomeip::DEFAULT_MAJOR, subscription_type_);
@@ -306,6 +335,19 @@ public:
while (wait_until_notified_from_other_services_) {
condition_.wait(its_lock);
}
+
+ // It is possible that we run in the case a subscription is NACKED
+ // due to TCP endpoint not completely connected when subscription
+ // is processed in the server - due to resubscribing the error handler
+ // count may differ from expected value, but its not a real but as
+ // the subscription takes places anyways and all events will be received.
+ if (!subscription_error_occured_) {
+ // 4 * subscribe count cause we installed three additional wild-card handlers
+ ASSERT_EQ(subscribe_count * 4, subscription_state_handler_called_);
+ } else {
+ VSOMEIP_WARNING << "Subscription state handler check skipped: CallCount="
+ << std::dec << subscription_state_handler_called_;
+ }
}
void notify_one() {
@@ -363,12 +405,32 @@ public:
wait_until_notified_from_other_services_ = false;
condition_.notify_one();
}
+
+ stop_offer();
+
+ // ensure that the service which hosts the routing doesn't exit to early
+ if (app_->is_routing()) {
+ for (const auto& i : subscribe_notify_one_test::service_infos) {
+ if ((i.service_id == service_info_.service_id
+ && i.instance_id == service_info_.instance_id)
+ || (i.service_id == 0xFFFF && i.instance_id == 0xFFFF)) {
+ continue;
+ }
+ while (app_->is_available(i.service_id, i.instance_id,
+ vsomeip::ANY_MAJOR, vsomeip::ANY_MINOR)) {
+ std::this_thread::sleep_for(std::chrono::milliseconds(100));
+ }
+ }
+ }
+
for(const auto& i : subscribe_notify_one_test::service_infos) {
if ((i.service_id == service_info_.service_id
&& i.instance_id == service_info_.instance_id)
|| (i.service_id == 0xFFFF && i.instance_id == 0xFFFF)) {
continue;
}
+ app_->register_subscription_status_handler(i.service_id, i.instance_id,
+ i.eventgroup_id, vsomeip::ANY_EVENT, nullptr);
app_->unsubscribe(i.service_id, i.instance_id, i.eventgroup_id);
app_->release_event(i.service_id, i.instance_id, i.event_id);
app_->release_service(i.service_id, i.instance_id);
@@ -403,6 +465,8 @@ private:
std::thread notify_thread_;
std::unordered_set<vsomeip::client_t> subscribers_;
+ std::atomic<uint32_t> subscription_state_handler_called_;
+ std::atomic<bool> subscription_error_occured_;
};
static int service_number;
diff --git a/test/subscribe_notify_tests/conf/subscribe_notify_test_one_event_two_eventgroups_master.json.in b/test/subscribe_notify_tests/conf/subscribe_notify_test_one_event_two_eventgroups_master.json.in
new file mode 100644
index 0000000..0b0051a
--- /dev/null
+++ b/test/subscribe_notify_tests/conf/subscribe_notify_test_one_event_two_eventgroups_master.json.in
@@ -0,0 +1,31 @@
+{
+ "unicast" : "@TEST_IP_MASTER@",
+ "logging" :
+ {
+ "level" : "debug",
+ "console" : "true",
+ "file" : { "enable" : "false", "path" : "/var/log/vsomeip.log" },
+ "dlt" : "false"
+ },
+ "applications" :
+ [
+ {
+ "name" : "subscribe_notify_test_client",
+ "id" : "0x9999"
+ }
+ ],
+ "routing" : "vsomeipd",
+ "service-discovery" :
+ {
+ "enable":"true",
+ "multicast":"224.0.0.1",
+ "port":"30490",
+ "protocol":"udp",
+ "initial_delay_min" : "10",
+ "initial_delay_max" : "10",
+ "repetitions_base_delay" : "30",
+ "repetitions_max" : "0",
+ "cyclic_offer_delay" : "1000",
+ "ttl" : "3"
+ }
+}
diff --git a/test/subscribe_notify_tests/conf/subscribe_notify_test_one_event_two_eventgroups_tcp_slave.json.in b/test/subscribe_notify_tests/conf/subscribe_notify_test_one_event_two_eventgroups_tcp_slave.json.in
new file mode 100644
index 0000000..558a873
--- /dev/null
+++ b/test/subscribe_notify_tests/conf/subscribe_notify_test_one_event_two_eventgroups_tcp_slave.json.in
@@ -0,0 +1,39 @@
+{
+ "unicast" : "@TEST_IP_SLAVE@",
+ "logging" :
+ {
+ "level" : "debug",
+ "console" : "true",
+ "file" : { "enable" : "false", "path" : "/tmp/vsomeip.log" },
+ "dlt" : "false"
+ },
+ "applications" :
+ [
+ {
+ "name" : "subscribe_notify_test_service",
+ "id" : "0x8888"
+ }
+ ],
+ "services" :
+ [
+ {
+ "service" : "0xcafe",
+ "instance" : "0x1",
+ "reliable" : { "port":"30509", "enable-magic-cookies":"false" }
+ }
+ ],
+ "routing" : "vsomeipd",
+ "service-discovery" :
+ {
+ "enable":"true",
+ "multicast":"224.0.0.1",
+ "port":"30490",
+ "protocol":"udp",
+ "initial_delay_min" : "10",
+ "initial_delay_max" : "10",
+ "repetitions_base_delay" : "30",
+ "repetitions_max" : "0",
+ "cyclic_offer_delay" : "1000",
+ "ttl" : "3"
+ }
+}
diff --git a/test/subscribe_notify_tests/conf/subscribe_notify_test_one_event_two_eventgroups_udp_slave.json.in b/test/subscribe_notify_tests/conf/subscribe_notify_test_one_event_two_eventgroups_udp_slave.json.in
new file mode 100644
index 0000000..1828a7a
--- /dev/null
+++ b/test/subscribe_notify_tests/conf/subscribe_notify_test_one_event_two_eventgroups_udp_slave.json.in
@@ -0,0 +1,39 @@
+{
+ "unicast" : "@TEST_IP_SLAVE@",
+ "logging" :
+ {
+ "level" : "debug",
+ "console" : "true",
+ "file" : { "enable" : "false", "path" : "/tmp/vsomeip.log" },
+ "dlt" : "false"
+ },
+ "applications" :
+ [
+ {
+ "name" : "subscribe_notify_test_service",
+ "id" : "0x8888"
+ }
+ ],
+ "services" :
+ [
+ {
+ "service" : "0xcafe",
+ "instance" : "0x1",
+ "unreliable" : "30509"
+ }
+ ],
+ "routing" : "vsomeipd",
+ "service-discovery" :
+ {
+ "enable":"true",
+ "multicast":"224.0.0.1",
+ "port":"30490",
+ "protocol":"udp",
+ "initial_delay_min" : "10",
+ "initial_delay_max" : "10",
+ "repetitions_base_delay" : "30",
+ "repetitions_max" : "0",
+ "cyclic_offer_delay" : "1000",
+ "ttl" : "3"
+ }
+}
diff --git a/test/subscribe_notify_tests/subscribe_notify_test_globals.hpp b/test/subscribe_notify_tests/subscribe_notify_test_globals.hpp
index ed41314..761c3c4 100644
--- a/test/subscribe_notify_tests/subscribe_notify_test_globals.hpp
+++ b/test/subscribe_notify_tests/subscribe_notify_test_globals.hpp
@@ -43,6 +43,13 @@ static constexpr std::array<service_info, 7> service_infos_same_service_id = {{
}};
static constexpr int notifications_to_send = 10;
+
+// one_event_two_eventgroups globals
+static constexpr struct service_info service_info_subscriber_based_notification =
+ { 0xCAFE, 0x1, 0x8888, 0x8111, 0x1};
+static constexpr vsomeip::method_t shutdown_method_id = 0x6666;
+static constexpr vsomeip::method_t set_method_id = 0x7777;
+
}
#endif /* SUBSCRIBE_NOTIFY_TEST_GLOBALS_HPP_ */
diff --git a/test/subscribe_notify_tests/subscribe_notify_test_one_event_two_eventgroups_client.cpp b/test/subscribe_notify_tests/subscribe_notify_test_one_event_two_eventgroups_client.cpp
new file mode 100644
index 0000000..eaec6be
--- /dev/null
+++ b/test/subscribe_notify_tests/subscribe_notify_test_one_event_two_eventgroups_client.cpp
@@ -0,0 +1,370 @@
+// 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 VSOMEIP_ENABLE_SIGNAL_HANDLING
+#include <csignal>
+#endif
+#include <chrono>
+#include <condition_variable>
+#include <iomanip>
+#include <iostream>
+#include <sstream>
+#include <thread>
+#include <utility>
+
+#include <vsomeip/vsomeip.hpp>
+#include "../../implementation/logging/include/logger.hpp"
+
+#include <gtest/gtest.h>
+
+#include "subscribe_notify_test_globals.hpp"
+
+class subscribe_notify_test_one_event_two_eventgroups_client {
+public:
+ subscribe_notify_test_one_event_two_eventgroups_client(
+ struct subscribe_notify_test::service_info _info, bool _use_tcp) :
+ app_(
+ vsomeip::runtime::get()->create_application(
+ "subscribe_notify_test_client")),
+ info_(_info),
+ use_tcp_(_use_tcp),
+ wait_availability_(true),
+ wait_set_value_(true),
+ wait_shutdown_response_(true),
+ wait_events_(true),
+ run_thread_(std::bind(&subscribe_notify_test_one_event_two_eventgroups_client::run, this)) {
+ }
+ ~subscribe_notify_test_one_event_two_eventgroups_client() {
+ run_thread_.join();
+ }
+
+ bool init() {
+ if (!app_->init()) {
+ ADD_FAILURE() << "Couldn't initialize application";
+ return false;
+ }
+
+ app_->register_state_handler(
+ std::bind(
+ &subscribe_notify_test_one_event_two_eventgroups_client::on_state,
+ this, std::placeholders::_1));
+
+ app_->register_message_handler(vsomeip::ANY_SERVICE,
+ vsomeip::ANY_INSTANCE, vsomeip::ANY_METHOD,
+ std::bind(
+ &subscribe_notify_test_one_event_two_eventgroups_client::on_message,
+ this, std::placeholders::_1));
+
+ app_->register_availability_handler(info_.service_id, info_.instance_id,
+ std::bind(
+ &subscribe_notify_test_one_event_two_eventgroups_client::on_availability,
+ this, std::placeholders::_1, std::placeholders::_2,
+ std::placeholders::_3));
+
+ std::set<vsomeip::eventgroup_t> its_groups;
+ // the service offers three events in two eventgroups
+ // one of the events is in both eventgroups (info_.event_id + 2)
+ its_groups.insert(info_.eventgroup_id);
+ app_->request_event(info_.service_id, info_.instance_id, info_.event_id, its_groups, true);
+ app_->request_event(info_.service_id, info_.instance_id,
+ static_cast<vsomeip::event_t>(info_.event_id + 2), its_groups, true);
+ its_groups.erase(info_.eventgroup_id);
+ its_groups.insert(static_cast<vsomeip::eventgroup_t>(info_.eventgroup_id +1));
+ app_->request_event(info_.service_id, info_.instance_id,
+ static_cast<vsomeip::event_t>(info_.event_id+1), its_groups, true);
+ app_->request_event(info_.service_id, info_.instance_id,
+ static_cast<vsomeip::event_t>(info_.event_id+2), its_groups, true);
+
+
+
+ return true;
+ }
+
+ void start() {
+ app_->start();
+ }
+
+ void stop() {
+ app_->clear_all_handler();
+ app_->unsubscribe(info_.service_id, info_.instance_id, info_.eventgroup_id);
+ app_->unsubscribe(info_.service_id, info_.instance_id, static_cast<vsomeip::eventgroup_t>(info_.eventgroup_id+1));
+ app_->release_event(info_.service_id, info_.instance_id, info_.event_id);
+ app_->release_event(info_.service_id, info_.instance_id, static_cast<vsomeip::event_t>(info_.event_id+1));
+ app_->release_event(info_.service_id, info_.instance_id, static_cast<vsomeip::event_t>(info_.event_id+2));
+ app_->release_service(info_.service_id, info_.instance_id);
+ app_->stop();
+ }
+
+ void on_state(vsomeip::state_type_e _state) {
+ if (_state == vsomeip::state_type_e::ST_REGISTERED) {
+ app_->request_service(info_.service_id, info_.instance_id);
+ }
+ }
+
+ void on_availability(vsomeip::service_t _service,
+ vsomeip::instance_t _instance,
+ bool _is_available) {
+ VSOMEIP_DEBUG << "Service ["
+ << std::setw(4) << std::setfill('0') << std::hex << _service
+ << "." << _instance << "] is "
+ << (_is_available ? "available." : "NOT available.");
+ if (_service == info_.service_id && _instance == info_.instance_id && _is_available) {
+ std::lock_guard<std::mutex> its_lock(availability_mutex_);
+ wait_availability_ = false;
+ availability_condition_.notify_one();
+ }
+ }
+
+ void on_message(const std::shared_ptr<vsomeip::message> &_response) {
+ std::stringstream its_message;
+ its_message << "Received a message ["
+ << std::setw(4) << std::setfill('0') << std::hex
+ << _response->get_service() << "."
+ << std::setw(4) << std::setfill('0') << std::hex
+ << _response->get_instance() << "."
+ << std::setw(4) << std::setfill('0') << std::hex
+ << _response->get_method() << "] from Client/Session ["
+ << std::setw(4) << std::setfill('0') << std::hex
+ << _response->get_client() << "/"
+ << std::setw(4) << std::setfill('0') << std::hex
+ << _response->get_session()
+ << "] = ";
+ std::shared_ptr<vsomeip::payload> its_payload =
+ _response->get_payload();
+ its_message << "(" << std::dec << its_payload->get_length() << ") ";
+ for (uint32_t i = 0; i < its_payload->get_length(); ++i)
+ its_message << std::hex << std::setw(2) << std::setfill('0')
+ << (int) its_payload->get_data()[i] << " ";
+ VSOMEIP_DEBUG << its_message.str();
+ ASSERT_EQ(info_.service_id, _response->get_service());
+
+ if (_response->get_method() == info_.method_id
+ || _response->get_method() == subscribe_notify_test::shutdown_method_id) {
+ ASSERT_EQ(vsomeip::message_type_e::MT_RESPONSE, _response->get_message_type());
+ ASSERT_EQ(vsomeip::return_code_e::E_OK, _response->get_return_code());
+ std::lock_guard<std::mutex> its_lock(shutdown_response_mutex_);
+ wait_shutdown_response_ = false;
+ shutdown_response_condition_.notify_one();
+ } else if (_response->get_method() == subscribe_notify_test::set_method_id) {
+ std::lock_guard<std::mutex> its_lock(set_value_mutex_);
+ wait_set_value_ = false;
+ set_value_condition_.notify_one();
+ } else if (_response->get_method() >= info_.event_id
+ && _response->get_method() <= static_cast<vsomeip::event_t>(info_.event_id + 3)) {
+ std::lock_guard<std::mutex> its_lock(events_mutex_);
+ received_events_.push_back(_response->get_payload());
+ number_received_events_[_response->get_method()]++;
+ events_condition_.notify_one();
+ } else {
+ ADD_FAILURE() << "Received unknown method id: " << std::setw(4)
+ << std::setfill('0') << std::hex << _response->get_method();
+ }
+
+ }
+
+ void set_field_at_service(vsomeip::byte_t _value) {
+ std::shared_ptr<vsomeip::runtime> its_runtime = vsomeip::runtime::get();
+ std::shared_ptr<vsomeip::message> its_request = its_runtime->create_request(false);
+ its_request->set_service(info_.service_id);
+ its_request->set_instance(info_.instance_id);
+ its_request->set_method(subscribe_notify_test::set_method_id);
+ its_request->set_reliable(use_tcp_);
+ std::shared_ptr<vsomeip::payload> its_payload = its_runtime->create_payload(&_value, sizeof(_value));
+ its_request->set_payload(its_payload);
+ app_->send(its_request);
+ }
+
+ void call_method_at_service(vsomeip::method_t _method) {
+ std::shared_ptr<vsomeip::runtime> its_runtime = vsomeip::runtime::get();
+ std::shared_ptr<vsomeip::message> its_request = its_runtime->create_request(false);
+ its_request->set_service(info_.service_id);
+ its_request->set_instance(info_.instance_id);
+ its_request->set_method(_method);
+ its_request->set_reliable(use_tcp_);
+ app_->send(its_request);
+ }
+
+ void wait_on_condition(std::unique_lock<std::mutex>&& _lock, bool *_predicate, std::condition_variable&& _condition) {
+ while (*_predicate) {
+ _condition.wait(_lock);
+ }
+ *_predicate = true;
+ }
+
+ void subscribe_at_service() {
+ // subscribe to both eventgroups
+ app_->subscribe(info_.service_id, info_.instance_id, info_.eventgroup_id);
+ app_->subscribe(info_.service_id, info_.instance_id, static_cast<vsomeip::eventgroup_t>(info_.eventgroup_id+1));
+ }
+
+ void unsubscribe_at_service() {
+ app_->unsubscribe(info_.service_id, info_.instance_id, info_.eventgroup_id);
+ app_->unsubscribe(info_.service_id, info_.instance_id, static_cast<vsomeip::eventgroup_t>(info_.eventgroup_id+1));
+ }
+
+ void wait_for_events(std::unique_lock<std::mutex>&& _lock,
+ std::uint32_t _expected_number_received_events,
+ std::condition_variable&& _condition) {
+ while (wait_events_ &&
+ received_events_.size() != _expected_number_received_events) {
+ _condition.wait(_lock);
+ }
+ ASSERT_EQ(size_t(_expected_number_received_events), received_events_.size());
+ }
+
+ void check_received_events_payload(vsomeip::byte_t _value) {
+ for (const auto &p : received_events_) {
+ ASSERT_EQ(vsomeip::length_t(1), p->get_length());
+ ASSERT_EQ(vsomeip::byte_t(_value), *p->get_data());
+ }
+ received_events_.clear();
+ }
+
+ void check_received_events_number(std::set<std::pair<vsomeip::event_t, std::uint32_t>> _expected) {
+ for (const auto &e : _expected) {
+ auto event = number_received_events_.find(e.first);
+ ASSERT_NE(number_received_events_.end(), event);
+ ASSERT_EQ(e.second, event->second);
+ }
+ number_received_events_.clear();
+ }
+
+ void run() {
+ std::unique_lock<std::mutex> its_availability_lock(availability_mutex_);
+ wait_on_condition(std::move(its_availability_lock), &wait_availability_, std::move(availability_condition_));
+ // service is available now
+
+ for (int i = 0; i < 3; i++) {
+ // set value
+ set_field_at_service(0x1);
+ std::unique_lock<std::mutex> its_set_value_lock(set_value_mutex_);
+ wait_on_condition(std::move(its_set_value_lock), &wait_set_value_, std::move(set_value_condition_));
+
+ // subscribe
+ std::unique_lock<std::mutex> its_events_lock(events_mutex_);
+ subscribe_at_service();
+ wait_for_events(std::move(its_events_lock), 4, std::move(events_condition_));
+ check_received_events_payload(0x1);
+
+ std::set<std::pair<vsomeip::event_t, std::uint32_t>> its_expected;
+ its_expected.insert({info_.event_id, 1});
+ its_expected.insert({static_cast<vsomeip::event_t>(info_.event_id+1), 1});
+ // Initial event for the event which is member of both eventgroups has to be sent twice
+ its_expected.insert({static_cast<vsomeip::event_t>(info_.event_id+2), 2});
+
+ check_received_events_number(its_expected);
+ its_expected.clear();
+
+ // set value again
+ set_field_at_service(0x2);
+ wait_on_condition(std::move(its_set_value_lock), &wait_set_value_, std::move(set_value_condition_));
+
+ wait_for_events(std::move(its_events_lock), 3, std::move(events_condition_));
+ check_received_events_payload(0x2);
+ its_expected.insert({info_.event_id, 1});
+ its_expected.insert({static_cast<vsomeip::event_t>(info_.event_id+1), 1});
+ its_expected.insert({static_cast<vsomeip::event_t>(info_.event_id+2), 1});
+
+ check_received_events_number(its_expected);
+ its_expected.clear();
+
+
+ // set value again
+ set_field_at_service(0x3);
+ wait_on_condition(std::move(its_set_value_lock), &wait_set_value_, std::move(set_value_condition_));
+ wait_for_events(std::move(its_events_lock), 3, std::move(events_condition_));
+ check_received_events_payload(0x3);
+ its_expected.insert({info_.event_id, 1});
+ its_expected.insert({static_cast<vsomeip::event_t>(info_.event_id+1), 1});
+ its_expected.insert({static_cast<vsomeip::event_t>(info_.event_id+2), 1});
+ check_received_events_number(its_expected);
+
+ unsubscribe_at_service();
+ // sleep some time to ensure the unsubscription was processed by the
+ // remote routing_manager before setting the field again in the next
+ // loop.
+ std::this_thread::sleep_for(std::chrono::milliseconds(1000));
+ }
+ std::unique_lock<std::mutex> its_shutdown_lock(shutdown_response_mutex_);
+ call_method_at_service(subscribe_notify_test::shutdown_method_id);
+ wait_on_condition(std::move(its_shutdown_lock), &wait_shutdown_response_, std::move(shutdown_response_condition_));
+ stop();
+ }
+
+private:
+ std::shared_ptr<vsomeip::application> app_;
+ struct subscribe_notify_test::service_info info_;
+ bool use_tcp_;
+
+ bool wait_availability_;
+ std::mutex availability_mutex_;
+ std::condition_variable availability_condition_;
+
+ bool wait_set_value_;
+ std::mutex set_value_mutex_;
+ std::condition_variable set_value_condition_;
+
+ bool wait_shutdown_response_;
+ std::mutex shutdown_response_mutex_;
+ std::condition_variable shutdown_response_condition_;
+
+ bool wait_events_;
+ std::mutex events_mutex_;
+ std::condition_variable events_condition_;
+
+ std::vector<std::shared_ptr<vsomeip::payload>> received_events_;
+ std::map<vsomeip::event_t, std::uint32_t> number_received_events_;
+ std::thread run_thread_;
+};
+
+#ifndef VSOMEIP_ENABLE_SIGNAL_HANDLING
+ subscribe_notify_test_one_event_two_eventgroups_client *its_client_ptr(nullptr);
+ void handle_signal(int _signal) {
+ if (its_client_ptr != nullptr &&
+ (_signal == SIGINT || _signal == SIGTERM))
+ its_client_ptr->stop();
+ }
+#endif
+
+static bool use_tcp;
+
+TEST(someip_subscribe_notify_test_one_event_two_eventgroups, subscribe_to_service)
+{
+ subscribe_notify_test_one_event_two_eventgroups_client its_client(
+ subscribe_notify_test::service_info_subscriber_based_notification, use_tcp);
+#ifndef VSOMEIP_ENABLE_SIGNAL_HANDLING
+ its_client_ptr = &its_client;
+ signal(SIGINT, handle_signal);
+ signal(SIGTERM, handle_signal);
+#endif
+ if (its_client.init()) {
+ its_client.start();
+ }
+}
+
+#ifndef _WIN32
+int main(int argc, char** argv)
+{
+ ::testing::InitGoogleTest(&argc, argv);
+ if(argc < 2) {
+ std::cerr << "Please specify a subscription type, like: " << argv[0] << " UDP" << std::endl;
+ std::cerr << "Valid subscription types include:" << std::endl;
+ std::cerr << "[UDP, TCP]" << std::endl;
+ return 1;
+ }
+
+ if(std::string("TCP") == std::string(argv[1])) {
+ use_tcp = true;
+ } else if(std::string("UDP") == std::string(argv[1])) {
+ use_tcp = false;
+ } else {
+ std::cerr << "Wrong subscription type passed, exiting" << std::endl;
+ std::cerr << "Valid subscription types include:" << std::endl;
+ std::cerr << "[UDP, TCP]" << std::endl;
+ return 1;
+ }
+
+ return RUN_ALL_TESTS();
+}
+#endif
diff --git a/test/subscribe_notify_tests/subscribe_notify_test_one_event_two_eventgroups_master_starter.sh b/test/subscribe_notify_tests/subscribe_notify_test_one_event_two_eventgroups_master_starter.sh
new file mode 100755
index 0000000..c983369
--- /dev/null
+++ b/test/subscribe_notify_tests/subscribe_notify_test_one_event_two_eventgroups_master_starter.sh
@@ -0,0 +1,88 @@
+#!/bin/bash
+# Copyright (C) 2015-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/.
+
+# Purpose: This script is needed to start the services with
+# one command. This is necessary as ctest - which is used to run the
+# tests - isn't able to start multiple binaries for one testcase. Therefore
+# the testcase simply executes this script. This script then runs the services
+# and checks that all exit successfully.
+
+if [ $# -lt 2 ]; then
+ echo "Please pass a json file and a subscription type to this script."
+ echo "Valid subscription types include:"
+ echo " [UDP, TCP]"
+ echo "For example: $0 UDP subscribe_notify_test_one_event_two_eventgroups_master.json"
+ exit 1
+fi
+
+# replace master with slave to be able display the correct json file to be used
+# with the slave script
+MASTER_JSON_FILE=$2
+if [ $1 == "UDP" ]; then
+ SLAVE_JSON_FILE=${MASTER_JSON_FILE/master/udp_slave}
+elif [ $1 == "TCP" ]; then
+ SLAVE_JSON_FILE=${MASTER_JSON_FILE/master/tcp_slave}
+fi
+
+FAIL=0
+
+export VSOMEIP_CONFIGURATION=$2
+# start daemon
+../daemon/./vsomeipd &
+PID_VSOMEIPD=$!
+
+# Start the client
+./subscribe_notify_test_one_event_two_eventgroups_client $1 &
+PID_CLIENT=$!
+sleep 1
+
+if [ ! -z "$USE_LXC_TEST" ]; then
+ echo "starting subscribe_notify_test_slave_starter.sh on slave LXC with parameters $SLAVE_JSON_FILE"
+ ssh -tt -i $SANDBOX_ROOT_DIR/commonapi_main/lxc-config/.ssh/mgc_lxc/rsa_key_file.pub -o StrictHostKeyChecking=no root@$LXC_TEST_SLAVE_IP "bash -ci \"set -m; cd \\\$SANDBOX_TARGET_DIR/vsomeip/test; ./subscribe_notify_test_one_event_two_eventgroups_slave_starter.sh $SLAVE_JSON_FILE\"" &
+ echo "remote ssh job id: $!"
+elif [ ! -z "$USE_DOCKER" ]; then
+ docker run --name sntms --cap-add NET_ADMIN $DOCKER_IMAGE sh -c "route add -net 224.0.0.0/4 dev eth0 && cd $DOCKER_TESTS && ./subscribe_notify_test_one_event_two_eventgroups_slave_starter.sh $SLAVE_JSON_FILE" &
+else
+ cat <<End-of-message
+*******************************************************************************
+*******************************************************************************
+** Please now run:
+** subscribe_notify_test_one_event_two_eventgroups_slave_starter.sh $SLAVE_JSON_FILE
+** from an external host to successfully complete this test.
+**
+** You probably will need to adapt the 'unicast' settings in
+** subscribe_notify_test_diff_client_ids_diff_ports_master.json and
+** subscribe_notify_test_diff_client_ids_diff_ports_slave.json to your personal setup.
+*******************************************************************************
+*******************************************************************************
+End-of-message
+fi
+
+if [ ! -z "$USE_DOCKER" ]; then
+ FAIL=0
+fi
+
+# wait until client exits successfully
+wait $PID_CLIENT || FAIL=$(($FAIL+1))
+
+
+# kill daemon
+kill $PID_VSOMEIPD
+wait $PID_VSOMEIPD || FAIL=$(($FAIL+1))
+
+if [ ! -z "$USE_DOCKER" ]; then
+ docker stop sntms
+ docker rm sntms
+fi
+
+echo ""
+
+# Check if both exited successfully
+if [ $FAIL -eq 0 ]; then
+ exit 0
+else
+ exit 1
+fi
diff --git a/test/subscribe_notify_tests/subscribe_notify_test_one_event_two_eventgroups_service.cpp b/test/subscribe_notify_tests/subscribe_notify_test_one_event_two_eventgroups_service.cpp
new file mode 100644
index 0000000..1d7b0c3
--- /dev/null
+++ b/test/subscribe_notify_tests/subscribe_notify_test_one_event_two_eventgroups_service.cpp
@@ -0,0 +1,212 @@
+// 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 VSOMEIP_ENABLE_SIGNAL_HANDLING
+#include <csignal>
+#endif
+#include <chrono>
+#include <condition_variable>
+#include <iomanip>
+#include <iostream>
+#include <sstream>
+#include <thread>
+#include <atomic>
+
+#include <gtest/gtest.h>
+#include "../../implementation/logging/include/logger.hpp"
+
+#include <vsomeip/vsomeip.hpp>
+
+#include "subscribe_notify_test_globals.hpp"
+
+class subscribe_notify_test_one_event_two_eventgroups_service {
+public:
+ subscribe_notify_test_one_event_two_eventgroups_service(subscribe_notify_test::service_info _info) :
+ app_(vsomeip::runtime::get()->create_application()),
+ wait_for_shutdown_(true),
+ info_(_info),
+ notify_thread_(std::bind(&subscribe_notify_test_one_event_two_eventgroups_service::wait_for_shutdown, this)) {
+ }
+
+ ~subscribe_notify_test_one_event_two_eventgroups_service() {
+ notify_thread_.join();
+ }
+
+ bool init() {
+ if (!app_->init()) {
+ ADD_FAILURE() << "Couldn't initialize application";
+ return false;
+ }
+ app_->register_state_handler(
+ std::bind(&subscribe_notify_test_one_event_two_eventgroups_service::on_state, this,
+ std::placeholders::_1));
+
+ app_->register_message_handler(
+ info_.service_id,
+ info_.instance_id,
+ subscribe_notify_test::set_method_id,
+ std::bind(&subscribe_notify_test_one_event_two_eventgroups_service::on_set, this,
+ std::placeholders::_1));
+
+ app_->register_message_handler(
+ info_.service_id,
+ info_.instance_id,
+ info_.method_id,
+ std::bind(&subscribe_notify_test_one_event_two_eventgroups_service::on_message, this,
+ std::placeholders::_1));
+
+ app_->register_message_handler(
+ info_.service_id,
+ info_.instance_id,
+ subscribe_notify_test::shutdown_method_id,
+ std::bind(&subscribe_notify_test_one_event_two_eventgroups_service::on_shutdown, this,
+ std::placeholders::_1));
+
+ std::set<vsomeip::eventgroup_t> its_groups;
+ // the service offers three events in two eventgroups
+ // one of the events is in both eventgroups
+ its_groups.insert(info_.eventgroup_id);
+ app_->offer_event(info_.service_id, info_.instance_id,
+ info_.event_id, its_groups, true);
+ app_->offer_event(info_.service_id, info_.instance_id,
+ static_cast<vsomeip::event_t>(info_.event_id + 2), its_groups, true);
+ its_groups.erase(info_.eventgroup_id);
+ its_groups.insert(static_cast<vsomeip::eventgroup_t>(info_.eventgroup_id + 1));
+ app_->offer_event(info_.service_id, info_.instance_id,
+ static_cast<vsomeip::event_t>(info_.event_id + 1), its_groups, true);
+ app_->offer_event(info_.service_id, info_.instance_id,
+ static_cast<vsomeip::event_t>(info_.event_id + 2), its_groups, true);
+ payload_ = vsomeip::runtime::get()->create_payload();
+
+ return true;
+ }
+
+ void start() {
+ app_->start();
+ }
+
+#ifndef VSOMEIP_ENABLE_SIGNAL_HANDLING
+ /*
+ * Handle signal to shutdown
+ */
+ void stop() {
+ {
+ std::lock_guard<std::mutex> its_lock(shutdown_mutex_);
+ wait_for_shutdown_ = false;
+ shutdown_condition_.notify_one();
+ }
+ app_->clear_all_handler();
+ stop_offer();
+ notify_thread_.join();
+ app_->stop();
+ }
+#endif
+
+ void offer() {
+ app_->offer_service(info_.service_id, info_.instance_id);
+ }
+
+ void stop_offer() {
+ app_->stop_offer_service(info_.service_id, info_.instance_id);
+ }
+
+ void on_state(vsomeip::state_type_e _state) {
+ std::cout << "Application " << app_->get_name() << " is "
+ << (_state == vsomeip::state_type_e::ST_REGISTERED ?
+ "registered." : "deregistered.") << std::endl;
+
+ if (_state == vsomeip::state_type_e::ST_REGISTERED) {
+ offer();
+ }
+ }
+
+ void on_shutdown(const std::shared_ptr<vsomeip::message> &_message) {
+ std::shared_ptr<vsomeip::message> its_response
+ = vsomeip::runtime::get()->create_response(_message);
+ its_response->set_payload(payload_);
+ app_->send(its_response, true);
+ {
+ std::lock_guard<std::mutex> its_lock(shutdown_mutex_);
+ wait_for_shutdown_ = false;
+ shutdown_condition_.notify_one();
+ }
+ }
+
+ void on_set(const std::shared_ptr<vsomeip::message> &_message) {
+ std::shared_ptr<vsomeip::message> its_response
+ = vsomeip::runtime::get()->create_response(_message);
+ payload_ = _message->get_payload();
+ its_response->set_payload(payload_);
+ app_->send(its_response, true);
+ app_->notify(info_.service_id, info_.instance_id, info_.event_id, payload_);
+ app_->notify(info_.service_id, info_.instance_id, static_cast<vsomeip::event_t>(info_.event_id + 1), payload_);
+ app_->notify(info_.service_id, info_.instance_id, static_cast<vsomeip::event_t>(info_.event_id + 2), payload_);
+ }
+
+ void on_message(const std::shared_ptr<vsomeip::message> &_message) {
+ app_->send(vsomeip::runtime::get()->create_response(_message),true);
+ }
+
+ void wait_for_shutdown() {
+ {
+ std::unique_lock<std::mutex> its_lock(shutdown_mutex_);
+ while (wait_for_shutdown_) {
+ shutdown_condition_.wait(its_lock);
+ }
+ wait_for_shutdown_= true;
+ }
+
+ app_->clear_all_handler();
+ std::this_thread::sleep_for(std::chrono::milliseconds(100));
+ stop_offer();
+ app_->stop();
+ }
+
+private:
+ std::shared_ptr<vsomeip::application> app_;
+
+ std::mutex shutdown_mutex_;
+ bool wait_for_shutdown_;
+ std::condition_variable shutdown_condition_;
+
+ std::shared_ptr<vsomeip::payload> payload_;
+
+ subscribe_notify_test::service_info info_;
+
+ std::thread notify_thread_;
+};
+
+#ifndef VSOMEIP_ENABLE_SIGNAL_HANDLING
+ subscribe_notify_test_one_event_two_eventgroups_service *its_service_ptr(nullptr);
+ void handle_signal(int _signal) {
+ if (its_service_ptr != nullptr &&
+ (_signal == SIGINT || _signal == SIGTERM))
+ its_service_ptr->stop();
+ }
+#endif
+
+
+TEST(someip_subscribe_notify_test_one_event_two_eventgroups, wait_for_attribute_set)
+{
+ subscribe_notify_test_one_event_two_eventgroups_service its_service(
+ subscribe_notify_test::service_info_subscriber_based_notification);
+#ifndef VSOMEIP_ENABLE_SIGNAL_HANDLING
+ its_service_ptr = &its_service;
+ signal(SIGINT, handle_signal);
+ signal(SIGTERM, handle_signal);
+#endif
+ if (its_service.init()) {
+ its_service.start();
+ }
+}
+
+#ifndef _WIN32
+int main(int argc, char** argv)
+{
+ ::testing::InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
+}
+#endif
+
+
diff --git a/test/subscribe_notify_tests/subscribe_notify_test_one_event_two_eventgroups_slave_starter.sh b/test/subscribe_notify_tests/subscribe_notify_test_one_event_two_eventgroups_slave_starter.sh
new file mode 100755
index 0000000..8138612
--- /dev/null
+++ b/test/subscribe_notify_tests/subscribe_notify_test_one_event_two_eventgroups_slave_starter.sh
@@ -0,0 +1,45 @@
+#!/bin/bash
+# Copyright (C) 2015-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/.
+
+# Purpose: This script is needed to start the services with
+# one command. This is necessary as ctest - which is used to run the
+# tests - isn't able to start multiple binaries for one testcase. Therefore
+# the testcase simply executes this script. This script then runs the services
+# and checks that all exit successfully.
+
+if [ $# -lt 1 ]; then
+ echo "Please pass a json file to this script."
+ echo "For example: $0 subscribe_notify_test_one_event_two_eventgroups_slave.json"
+ exit 1
+fi
+
+FAIL=0
+
+export VSOMEIP_CONFIGURATION=$1
+# start daemon
+../daemon/./vsomeipd &
+PID_VSOMEIPD=$!
+
+# Start the services
+./subscribe_notify_test_one_event_two_eventgroups_service &
+PID_SERVICE=$!
+
+# wait until service exits successfully
+wait $PID_SERVICE || FAIL=$(($FAIL+1))
+
+
+# kill daemon
+kill $PID_VSOMEIPD
+wait $PID_VSOMEIPD || FAIL=$(($FAIL+1))
+
+echo ""
+
+# Check if both exited successfully
+if [ $FAIL -eq 0 ]; then
+ exit 0
+else
+ exit 1
+fi
diff --git a/test/subscribe_notify_tests/subscribe_notify_test_service.cpp b/test/subscribe_notify_tests/subscribe_notify_test_service.cpp
index bc2eedd..b49831c 100644
--- a/test/subscribe_notify_tests/subscribe_notify_test_service.cpp
+++ b/test/subscribe_notify_tests/subscribe_notify_test_service.cpp
@@ -11,6 +11,7 @@
#include <thread>
#include <map>
#include <algorithm>
+#include <atomic>
#include <gtest/gtest.h>
@@ -36,7 +37,9 @@ public:
wait_for_stop_(true),
stop_thread_(std::bind(&subscribe_notify_test_service::wait_for_stop, this)),
wait_for_notify_(true),
- notify_thread_(std::bind(&subscribe_notify_test_service::notify, this)) {
+ notify_thread_(std::bind(&subscribe_notify_test_service::notify, this)),
+ subscription_state_handler_called_(0),
+ subscription_error_occured_(false) {
if (!app_->init()) {
ADD_FAILURE() << "Couldn't initialize application";
return;
@@ -73,6 +76,12 @@ public:
std::placeholders::_1, std::placeholders::_2,
std::placeholders::_3));
+ auto handler = std::bind(&subscribe_notify_test_service::on_subscription_state_change, this,
+ std::placeholders::_1, std::placeholders::_2,
+ std::placeholders::_3, std::placeholders::_4, std::placeholders::_5);
+ app_->register_subscription_status_handler(i.service_id, i.instance_id, i.eventgroup_id, vsomeip::ANY_EVENT, handler);
+
+
std::set<vsomeip::eventgroup_t> its_eventgroups;
its_eventgroups.insert(i.eventgroup_id);
app_->request_event(i.service_id, i.instance_id, i.event_id, its_eventgroups, true);
@@ -143,6 +152,23 @@ public:
}
}
+ void on_subscription_state_change(const vsomeip::service_t _service, const vsomeip::instance_t _instance,
+ const vsomeip::eventgroup_t _eventgroup, const vsomeip::event_t _event, const uint16_t _error) {
+ (void)_service;
+ (void)_instance;
+ (void)_eventgroup;
+ (void)_event;
+
+ if (!_error) {
+ subscription_state_handler_called_++;
+ } else {
+ subscription_error_occured_ = true;
+ VSOMEIP_WARNING << std::hex << app_->get_client()
+ << " : on_subscription_state_change: for service " << std::hex
+ << _service << " received a subscription error!";
+ }
+ }
+
bool on_subscription(vsomeip::client_t _client, bool _subscribed) {
static bool notified(false);
if (_subscribed) {
@@ -285,12 +311,14 @@ public:
VSOMEIP_DEBUG << "[" << std::setw(4) << std::setfill('0') << std::hex
<< service_info_.service_id << "] Subscribing";
// subscribe to events of other services
+ uint32_t subscribe_count = 0;
for(const subscribe_notify_test::service_info& i: service_infos_) {
if ((i.service_id == service_info_.service_id
&& i.instance_id == service_info_.instance_id)
|| (i.service_id == 0xFFFF && i.instance_id == 0xFFFF)) {
continue;
}
+ ++subscribe_count;
app_->subscribe(i.service_id, i.instance_id, i.eventgroup_id,
vsomeip::DEFAULT_MAJOR, subscription_type_);
VSOMEIP_DEBUG << "[" << std::hex << service_info_.service_id
@@ -303,6 +331,18 @@ public:
while (wait_until_notified_from_other_services_) {
condition_.wait(its_lock);
}
+
+ // It is possible that we run in the case a subscription is NACKED
+ // due to TCP endpoint not completely connected when subscription
+ // is processed in the server - due to resubscribing the error handler
+ // count may differ from expected value, but its not a real but as
+ // the subscription takes places anyways and all events will be received.
+ if (!subscription_error_occured_) {
+ ASSERT_EQ(subscribe_count, subscription_state_handler_called_);
+ } else {
+ VSOMEIP_WARNING << "Subscription state handler check skipped: CallCount="
+ << std::dec << subscription_state_handler_called_;
+ }
}
void notify() {
@@ -358,6 +398,23 @@ public:
condition_.notify_one();
}
+ stop_offer();
+
+ // ensure that the service which hosts the routing doesn't exit to early
+ if (app_->is_routing()) {
+ for (const auto& i : service_infos_) {
+ if ((i.service_id == service_info_.service_id
+ && i.instance_id == service_info_.instance_id)
+ || (i.service_id == 0xFFFF && i.instance_id == 0xFFFF)) {
+ continue;
+ }
+ while (app_->is_available(i.service_id, i.instance_id,
+ vsomeip::ANY_MAJOR, vsomeip::ANY_MINOR)) {
+ std::this_thread::sleep_for(std::chrono::milliseconds(100));
+ }
+ }
+ }
+
std::this_thread::sleep_for(std::chrono::seconds(1));
for(const auto& i : service_infos_) {
if ((i.service_id == service_info_.service_id
@@ -365,6 +422,8 @@ public:
|| (i.service_id == 0xFFFF && i.instance_id == 0xFFFF)) {
continue;
}
+ app_->register_subscription_status_handler(i.service_id, i.instance_id,
+ i.eventgroup_id, vsomeip::ANY_EVENT, nullptr);
app_->unsubscribe(i.service_id, i.instance_id, i.eventgroup_id);
app_->release_event(i.service_id, i.instance_id, i.event_id);
app_->release_service(i.service_id, i.instance_id);
@@ -398,6 +457,8 @@ private:
std::mutex notify_mutex_;
std::condition_variable notify_condition_;
std::thread notify_thread_;
+ std::atomic<uint32_t> subscription_state_handler_called_;
+ std::atomic<bool> subscription_error_occured_;
};
static int service_number;
diff --git a/tools/vsomeip_ctrl.cpp b/tools/vsomeip_ctrl.cpp
index 9dde00a..1f64c2f 100644
--- a/tools/vsomeip_ctrl.cpp
+++ b/tools/vsomeip_ctrl.cpp
@@ -375,8 +375,10 @@ int main(int argc, char** argv) {
for (unsigned int i = 0; i < message.length(); i += 2) {
vsomeip::byte_t its_byte;
try {
- its_byte = static_cast<vsomeip::byte_t>(std::stoul(
- message.substr(i, 2), 0, 16));
+ std::uint64_t tmp = std::stoul(message.substr(i, 2), 0, 16);
+ tmp = (tmp > (std::numeric_limits<std::uint8_t>::max)()) ?
+ (std::numeric_limits<std::uint8_t>::max)() : tmp;
+ its_byte = static_cast<vsomeip::byte_t>(tmp);
} catch (std::invalid_argument &e) {
std::cerr << e.what() << ": Couldn't convert '"
<< message.substr(i, 2) << "' to hex, exiting: "
@@ -404,8 +406,11 @@ int main(int argc, char** argv) {
for (unsigned int i = 0; i < instance_str.length(); i += 2) {
vsomeip::byte_t its_byte;
try {
- its_byte = static_cast<vsomeip::byte_t>(std::stoul(
- instance_str.substr(i, 2), 0, 16));
+ std::uint64_t tmp = std::stoul(instance_str.substr(i, 2), 0, 16);
+ tmp = (tmp > (std::numeric_limits<std::uint8_t>::max)()) ?
+ (std::numeric_limits<std::uint8_t>::max)() : tmp;
+ its_byte = static_cast<vsomeip::byte_t>(tmp);
+ its_byte = static_cast<vsomeip::byte_t>(tmp);
} catch (std::invalid_argument &e) {
std::cerr << e.what() << ": Couldn't convert '"
<< instance_str.substr(i, 2) << "' to hex, exiting: "
@@ -433,4 +438,5 @@ int main(int argc, char** argv) {
}
vsomeip_ctrl::vsomeip_sender sender(use_tcp, user_message, instance);
+ return EXIT_SUCCESS;
}