summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJürgen Gehring <Juergen.Gehring@bmw.de>2016-11-04 09:26:06 -0700
committerJürgen Gehring <Juergen.Gehring@bmw.de>2016-11-04 09:26:06 -0700
commit30b6688d9f77d40352cc3cec99052e0946a8affc (patch)
tree52d7f9332f709917bb287db61505000e18eeeefd
parent7bb933404f4ee0be3add0c506b53e1c1f7274869 (diff)
downloadvSomeIP-30b6688d9f77d40352cc3cec99052e0946a8affc.tar.gz
vSomeIP 2.5.02.5.0
-rw-r--r--.gitignore5
-rw-r--r--CHANGES14
-rw-r--r--CMakeLists.txt33
-rw-r--r--README.md81
-rw-r--r--config/vsomeip-local-security.json75
-rw-r--r--config/vsomeip-tcp-client-security.json74
-rw-r--r--config/vsomeip-tcp-service-security.json88
-rw-r--r--config/vsomeip-udp-client-security.json74
-rw-r--r--config/vsomeip-udp-service-security.json88
-rw-r--r--daemon/vsomeipd.cpp6
-rw-r--r--documentation/vsomeipUserGuide (renamed from README)133
-rw-r--r--exportmap.gcc5
-rw-r--r--implementation/configuration/include/configuration.hpp17
-rw-r--r--implementation/configuration/include/configuration_impl.hpp130
-rw-r--r--implementation/configuration/include/internal.hpp.in13
-rw-r--r--implementation/configuration/include/policy.hpp29
-rw-r--r--implementation/configuration/include/trace.hpp3
-rw-r--r--implementation/configuration/src/configuration.cpp29
-rw-r--r--implementation/configuration/src/configuration_impl.cpp1871
-rw-r--r--implementation/endpoints/include/client_endpoint_impl.hpp5
-rw-r--r--implementation/endpoints/include/credentials.hpp26
-rw-r--r--implementation/endpoints/include/endpoint_host.hpp10
-rw-r--r--implementation/endpoints/include/local_client_endpoint_impl.hpp2
-rw-r--r--implementation/endpoints/include/local_server_endpoint_impl.hpp16
-rw-r--r--implementation/endpoints/include/server_endpoint_impl.hpp2
-rw-r--r--implementation/endpoints/include/tcp_server_endpoint_impl.hpp1
-rw-r--r--implementation/endpoints/include/udp_server_endpoint_impl.hpp1
-rw-r--r--implementation/endpoints/src/client_endpoint_impl.cpp24
-rw-r--r--implementation/endpoints/src/credentials.cpp109
-rw-r--r--implementation/endpoints/src/local_client_endpoint_impl.cpp54
-rw-r--r--implementation/endpoints/src/local_server_endpoint_impl.cpp82
-rw-r--r--implementation/endpoints/src/tcp_client_endpoint_impl.cpp4
-rw-r--r--implementation/endpoints/src/tcp_server_endpoint_impl.cpp9
-rw-r--r--implementation/endpoints/src/udp_server_endpoint_impl.cpp42
-rw-r--r--implementation/logging/include/defines.hpp2
-rw-r--r--implementation/logging/include/logger_impl.hpp9
-rw-r--r--implementation/logging/src/logger_impl.cpp30
-rw-r--r--implementation/routing/include/event.hpp14
-rw-r--r--implementation/routing/include/routing_manager.hpp11
-rw-r--r--implementation/routing/include/routing_manager_base.hpp50
-rw-r--r--implementation/routing/include/routing_manager_impl.hpp35
-rw-r--r--implementation/routing/include/routing_manager_proxy.hpp47
-rw-r--r--implementation/routing/include/routing_manager_stub.hpp20
-rw-r--r--implementation/routing/include/routing_manager_stub_host.hpp1
-rw-r--r--implementation/routing/include/serviceinfo.hpp4
-rw-r--r--implementation/routing/src/event.cpp33
-rw-r--r--implementation/routing/src/routing_manager_base.cpp84
-rw-r--r--implementation/routing/src/routing_manager_impl.cpp301
-rw-r--r--implementation/routing/src/routing_manager_proxy.cpp358
-rw-r--r--implementation/routing/src/routing_manager_stub.cpp275
-rw-r--r--implementation/routing/src/serviceinfo.cpp11
-rw-r--r--implementation/runtime/include/application_impl.hpp19
-rw-r--r--implementation/runtime/include/runtime_impl.hpp2
-rw-r--r--implementation/runtime/src/application_impl.cpp216
-rw-r--r--implementation/runtime/src/runtime_impl.cpp2
-rw-r--r--implementation/service_discovery/include/defines.hpp1
-rw-r--r--implementation/service_discovery/include/fsm_base.hpp38
-rw-r--r--implementation/service_discovery/include/fsm_events.hpp60
-rw-r--r--implementation/service_discovery/include/service_discovery.hpp16
-rw-r--r--implementation/service_discovery/include/service_discovery_fsm.hpp203
-rw-r--r--implementation/service_discovery/include/service_discovery_host.hpp3
-rw-r--r--implementation/service_discovery/include/service_discovery_impl.hpp88
-rw-r--r--implementation/service_discovery/src/fsm_base.cpp51
-rw-r--r--implementation/service_discovery/src/service_discovery_fsm.cpp416
-rw-r--r--implementation/service_discovery/src/service_discovery_impl.cpp555
-rw-r--r--implementation/utility/include/utility.hpp12
-rw-r--r--implementation/utility/src/utility.cpp37
-rw-r--r--interface/vsomeip/application.hpp10
-rw-r--r--interface/vsomeip/enumeration_types.hpp8
-rw-r--r--interface/vsomeip/export.hpp7
-rw-r--r--test/CMakeLists.txt76
-rw-r--r--test/application_tests/application_test.cpp15
-rw-r--r--test/application_tests/application_test_client.cpp193
-rw-r--r--test/application_tests/application_test_daemon.cpp34
-rw-r--r--test/application_tests/application_test_globals.hpp25
-rw-r--r--test/application_tests/application_test_service.cpp115
-rw-r--r--test/application_tests/application_test_single_process.cpp47
-rw-r--r--test/application_tests/application_test_single_process.json14
-rwxr-xr-xtest/application_tests/application_test_single_process_starter.sh23
-rw-r--r--test/application_tests/conf/application_test.json.in (renamed from test/application_tests/application_test.json)2
-rw-r--r--test/application_tests/conf/application_test_daemon.json.in (renamed from test/application_tests/application_test_daemon.json)2
-rw-r--r--test/application_tests/conf/application_test_no_dispatch_threads.json.in (renamed from test/application_tests/application_test_no_dispatch_threads.json)2
-rw-r--r--test/application_tests/conf/application_test_no_dispatch_threads_daemon.json.in (renamed from test/application_tests/application_test_no_dispatch_threads_daemon.json)2
-rw-r--r--test/big_payload_tests/big_payload_test_client.cpp7
-rw-r--r--test/big_payload_tests/big_payload_test_service.cpp9
-rw-r--r--test/client_id_tests/client_id_test_service.cpp41
-rw-r--r--test/configuration_tests/configuration-test-deprecated.json16
-rw-r--r--test/configuration_tests/configuration-test.cpp302
-rw-r--r--test/cpu_load_tests/cpu_load_test_client.cpp11
-rw-r--r--test/cpu_load_tests/cpu_load_test_service.cpp11
-rw-r--r--test/header_factory_tests/header_factory_test_client.cpp12
-rw-r--r--test/header_factory_tests/header_factory_test_service.cpp9
-rw-r--r--test/initial_event_tests/conf/initial_event_test_diff_client_ids_diff_ports_master.json.in10
-rw-r--r--test/initial_event_tests/conf/initial_event_test_diff_client_ids_diff_ports_same_service_id_master.json.in10
-rw-r--r--test/initial_event_tests/conf/initial_event_test_diff_client_ids_diff_ports_same_service_id_slave.json.in10
-rw-r--r--test/initial_event_tests/conf/initial_event_test_diff_client_ids_diff_ports_slave.json.in10
-rw-r--r--test/initial_event_tests/conf/initial_event_test_diff_client_ids_partial_same_ports_master.json.in10
-rw-r--r--test/initial_event_tests/conf/initial_event_test_diff_client_ids_partial_same_ports_slave.json.in10
-rw-r--r--test/initial_event_tests/conf/initial_event_test_diff_client_ids_same_ports_master.json.in10
-rw-r--r--test/initial_event_tests/conf/initial_event_test_diff_client_ids_same_ports_slave.json.in10
-rw-r--r--test/initial_event_tests/conf/initial_event_test_same_client_ids_diff_ports_master.json.in10
-rw-r--r--test/initial_event_tests/conf/initial_event_test_same_client_ids_diff_ports_slave.json.in10
-rw-r--r--test/initial_event_tests/conf/initial_event_test_same_client_ids_same_ports_master.json.in10
-rw-r--r--test/initial_event_tests/conf/initial_event_test_same_client_ids_same_ports_slave.json.in10
-rw-r--r--test/initial_event_tests/initial_event_test_availability_checker.cpp6
-rw-r--r--test/initial_event_tests/initial_event_test_client.cpp55
-rwxr-xr-xtest/initial_event_tests/initial_event_test_master_starter.sh70
-rw-r--r--test/initial_event_tests/initial_event_test_service.cpp5
-rwxr-xr-xtest/initial_event_tests/initial_event_test_slave_starter.sh35
-rw-r--r--test/initial_event_tests/initial_event_test_stop_service.cpp7
-rw-r--r--test/magic_cookies_tests/magic_cookies_test_client.cpp6
-rw-r--r--test/magic_cookies_tests/magic_cookies_test_service.cpp6
-rw-r--r--test/offer_tests/offer_test_client.cpp7
-rw-r--r--test/offer_tests/offer_test_globals.hpp6
-rw-r--r--test/offer_tests/offer_test_service.cpp6
-rw-r--r--test/offer_tests/offer_test_service_external.cpp26
-rw-r--r--test/payload_tests/payload_test_client.cpp11
-rw-r--r--test/payload_tests/payload_test_client.hpp1
-rw-r--r--test/payload_tests/payload_test_service.cpp11
-rw-r--r--test/routing_tests/conf/external_local_routing_test_client_external.json.in5
-rw-r--r--test/routing_tests/conf/external_local_routing_test_service.json.in1
-rwxr-xr-xtest/routing_tests/conf/local_routing_test_starter.sh.bat.in (renamed from test/routing_tests/local_routing_test_starter.sh)2
-rwxr-xr-xtest/routing_tests/conf/local_routing_test_starter.sh.in79
-rw-r--r--test/routing_tests/external_local_routing_test_service.cpp9
-rw-r--r--test/routing_tests/local_routing_test_client.cpp12
-rw-r--r--test/routing_tests/local_routing_test_client.json3
-rw-r--r--test/routing_tests/local_routing_test_service.cpp9
-rw-r--r--test/routing_tests/local_routing_test_service.json1
-rw-r--r--test/someip_test_globals.hpp4
-rw-r--r--test/subscribe_notify_one_tests/conf/subscribe_notify_one_test_diff_client_ids_diff_ports_master.json.in8
-rw-r--r--test/subscribe_notify_one_tests/conf/subscribe_notify_one_test_diff_client_ids_diff_ports_slave.json.in8
-rw-r--r--test/subscribe_notify_one_tests/subscribe_notify_one_test_service.cpp6
-rw-r--r--test/subscribe_notify_tests/conf/subscribe_notify_test_diff_client_ids_diff_ports_autoconfig_master.json.in8
-rw-r--r--test/subscribe_notify_tests/conf/subscribe_notify_test_diff_client_ids_diff_ports_autoconfig_slave.json.in8
-rw-r--r--test/subscribe_notify_tests/conf/subscribe_notify_test_diff_client_ids_diff_ports_master.json.in8
-rw-r--r--test/subscribe_notify_tests/conf/subscribe_notify_test_diff_client_ids_diff_ports_same_service_id_master.json.in8
-rw-r--r--test/subscribe_notify_tests/conf/subscribe_notify_test_diff_client_ids_diff_ports_same_service_id_slave.json.in8
-rw-r--r--test/subscribe_notify_tests/conf/subscribe_notify_test_diff_client_ids_diff_ports_slave.json.in8
-rw-r--r--test/subscribe_notify_tests/conf/subscribe_notify_test_diff_client_ids_partial_same_ports_master.json.in8
-rw-r--r--test/subscribe_notify_tests/conf/subscribe_notify_test_diff_client_ids_partial_same_ports_slave.json.in8
-rw-r--r--test/subscribe_notify_tests/conf/subscribe_notify_test_diff_client_ids_same_ports_master.json.in8
-rw-r--r--test/subscribe_notify_tests/conf/subscribe_notify_test_diff_client_ids_same_ports_slave.json.in8
-rw-r--r--test/subscribe_notify_tests/conf/subscribe_notify_test_same_client_ids_diff_ports_master.json.in8
-rw-r--r--test/subscribe_notify_tests/conf/subscribe_notify_test_same_client_ids_diff_ports_slave.json.in8
-rw-r--r--test/subscribe_notify_tests/conf/subscribe_notify_test_same_client_ids_same_ports_master.json.in8
-rw-r--r--test/subscribe_notify_tests/conf/subscribe_notify_test_same_client_ids_same_ports_slave.json.in8
-rw-r--r--test/subscribe_notify_tests/subscribe_notify_test_service.cpp6
147 files changed, 5236 insertions, 2559 deletions
diff --git a/.gitignore b/.gitignore
index fa624bc..313f04c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,6 +6,10 @@
/daemon/CMakeFiles
/examples/CMakeFiles
/implementation/configuration/include/internal.hpp
+/test/application_tests/application_test.json
+/test/application_tests/application_test_daemon.json
+/test/application_tests/application_test_no_dispatch_threads.json
+/test/application_tests/application_test_no_dispatch_threads_daemon.json
/test/big_payload_tests/big_payload_test_tcp_client.json
/test/big_payload_tests/big_payload_test_tcp_service.json
/test/magic_cookies_tests/magic_cookies_test_client.json
@@ -15,6 +19,7 @@
/test/payload_tests/external_local_payload_test_service.json
/test/routing_tests/external_local_routing_test_client_external.json
/test/routing_tests/external_local_routing_test_service.json
+/test/routing_tests/local_routing_test_starter.sh
/test/client_id_tests/client_id_test_diff_client_ids_diff_ports_master.json
/test/client_id_tests/client_id_test_diff_client_ids_diff_ports_slave.json
/test/client_id_tests/client_id_test_diff_client_ids_same_ports_master.json
diff --git a/CHANGES b/CHANGES
index 8105aef..3f50503 100644
--- a/CHANGES
+++ b/CHANGES
@@ -228,3 +228,17 @@ v2.4.2
v2.4.3
- Fix receiving of UDP frames containing multiple SOME/IP messages via UDP from
external service instances
+
+v2.5.0
+- Added notify-/notify_one-methods to enable flush control for notifications.
+- Restructured configuration to be a separate module (preparation to enable
+ the usage of compiled configurations to speed-up startup)
+- Added vSomeIP-Security: Socket authentication based on Linux-credentials
+ together with further security checks using configurable policies.
+- Fixed pending subscriptions had not sent out if subscribing application
+ hosts the routing manager.
+- Fixed crash in vsomeipd due to concurrent access when closing/shutdown socket.
+- The service discovery now debounces newly offered service instances to avoid
+ sending out the offers of the same service instance with a too high frequency.
+ The default debounce time is set to 500ms. It can be changed via the new json
+ file parameter service-discovery/offer_debounce_time.
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 21967a6..1b0fd39 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 4)
-set (VSOMEIP_PATCH_VERSION 3)
+set (VSOMEIP_MINOR_VERSION 5)
+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)
@@ -115,7 +115,6 @@ link_directories(
# Base library
file(GLOB vsomeip_SRC
- "implementation/configuration/src/*.cpp"
"implementation/endpoints/src/*.cpp"
"implementation/logging/src/*.cpp"
"implementation/tracing/src/*.cpp"
@@ -130,7 +129,7 @@ add_definitions(-DVSOMEIP_VERSION="${VSOMEIP_VERSION}")
if (MSVC)
message("using MSVC Compiler")
- add_definitions(-DVSOMEIP_DLL_COMPILATION)
+ # add_definitions(-DVSOMEIP_DLL_COMPILATION) now it is controlled per target
SET(BOOST_WINDOWS_VERSION "0x600" CACHE STRING "Set the same Version as the Version with which Boost was built, otherwise there will be errors. (normaly 0x600 is for Windows 7 and 0x501 is for Windows XP)")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_WINSOCK_DEPRECATED_NO_WARNINGS -D_WIN32_WINNT=${BOOST_WINDOWS_VERSION} -DWIN32 -DUSE_VSOMEIP_STATISTICS -DCOMMONAPI_INTERNAL_COMPILATION -DBOOST_LOG_DYN_LINK -DBOOST_ASIO_DISABLE_IOCP /EHsc")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D_CRT_SECURE_NO_WARNINGS -D_SCL_SECURE_NO_WARNINGS -D_WINSOCK_DEPRECATED_NO_WARNINGS -D_WIN32_WINNT=${BOOST_WINDOWS_VERSION} -DWIN32 -DUSE_VSOMEIP_STATISTICS -DCOMMONAPI_INTERNAL_COMPILATION -DBOOST_LOG_DYN_LINK -DBOOST_ASIO_DISABLE_IOCP /EHsc")
@@ -152,6 +151,16 @@ set_target_properties (vsomeip PROPERTIES VERSION ${VSOMEIP_VERSION} SOVERSION $
# the build.
target_link_libraries(vsomeip PRIVATE ${Boost_LIBRARIES} ${USE_RT} ${DL_LIBRARY} ${DLT_LIBRARIES} ${SystemD_LIBRARIES} )
+# Configuration library
+file(GLOB vsomeip-cfg_SRC
+ "implementation/configuration/src/*.cpp"
+)
+list(SORT vsomeip-cfg_SRC)
+
+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})
+
file(GLOB vsomeip-sd_SRC
"implementation/service_discovery/src/*.cpp"
)
@@ -161,6 +170,12 @@ add_library(vsomeip-sd SHARED ${vsomeip-sd_SRC})
set_target_properties (vsomeip-sd PROPERTIES VERSION ${VSOMEIP_VERSION} SOVERSION ${VSOMEIP_MAJOR_VERSION})
target_link_libraries(vsomeip-sd vsomeip ${Boost_LIBRARIES} ${USE_RT} ${DL_LIBRARY} ${SystemD_LIBRARIES})
+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 PROPERTIES COMPILE_DEFINITIONS "VSOMEIP_DLL_COMPILATION")
+endif()
+
# Configuration files
set(EXAMPLE_CONFIG_FILES
@@ -212,6 +227,12 @@ install (
)
install (
+ TARGETS vsomeip-cfg
+ LIBRARY DESTINATION "${INSTALL_LIB_DIR}" COMPONENT shlib
+ RUNTIME DESTINATION "${INSTALL_BIN_DIR}" COMPONENT bin
+)
+
+install (
TARGETS vsomeip-sd
LIBRARY DESTINATION "${INSTALL_LIB_DIR}" COMPONENT shlib
RUNTIME DESTINATION "${INSTALL_BIN_DIR}" COMPONENT bin
@@ -321,8 +342,8 @@ else()
COMMAND asciidoc
-a version=${VSOMEIP_VERSION}
-b html
- -o documentation/README.html
- ${PROJECT_BINARY_DIR}/../README)
+ -o documentation/vsomeipUserGuide.html
+ ${PROJECT_BINARY_DIR}/../documentation/vsomeipUserGuide)
endif()
##############################################################################
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..bfdb89e
--- /dev/null
+++ b/README.md
@@ -0,0 +1,81 @@
+### vsomeip
+
+##### Copyright
+Copyright (C) 2015-2016, Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+
+##### License
+
+This Source Code Form is subject to the terms of the Mozilla Public
+License, v. 2.0. If a copy of the MPL was not distributed with this
+file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+##### vsomeip Overview
+----------------
+The vsomeip stack implements the http://some-ip.com/ (Scalable service-Oriented
+MiddlewarE over IP (SOME/IP)) protocol. The stack consists out of:
+
+* a shared library for SOME/IP (`libvsomeip.so`)
+* a second shared library for SOME/IP's service discovery (`libvsomeip-sd.so`)
+ which is loaded during runtime if the service discovery is enabled.
+
+##### Build Instructions
+
+###### Dependencies
+
+- A C++11 enabled compiler like gcc >= 4.8 is needed.
+- vsomeip uses CMake as buildsystem.
+- vsomeip uses Boost >= 1.55:
+
+Ubuntu 14.04:
+
+`sudo apt-get install libboost-system1.55-dev libboost-thread1.55-dev libboost-log1.55-dev`
+
+Ubuntu 12.04: a PPA is necessary to use version 1.54 of Boost:
+-- URL: https://launchpad.net/~boost-latest/+archive/ubuntu/ppa
+--`sudo add-apt-repository ppa:boost-latest/ppa`
+--`sudo apt-get install libboost-system1.55-dev libboost-thread1.55-dev
+ libboost-log1.55-dev`
+
+For the tests Google's test framework https://code.google.com/p/googletest/[gtest] in version 1.7.0 is needed.
+-- URL: https://googletest.googlecode.com/files/gtest-1.7.0.zip
+
+To build the documentation asciidoc, source-highlight, doxygen and graphviz is needed:
+--`sudo apt-get install asciidoc source-highlight doxygen graphviz`
+
+###### Compilation
+
+For compilation call:
+
+```bash
+mkdir build
+cd build
+cmake ..
+make
+```
+
+To specify a installation directory (like `--prefix=` if you're used to autotools) call cmake like:
+```bash
+cmake -DCMAKE_INSTALL_PREFIX:PATH=$YOUR_PATH ..
+make
+make install
+```
+
+###### Compilation with predefined unicast and/or diagnosis address
+To predefine the unicast address, call cmake like:
+```bash
+cmake -DUNICAST_ADDRESS=<YOUR IP ADDRESS> ..
+```
+
+To predefine the diagnosis address, call cmake like:
+```bash
+cmake -DDIAGNOSIS_ADDRESS=<YOUR DIAGNOSIS ADDRESS> ..
+```
+The diagnosis address is a single byte value.
+
+###### Compilation with signal handling
+
+To compile vsomeip with signal handling (SIGINT/SIGTERM) enabled, call cmake like:
+```bash
+cmake -DENABLE_SIGNAL_HANDLING=1 ..
+```
+In the default setting, the application has to take care of shutting down vsomeip in case these signals are received.
diff --git a/config/vsomeip-local-security.json b/config/vsomeip-local-security.json
new file mode 100644
index 0000000..0f8096f
--- /dev/null
+++ b/config/vsomeip-local-security.json
@@ -0,0 +1,75 @@
+{
+ "unicast" : "10.0.3.1",
+ "logging" :
+ {
+ "level" : "info",
+ "console" : "true",
+ "file" : { "enable" : "false", "path" : "/tmp/vsomeip.log" },
+ "dlt" : "false"
+ },
+ "applications" :
+ [
+ {
+ "name" : "service-sample",
+ "id" : "0x1277"
+ },
+ {
+ "name" : "client-sample",
+ "id" : "0x1344"
+ }
+ ],
+ "security" :
+ {
+ "check_credentials" : "true",
+ "policies" :
+ [
+ {
+ "client" : "0x1277",
+ "credentials" : { "uid" : "1000", "gid" : "1000" },
+ "allow" :
+ {
+ "offers":
+ [
+ {
+ "service" : "0x1234",
+ "instance" : "0x5678"
+ },
+ {
+ "service" : "0x1235",
+ "instance" : "0x5678"
+ }
+ ]
+ }
+ },
+ {
+ "client" : "0x1344",
+ "credentials" : { "uid" : "1000", "gid" : "1000" },
+ "allow" :
+ {
+ "requests":
+ [
+ {
+ "service" : "0x1234",
+ "instance" : "0x5678"
+ }
+ ]
+ }
+ }
+ ]
+ },
+ "routing" : "service-sample",
+ "service-discovery" :
+ {
+ "enable" : "true",
+ "multicast" : "224.244.224.245",
+ "port" : "30490",
+ "protocol" : "udp",
+ "initial_delay_min" : "10",
+ "initial_delay_max" : "100",
+ "repetitions_base_delay" : "200",
+ "repetitions_max" : "3",
+ "ttl" : "3",
+ "cyclic_offer_delay" : "2000",
+ "request_response_delay" : "1500"
+ }
+}
diff --git a/config/vsomeip-tcp-client-security.json b/config/vsomeip-tcp-client-security.json
new file mode 100644
index 0000000..319e6b1
--- /dev/null
+++ b/config/vsomeip-tcp-client-security.json
@@ -0,0 +1,74 @@
+{
+ "unicast" : "10.0.3.28",
+ "netmask" : "255.255.255.0",
+ "logging" :
+ {
+ "level" : "info",
+ "console" : "true",
+ "file" : { "enable" : "true", "path" : "/var/log/vsomeip.log" },
+ "dlt" : "true"
+ },
+ "applications" :
+ [
+ {
+ "name" : "client-sample",
+ "id" : "0x1343"
+ },
+ {
+ "name" : "second-client-sample",
+ "id" : "0x1344"
+ },
+ {
+ "name" : "third-client-sample",
+ "id" : "0x1345"
+ },
+ {
+ "name" : "fourth-client-sample",
+ "id" : "0x1346"
+ }
+ ],
+ "clients" :
+ [
+ {
+ "service" : "0x1234",
+ "instance" : "0x5678",
+ "reliable" : [ "41234" ]
+ }
+ ],
+ "security" :
+ {
+ "check_credentials" : "true",
+ "policies" :
+ [
+ {
+ "client" : { "first" : "0x1343", "last" : "0x1346" },
+ "credentials" : { "uid" : "0", "gid" : "0" },
+ "allow" :
+ {
+ "requests":
+ [
+ {
+ "service" : "0x1234",
+ "instance" : "0x5678"
+ }
+ ]
+ }
+ }
+ ]
+ },
+ "routing" : "client-sample",
+ "service-discovery" :
+ {
+ "enable" : "true",
+ "multicast" : "224.244.224.245",
+ "port" : "30490",
+ "protocol" : "udp",
+ "initial_delay_min" : "10",
+ "initial_delay_max" : "100",
+ "repetitions_base_delay" : "200",
+ "repetitions_max" : "3",
+ "ttl" : "3",
+ "cyclic_offer_delay" : "2000",
+ "request_response_delay" : "1500"
+ }
+}
diff --git a/config/vsomeip-tcp-service-security.json b/config/vsomeip-tcp-service-security.json
new file mode 100644
index 0000000..d1a8521
--- /dev/null
+++ b/config/vsomeip-tcp-service-security.json
@@ -0,0 +1,88 @@
+{
+ "unicast" : "10.0.3.1",
+ "logging" :
+ {
+ "level" : "debug",
+ "console" : "true",
+ "file" : { "enable" : "false", "path" : "/tmp/vsomeip.log" },
+ "dlt" : "false"
+ },
+ "applications" :
+ [
+ {
+ "name" : "service-sample",
+ "id" : "0x1277"
+ }
+ ],
+ "services" :
+ [
+ {
+ "service" : "0x1234",
+ "instance" : "0x5678",
+ "reliable" : { "port" : "30509", "enable-magic-cookies" : "false" }
+ },
+ {
+ "service" : "0x1235",
+ "instance" : "0x5678",
+ "unreliable" : "30509",
+ "multicast" :
+ {
+ "address" : "224.225.226.234",
+ "port" : "32344"
+ }
+ }
+ ],
+ "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"
+ }
+ ]
+ }
+ }
+ ]
+ },
+ "routing" : "service-sample",
+ "service-discovery" :
+ {
+ "enable" : "true",
+ "multicast" : "224.244.224.245",
+ "port" : "30490",
+ "protocol" : "udp",
+ "initial_delay_min" : "10",
+ "initial_delay_max" : "100",
+ "repetitions_base_delay" : "200",
+ "repetitions_max" : "3",
+ "ttl" : "3",
+ "cyclic_offer_delay" : "2000",
+ "request_response_delay" : "1500"
+ }
+}
diff --git a/config/vsomeip-udp-client-security.json b/config/vsomeip-udp-client-security.json
new file mode 100644
index 0000000..661e092
--- /dev/null
+++ b/config/vsomeip-udp-client-security.json
@@ -0,0 +1,74 @@
+{
+ "unicast" : "10.0.3.28",
+ "netmask" : "255.255.255.0",
+ "logging" :
+ {
+ "level" : "debug",
+ "console" : "true",
+ "file" : { "enable" : "true", "path" : "/var/log/vsomeip.log" },
+ "dlt" : "true"
+ },
+ "applications" :
+ [
+ {
+ "name" : "client-sample",
+ "id" : "0x1343"
+ },
+ {
+ "name" : "second-client-sample",
+ "id" : "0x1344"
+ },
+ {
+ "name" : "third-client-sample",
+ "id" : "0x1345"
+ },
+ {
+ "name" : "fourth-client-sample",
+ "id" : "0x1346"
+ }
+ ],
+ "clients" :
+ [
+ {
+ "service" : "0x1234",
+ "instance" : "0x5678",
+ "unreliable" : [ 40000, 40002 ]
+ }
+ ],
+ "security" :
+ {
+ "check_credentials" : "true",
+ "policies" :
+ [
+ {
+ "client" : { "first" : "0x1343", "last" : "0x1346" },
+ "credentials" : { "uid" : "0", "gid" : "0" },
+ "allow" :
+ {
+ "requests":
+ [
+ {
+ "service" : "0x1234",
+ "instance" : "0x5678"
+ }
+ ]
+ }
+ }
+ ]
+ },
+ "routing" : "client-sample",
+ "service-discovery" :
+ {
+ "enable" : "true",
+ "multicast" : "224.244.224.245",
+ "port" : "30490",
+ "protocol" : "udp",
+ "initial_delay_min" : "10",
+ "initial_delay_max" : "100",
+ "repetitions_base_delay" : "200",
+ "repetitions_max" : "3",
+ "ttl" : "3",
+ "cyclic_offer_delay" : "2000",
+ "request_response_delay" : "1500"
+ }
+}
diff --git a/config/vsomeip-udp-service-security.json b/config/vsomeip-udp-service-security.json
new file mode 100644
index 0000000..8dcff8e
--- /dev/null
+++ b/config/vsomeip-udp-service-security.json
@@ -0,0 +1,88 @@
+{
+ "unicast" : "10.0.3.1",
+ "logging" :
+ {
+ "level" : "debug",
+ "console" : "true",
+ "file" : { "enable" : "false", "path" : "/tmp/vsomeip.log" },
+ "dlt" : "false"
+ },
+ "applications" :
+ [
+ {
+ "name" : "service-sample",
+ "id" : "0x1277"
+ }
+ ],
+ "services" :
+ [
+ {
+ "service" : "0x1234",
+ "instance" : "0x5678",
+ "unreliable" : "30509"
+ },
+ {
+ "service" : "0x1235",
+ "instance" : "0x5678",
+ "unreliable" : "30509",
+ "multicast" :
+ {
+ "address" : "224.225.226.234",
+ "port" : "32344"
+ }
+ }
+ ],
+ "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"
+ }
+ ]
+ }
+ }
+ ]
+ },
+ "routing" : "service-sample",
+ "service-discovery" :
+ {
+ "enable" : "true",
+ "multicast" : "224.244.224.245",
+ "port" : "30490",
+ "protocol" : "udp",
+ "initial_delay_min" : "10",
+ "initial_delay_max" : "100",
+ "repetitions_base_delay" : "200",
+ "repetitions_max" : "3",
+ "ttl" : "3",
+ "cyclic_offer_delay" : "2000",
+ "request_response_delay" : "1500"
+ }
+}
diff --git a/daemon/vsomeipd.cpp b/daemon/vsomeipd.cpp
index d924ac9..397abe9 100644
--- a/daemon/vsomeipd.cpp
+++ b/daemon/vsomeipd.cpp
@@ -28,6 +28,11 @@ static std::shared_ptr<vsomeip::application> its_application;
void vsomeipd_stop(int _signal) {
if (_signal == SIGINT || _signal == SIGTERM)
its_application->stop();
+ if (_signal == SIGABRT) {
+ VSOMEIP_DEBUG << "Suspending service discovery";
+ its_application->set_routing_state(vsomeip::routing_state_e::RS_SUSPENDED);
+ its_application->stop();
+ }
}
#endif
@@ -55,6 +60,7 @@ int vsomeipd_process(bool _is_quiet) {
// Handle signals
signal(SIGINT, vsomeipd_stop);
signal(SIGTERM, vsomeipd_stop);
+ signal(SIGABRT, vsomeipd_stop);
#endif
if (its_application->init()) {
if (its_application->is_routing()) {
diff --git a/README b/documentation/vsomeipUserGuide
index 8a453af..491a136 100644
--- a/README
+++ b/documentation/vsomeipUserGuide
@@ -133,13 +133,16 @@ network setup:
If one of this variables isn't specified, only the tests using local
communication exclusively will be runnable.
+Additionally the unit tests require enabled signal handling which can be enabled
+via the `ENABLE_SIGNAL_HANDLING` cmake variable.
+
Example, compilation of tests:
[source, bash]
----
mkdir build
cd build
export GTEST_ROOT=$PATH_TO_GTEST/gtest-1.7.0/
-cmake -DTEST_IP_MASTER=10.0.3.1 -DTEST_IP_SLAVE=10.0.3.125 ..
+cmake -DENABLE_SIGNAL_HANDLING=1 -DTEST_IP_MASTER=10.0.3.1 -DTEST_IP_SLAVE=10.0.3.125 ..
make check
----
@@ -214,6 +217,11 @@ On startup the following environment variables are read out:
local configuration file `./vsomeip.json` and/or a local configuration folder `./vsomeip`.
If `VSOMEIP_CONFIGURATION` is set to a valid file or directory path, this is used instead
of the standard configuration (thus neither default nor local file/folder will be parsed).
+* `VSOMEIP_MANDATORY_CONFIGURATION_FILES`: vsomeip allows to specify mandatory configuration
+ files to speed-up application startup. While mandatory configuration files are read by all
+ applications, all other configuration files are only read by the application that is
+ responsible for connections to external devices. If this configuration variable is not set,
+ the default mandatory files vsomeip_std.json, vsomeip_app.json and vsomeip_plc.json are used.
NOTE: If the file/folder that is configured by `VSOMEIP_CONFIGURATION` does _not_ exist,
the default configuration locations will be used.
@@ -432,7 +440,7 @@ Contains the events of the service.
+
The id of the event.
-**** `is_field`
+*** `is_field`
+
Specifies whether the event is of type field.
+
@@ -440,7 +448,7 @@ NOTE: A field is a combination of getter, setter and notification event. It
contains at least a getter, a setter, or a notifier. The notifier sends an event
message that transports the current value of a field on change.
-**** `is_reliable`
+*** `is_reliable`
+
Specifies whether the communication is reliable respectively whether the event
is sent with the TCP protocol (valid values: _true_,_false_).
@@ -636,6 +644,13 @@ Cycle of the OfferService messages in the main phase.
Minimum delay of a unicast message to a multicast message for
provided services and eventgroups.
+
+
+** `offer_debounce_time`
++
+Time which the stack collects new service offers before they enter the
+repetition phase. This can be used to reduce the number of
+sent messages during startup. The default setting is _500ms_.
++
//Watchdog
* anchor:config-watchdog[]'watchdog' (optional)
+
@@ -672,6 +687,105 @@ normal events.
Specifies an IP-Address (in IPv4 or IPv6 notation) on which the "selective"-feature is supported.
Multiple addresses can be configuered.
+Security
+--------
+vSomeIP has a security implementation based on UNIX credentials.
+If activated every local connection is authenticated during connect using the standard UNIX credential passing mechanism.
+During authentification a client transfers its client identifier together with its credentials (UID / GID) to the server which is then matched against the configuration.
+If received credentials don't match the policy the socket will be immediately closed by the server and an message is logged.
+If accepted the client identifier is bound to the receiving socket and can therefore be used to do further security checks on incoming messages (vSomeIP messages as well as internal commands).
+
+In general clients can be configured to be allowed/denied to request (means communicate with) and offer different service instances.
+Every incoming vSomeIP message (request/response/notifcation) as well as offer service requests or local subscriptions are then checked against the policy.
+If an incoming vSomeIP message or another operation (e.g. offer/subscribe) violates the configured policies it is skipped and a message is logged.
+
+Furthermore if an application receives a routing table (information about other clients/services in the system) it must be received from the authenticated routing manager which means the routing manager must be a configured application if security is active.
+This should avoid malicious applications faking the routing manager and therfore could wrongly inform other clients about services running on the system.
+
+Credential passing is only possible via Unix-Domain-Sockets and therefore only available for local communication.
+However if security is activated method calls from remote clients to local services are checked as well which means remote clients needs to be explicitly allowed.
+Such a policy looks same in case for local clients except the _credentials_ tag can be skipped.
+
+It follows the available configuration switches for the security feature including its functional behavior:
+
+// Security
+* anchor:config-policy[]'security' (optional)
++
+If specified the credential passing mechanism is activated. However no credential or security checks are done as long as _check_credentials_ isn't set to _true_.
+
+** 'check_credentials (optional)'
++
+Specifies whether security checks are active or not. This includes credentials checks on connect as well as all policies checks configured in follow.
+(valid values: _true, false_), (default is _false_).
+
+** 'policies' (array)
++
+Specifies the security policies. Each policy at least needs to specify _client_ and _allow_ / _deny_.
+
+*** 'client'
++
+Specifies a client for which a security policy will be applied (valid value: A valid client identifier in hex: e.g. _0x1234_).
+It is also possible to specify a client identifier range to easily apply a policy to a set of clients.
+A usecase is e.g. to allow a set of remote clients communicate with local services offered remote.
+
+**** 'first'
++
+Specifies the first client of a range (first is included).
+(valid value: A valid client identifier in hex: e.g. _0x1234_)
+
+**** 'last'
++
+Specifies the last client id of a range (last is included).
+(valid value: A valid client identifier in hex: e.g. _0x1234_)
+
+*** 'credentials' (optional)
++
+Specifies the credentials of the above client(s).
+If _check_credentials_ is set to _true_ the credentials for the above client(s) (if they running locally) needs to be specified correctly to ensure local socket authentification can succeed.
+This entry is optional due to the fact that remote clients needs to be configured as well to allow to communicate with local services as already mentioned above.
+For remote clients this entry should be skipped.
+
+**** 'uid'
++
+Specifies the LINUX user id of the above client(s) as decimal number.
+
+**** 'gid'
++
+Specifies the LINUX group id of the above client(s) as decimal number.
+
+*** 'allow/deny'
++
+This tag specifies either _allow_ or _deny_ depending on white- or blacklisting is needed. Specifing _allow_ and _deny_ entries in one policy is therefore not allowed.
+With _allow_ a whitelisting of what is allowed can be done which means an empty _allow_ tag implies everything is denied.
+With _deny_ a blacklisting of what is allowed can be done which means an empty _deny_ tag implies everything is allowed.
+
+**** 'requests' (array)
++
+Specifies a set of serivce instance pairs which the above client(s) is allowed/denied to communicate with.
+
+***** 'service'
++
+Specifies a service for the _requests_.
+
+***** 'instance'
++
+Specifies a instance for the _requests_
+
+**** 'offers' (array)
++
+Specifies a set of service instance pairs which are allowed/denied to be offered by the above client(s).
+
+***** 'service'
++
+Specifies a service for the _offers_.
+
+***** 'instance'
++
+Specifies a instance for the _offers_
+
+In the config/ folder are some vSomeIP configuration files to run the vSomeIP examples with activated security checks.
+They give a basic overview how to use the security related configuration tags described in this chapter to run a simple request/response or subscribe/notify example locally or over remote.
+
Autoconfiguration
-----------------
vsomeip supports the automatic configuration of client identifiers and the routing.
@@ -682,6 +796,11 @@ DIAGNOSIS_ADDRESS when compiling vsomeip. vsomeip will use the diagnosis address
as the high byte and enumerate the connecting applications within the low byte
of the client identifier.
+Autoconfiguration of client identifiers isn't meant to be used together with vSomeIP Security.
+Every client running locally needs to have at least its own credentials configured when security is activated to ensure the credential checks can pass.
+Practically that means if a client requests its identifier over the autoconfiguration for which no credentials are configured (at least it isn't known which client identifier is used beforehand) it is impossible for that client to establish a connection to a server endpoint.
+However if the credentials for all clients are same it's possible to configure them for the overall (or DIAGNOSIS_ADDRESS) client identifier range to mix autoconfiguration together with activated security.
+
vsomeipd
--------
The vsomeipd is a minimal vsomeip application intended to offer routing manager
@@ -771,7 +890,7 @@ CMakeFile
[source, bash]
----
-include::examples/hello_world/CMakeLists.txt[]
+include::../examples/hello_world/CMakeLists.txt[]
----
Configuration File For Client and Service
@@ -779,7 +898,7 @@ Configuration File For Client and Service
[source, bash]
----
-include::examples/hello_world/helloworld-local.json[]
+include::../examples/hello_world/helloworld-local.json[]
----
Service
@@ -787,7 +906,7 @@ Service
[source, bash]
----
-include::examples/hello_world/hello_world_service.cpp[]
+include::../examples/hello_world/hello_world_service.cpp[]
----
The service example results in the following program execution:
@@ -870,7 +989,7 @@ Client
~~~~~~
[source, bash]
----
-include::examples/hello_world/hello_world_client.cpp[]
+include::../examples/hello_world/hello_world_client.cpp[]
----
The client example results in the following program execution:
diff --git a/exportmap.gcc b/exportmap.gcc
index a768523..e0136e6 100644
--- a/exportmap.gcc
+++ b/exportmap.gcc
@@ -17,6 +17,8 @@ global:
vsomeip::udp*;
*vsomeip::logger;
vsomeip::logger::get*;
+ *vsomeip::logger_impl;
+ vsomeip::logger_impl::init*;
*vsomeip::message_base_impl;
*vsomeip::message_base_impl::*;
*vsomeip::message_header_impl;
@@ -34,7 +36,10 @@ global:
vsomeip::serviceinfo::*;
*vsomeip::sd::runtime;
vsomeip::sd::runtime::*;
+ *vsomeip::utility;
+ vsomeip::utility::is*;
};
+ VSOMEIP_CFG_RUNTIME;
VSOMEIP_SD_RUNTIME;
local:
*;
diff --git a/implementation/configuration/include/configuration.hpp b/implementation/configuration/include/configuration.hpp
index e33a0df..4a99ec3 100644
--- a/implementation/configuration/include/configuration.hpp
+++ b/implementation/configuration/include/configuration.hpp
@@ -25,13 +25,13 @@ namespace vsomeip {
class event;
-class VSOMEIP_IMPORT_EXPORT configuration {
+class VSOMEIP_IMPORT_EXPORT_CONFIG configuration {
public:
- static std::shared_ptr<configuration> get(
- const std::set<std::string> &_input = std::set<std::string>());
- static void reset();
+ static std::shared_ptr<configuration> get();
virtual ~configuration() {}
+ virtual bool load(const std::string &_name) = 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;
@@ -98,6 +98,7 @@ public:
virtual ttl_t get_sd_ttl() const = 0;
virtual int32_t get_sd_cyclic_offer_delay() const = 0;
virtual int32_t get_sd_request_response_delay() const = 0;
+ virtual std::uint32_t get_sd_offer_debounce_time() const = 0;
// Trace configuration
virtual std::shared_ptr<cfg::trace> get_trace() const = 0;
@@ -113,6 +114,14 @@ public:
virtual bool log_version() const = 0;
virtual uint32_t get_log_version_interval() const = 0;
+
+ // Security
+ virtual bool is_security_enabled() const = 0;
+ virtual bool is_client_allowed(client_t _client, service_t _service,
+ instance_t _instance) const = 0;
+ virtual bool is_offer_allowed(client_t _client, service_t _service,
+ instance_t _instance) const = 0;
+ virtual bool check_credentials(client_t _client, uint32_t _uid, uint32_t _gid) const = 0;
};
} // namespace vsomeip
diff --git a/implementation/configuration/include/configuration_impl.hpp b/implementation/configuration/include/configuration_impl.hpp
index 46b3166..0dfc382 100644
--- a/implementation/configuration/include/configuration_impl.hpp
+++ b/implementation/configuration/include/configuration_impl.hpp
@@ -18,6 +18,7 @@
#include "configuration.hpp"
#include "watchdog.hpp"
#include "service_instance_range.hpp"
+#include "policy.hpp"
namespace vsomeip {
namespace cfg {
@@ -38,18 +39,15 @@ struct element {
}
};
-class configuration_impl: public configuration {
+class configuration_impl: public configuration, public std::enable_shared_from_this<configuration_impl> {
public:
- VSOMEIP_EXPORT static std::shared_ptr<configuration> get(
- const std::set<std::string> &_input);
- VSOMEIP_EXPORT static void reset();
+ 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 void load(const element &_element);
- VSOMEIP_EXPORT void load_log(const std::vector<element> &_elements);
+ VSOMEIP_EXPORT bool load(const std::string &_name);
VSOMEIP_EXPORT const boost::asio::ip::address & get_unicast_address() const;
VSOMEIP_EXPORT unsigned short get_diagnosis_address() const;
@@ -117,6 +115,7 @@ public:
VSOMEIP_EXPORT ttl_t get_sd_ttl() const;
VSOMEIP_EXPORT int32_t get_sd_cyclic_offer_delay() const;
VSOMEIP_EXPORT int32_t get_sd_request_response_delay() const;
+ VSOMEIP_EXPORT std::uint32_t get_sd_offer_debounce_time() const;
// Trace configuration
VSOMEIP_EXPORT std::shared_ptr<cfg::trace> get_trace() const;
@@ -125,53 +124,72 @@ public:
VSOMEIP_EXPORT uint32_t get_watchdog_timeout() const;
VSOMEIP_EXPORT uint32_t get_allowed_missing_pongs() const;
-
VSOMEIP_EXPORT std::uint32_t get_umask() const;
VSOMEIP_EXPORT std::uint32_t get_permissions_shm() const;
+ // Policy
+ VSOMEIP_EXPORT bool is_security_enabled() const;
+ VSOMEIP_EXPORT bool is_client_allowed(client_t _client, service_t _service,
+ instance_t _instance) const;
+ 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;
+
private:
- void get_logging_configuration(const element &_element,
- std::set<std::string> &_warnings);
-
- void get_someip_configuration(const element &_element);
- void get_services_configuration(const boost::property_tree::ptree &_tree);
- void get_clients_configuration(const boost::property_tree::ptree &_tree);
- void get_payload_sizes_configuration(const boost::property_tree::ptree &_tree);
- void get_routing_configuration(const element &_element);
- void get_service_discovery_configuration(const element &_element);
- void get_applications_configuration(const element &_tree);
- void get_trace_configuration(const element &_tree);
- void get_supports_selective_broadcasts(const boost::property_tree::ptree &_tree);
- void get_watchdog_configuration(const element &_element);
-
- void get_servicegroup_configuration(
- const boost::property_tree::ptree &_tree);
- void get_delays_configuration(const boost::property_tree::ptree &_tree);
- void get_service_configuration(const boost::property_tree::ptree &_tree,
- const std::string &_unicast_address);
- void get_client_configuration(const boost::property_tree::ptree &_tree);
- std::set<uint16_t> get_client_port_configuration(
- const boost::property_tree::ptree &_tree);
- void get_event_configuration(std::shared_ptr<service> &_service,
- const boost::property_tree::ptree &_tree);
- void get_eventgroup_configuration(std::shared_ptr<service> &_service,
- const boost::property_tree::ptree &_tree);
- void get_application_configuration(
- const boost::property_tree::ptree &_tree, const std::string &_file_name);
- void get_trace_channels_configuration(
- const boost::property_tree::ptree &_tree);
- void get_trace_channel_configuration(
- const boost::property_tree::ptree &_tree);
- void get_trace_filters_configuration(
- const boost::property_tree::ptree &_tree);
- void get_trace_filter_configuration(
- const boost::property_tree::ptree &_tree);
- void get_trace_filter_expressions(
+ void read_data(const std::set<std::string> &_input,
+ std::vector<element> &_elements,
+ std::set<std::string> &_failed,
+ bool _standard_only);
+
+ bool load_data(const std::vector<element> &_elements,
+ bool _load_mandatory, bool _load_optional);
+
+ bool load_logging(const element &_element,
+ std::set<std::string> &_warnings);
+ bool load_routing(const element &_element);
+
+ bool load_applications(const element &_element);
+ void load_application_data(const boost::property_tree::ptree &_tree,
+ const std::string &_name);
+
+ void load_tracing(const element &_element);
+ void load_trace_channels(const boost::property_tree::ptree &_tree);
+ void load_trace_channel(const boost::property_tree::ptree &_tree);
+ void load_trace_filters(const boost::property_tree::ptree &_tree);
+ void load_trace_filter(const boost::property_tree::ptree &_tree);
+ void load_trace_filter_expressions(
const boost::property_tree::ptree &_tree,
std::string &_criteria,
std::shared_ptr<trace_filter_rule> &_filter_rule);
- void get_permission_configuration(const element &_element);
- void get_internal_services(const boost::property_tree::ptree &_tree);
+
+ void load_unicast_address(const element &_element);
+ void load_diagnosis_address(const element &_element);
+
+ void load_service_discovery(const element &_element);
+ void load_delays(const boost::property_tree::ptree &_tree);
+
+ void load_services(const element &_element);
+ void load_servicegroup(const boost::property_tree::ptree &_tree);
+ void load_service(const boost::property_tree::ptree &_tree,
+ const std::string &_unicast_address);
+ void load_event(std::shared_ptr<service> &_service,
+ const boost::property_tree::ptree &_tree);
+ void load_eventgroup(std::shared_ptr<service> &_service,
+ const boost::property_tree::ptree &_tree);
+
+ void load_internal_services(const element &_element);
+
+ void load_clients(const element &_element);
+ void load_client(const boost::property_tree::ptree &_tree);
+ std::set<uint16_t> load_client_ports(const boost::property_tree::ptree &_tree);
+
+ void load_watchdog(const element &_element);
+
+ void load_payload_sizes(const element &_element);
+ void load_permissions(const element &_element);
+ void load_selective_broadcasts_support(const element &_element);
+ void load_policies(const element &_element);
+ void load_policy(const boost::property_tree::ptree &_tree);
servicegroup *find_servicegroup(const std::string &_name) const;
std::shared_ptr<client> find_client(service_t _service, instance_t _instance) const;
@@ -181,12 +199,20 @@ private:
void set_magic_cookies_unicast_address();
+ bool is_mandatory(const std::string &_name) const;
bool is_remote(std::shared_ptr<service> _service) const;
bool is_internal_service(service_t _service, instance_t _instance) const;
+ void set_mandatory(const std::string &_input);
+ void trim(std::string &_s);
+
private:
- static std::shared_ptr<configuration_impl> the_configuration;
- static std::mutex mutex_;
+ std::mutex mutex_;
+
+ bool is_loaded_;
+ bool is_logging_loaded_;
+
+ std::set<std::string> mandatory_;
protected:
// Configuration data
@@ -224,6 +250,7 @@ protected:
ttl_t sd_ttl_;
int32_t sd_cyclic_offer_delay_;
int32_t sd_request_response_delay_;
+ std::uint32_t sd_offer_debounce_time_;
std::map<std::string, std::set<uint16_t> > magic_cookies_;
@@ -265,12 +292,17 @@ protected:
ET_WATCHDOG_ALLOWED_MISSING_PONGS,
ET_TRACING_ENABLE,
ET_TRACING_SD_ENABLE,
- ET_MAX = 23
+ ET_SERVICE_DISCOVERY_OFFER_DEBOUNCE_TIME,
+ ET_MAX = 24
};
bool is_configured_[ET_MAX];
std::uint32_t permissions_shm_;
std::uint32_t umask_;
+
+ std::map<client_t, std::shared_ptr<policy>> policies_;
+ bool policy_enabled_;
+ bool check_credentials_;
};
} // namespace cfg
diff --git a/implementation/configuration/include/internal.hpp.in b/implementation/configuration/include/internal.hpp.in
index d10c6d6..766a3f6 100644
--- a/implementation/configuration/include/internal.hpp.in
+++ b/implementation/configuration/include/internal.hpp.in
@@ -11,15 +11,21 @@
#define VSOMEIP_ENV_APPLICATION_NAME "VSOMEIP_APPLICATION_NAME"
#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_DEFAULT_CONFIGURATION_FILE "/etc/vsomeip.json"
#define VSOMEIP_LOCAL_CONFIGURATION_FILE "./vsomeip.json"
+#define VSOMEIP_MANDATORY_CONFIGURATION_FILES "vsomeip_std.json,vsomeip_app.json,vsomeip_plc.json"
-#define VSOMEIP_DEFAULT_CONFIGURATION_FOLDER "/etc/vsomeip"
-#define VSOMEIP_LOCAL_CONFIGURATION_FOLDER "./vsomeip"
+#define VSOMEIP_DEFAULT_CONFIGURATION_FOLDER "/etc/vsomeip"
+#define VSOMEIP_LOCAL_CONFIGURATION_FOLDER "./vsomeip"
#define VSOMEIP_BASE_PATH "/tmp/vsomeip-"
+#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"
+
#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"
@@ -45,6 +51,8 @@
#define VSOMEIP_MAX_DISPATCHERS 10
#define VSOMEIP_MAX_DISPATCH_TIME 100
+#define VSOMEIP_MAX_DESERIALIZER 5
+
#define VSOMEIP_COMMAND_HEADER_SIZE 7
#define VSOMEIP_COMMAND_TYPE_POS 0
@@ -57,6 +65,7 @@
#define VSOMEIP_DEREGISTER_APPLICATION 0x01
#define VSOMEIP_APPLICATION_LOST 0x02
#define VSOMEIP_ROUTING_INFO 0x03
+#define VSOMEIP_REGISTERED_ACK 0x04
#define VSOMEIP_PING 0x0E
#define VSOMEIP_PONG 0x0F
diff --git a/implementation/configuration/include/policy.hpp b/implementation/configuration/include/policy.hpp
new file mode 100644
index 0000000..c7a5e36
--- /dev/null
+++ b/implementation/configuration/include/policy.hpp
@@ -0,0 +1,29 @@
+// Copyright (C) 2014-2016 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_CFG_POLICY_HPP
+#define VSOMEIP_CFG_POLICY_HPP
+
+#include <memory>
+
+#include <vsomeip/primitive_types.hpp>
+
+namespace vsomeip {
+namespace cfg {
+
+struct policy {
+ std::set<std::pair<service_t, instance_t>> allowed_services_;
+ std::set<std::pair<service_t, instance_t>> allowed_offers_;
+ std::set<std::pair<service_t, instance_t>> denied_services_;
+ std::set<std::pair<service_t, instance_t>> denied_offers_;
+ std::uint32_t uid_;
+ std::uint32_t gid_;
+ bool allow_;
+};
+
+} // namespace cfg
+} // namespace vsomeip
+
+#endif // VSOMEIP_CFG_POLICY_HPP
diff --git a/implementation/configuration/include/trace.hpp b/implementation/configuration/include/trace.hpp
index 3ffdf00..ebfc5bb 100644
--- a/implementation/configuration/include/trace.hpp
+++ b/implementation/configuration/include/trace.hpp
@@ -6,6 +6,9 @@
#ifndef CONFIGURATION_INCLUDE_TRACE_HPP_
#define CONFIGURATION_INCLUDE_TRACE_HPP_
+#include <string>
+#include <vector>
+
#include <vsomeip/primitive_types.hpp>
#include "../../tracing/include/defines.hpp"
diff --git a/implementation/configuration/src/configuration.cpp b/implementation/configuration/src/configuration.cpp
index 0994dcd..ea5bcda 100644
--- a/implementation/configuration/src/configuration.cpp
+++ b/implementation/configuration/src/configuration.cpp
@@ -5,15 +5,32 @@
#include "../include/configuration_impl.hpp"
-namespace vsomeip {
+#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)
-std::shared_ptr<configuration> configuration::get(
- const std::set<std::string> &_input) {
- return cfg::configuration_impl::get(_input);
+INITIALIZER(init_vsomeip_cfg) {
+ VSOMEIP_CFG_RUNTIME_SYMBOL = vsomeip::configuration::get();
}
+#endif
+
+namespace vsomeip {
-void configuration::reset() {
- cfg::configuration_impl::reset();
+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 ef5b706..c4fefb9 100644
--- a/implementation/configuration/src/configuration_impl.cpp
+++ b/implementation/configuration/src/configuration_impl.cpp
@@ -3,7 +3,9 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#include <cctype>
#include <fstream>
+#include <functional>
#include <set>
#include <sstream>
@@ -30,128 +32,53 @@
namespace vsomeip {
namespace cfg {
-std::shared_ptr<configuration_impl> configuration_impl::the_configuration;
-std::mutex configuration_impl::mutex_;
-
-std::shared_ptr<configuration> configuration_impl::get(
- const std::set<std::string> &_input) {
- std::shared_ptr<configuration> its_configuration;
- std::lock_guard<std::mutex> its_lock(mutex_);
-
- std::set<std::string> failed_files;
- static bool has_reading_failed(false);
-
- if (!the_configuration) {
- std::chrono::steady_clock::time_point begin = std::chrono::steady_clock::now();
-
- the_configuration = std::make_shared<configuration_impl>();
- std::vector<element> its_configuration_elements;
-
- // Load logger configuration first
- for (auto i : _input) {
- if (utility::is_file(i)) {
- boost::property_tree::ptree its_tree;
- try {
- boost::property_tree::json_parser::read_json(i, its_tree);
- its_configuration_elements.push_back({ i, its_tree });
- }
- catch (boost::property_tree::json_parser_error &e) {
-#ifdef WIN32
- e; // silence MSVC warining C4101
-#endif
- failed_files.insert(i);
- }
- } else if (utility::is_folder(i)) {
- boost::filesystem::path its_path(i);
- for (auto j = boost::filesystem::directory_iterator(its_path);
- j != boost::filesystem::directory_iterator();
- j++) {
- auto its_file_path = j->path();
- if (!boost::filesystem::is_directory(its_file_path)) {
- std::string its_name = its_file_path.string();
- boost::property_tree::ptree its_tree;
- try {
- boost::property_tree::json_parser::read_json(its_name, its_tree);
- its_configuration_elements.push_back({its_name, its_tree});
- }
- catch (...) {
- failed_files.insert(its_name);
- }
- }
- }
- }
- }
-
- // Load log configuration
- the_configuration->load_log(its_configuration_elements);
-
- // Check whether reading of configuration file(s) succeeded.
- if (!failed_files.empty()) {
- has_reading_failed = true;
- for (auto its_failed : failed_files)
- VSOMEIP_ERROR << "Reading of configuration file \""
- << its_failed << "\" failed.";
- } else {
- // Load other configuration parts
- std::sort(its_configuration_elements.begin(),
- its_configuration_elements.end());
- for (auto e : its_configuration_elements)
- the_configuration->load(e);
- // set global unicast address for all services with magic cookies enabled
- the_configuration->set_magic_cookies_unicast_address();
- }
- std::chrono::steady_clock::time_point end = std::chrono::steady_clock::now();
- VSOMEIP_DEBUG << "Parsed vSomeIP configuration in "
- << std::chrono::duration_cast<std::chrono::milliseconds>(end - begin).count()
- << "ms";
- }
-
- // There is only one attempt to read the configuration file(s).
- // If it has failed, we must not return the configuration object.
- if (has_reading_failed)
- return nullptr;
-
- return the_configuration;
-}
-
-void configuration_impl::reset() {
- the_configuration.reset();
-}
-
-configuration_impl::configuration_impl() :
- diagnosis_(VSOMEIP_DIAGNOSIS_ADDRESS),
- has_console_log_(true),
- has_file_log_(false),
- has_dlt_log_(false),
- logfile_("/tmp/vsomeip.log"),
- loglevel_(boost::log::trivial::severity_level::info),
- is_sd_enabled_(VSOMEIP_SD_DEFAULT_ENABLED),
- sd_protocol_(VSOMEIP_SD_DEFAULT_PROTOCOL),
- sd_multicast_(VSOMEIP_SD_DEFAULT_MULTICAST),
- sd_port_(VSOMEIP_SD_DEFAULT_PORT),
- sd_initial_delay_min_(VSOMEIP_SD_DEFAULT_INITIAL_DELAY_MIN),
- sd_initial_delay_max_(VSOMEIP_SD_DEFAULT_INITIAL_DELAY_MAX),
- sd_repetitions_base_delay_(VSOMEIP_SD_DEFAULT_REPETITIONS_BASE_DELAY),
- sd_repetitions_max_(VSOMEIP_SD_DEFAULT_REPETITIONS_MAX),
- sd_ttl_(VSOMEIP_SD_DEFAULT_TTL),
- sd_cyclic_offer_delay_(VSOMEIP_SD_DEFAULT_CYCLIC_OFFER_DELAY),
- sd_request_response_delay_(VSOMEIP_SD_DEFAULT_REQUEST_RESPONSE_DELAY),
- max_configured_message_size_(0),
- trace_(std::make_shared<trace>()),
- watchdog_(std::make_shared<watchdog>()),
- log_version_(true),
- log_version_interval_(10),
- permissions_shm_(VSOMEIP_DEFAULT_SHM_PERMISSION),
- umask_(VSOMEIP_DEFAULT_UMASK_LOCAL_ENDPOINTS) {
+std::shared_ptr<configuration> configuration_impl::get() {
+ return std::make_shared<configuration_impl>();
+}
+
+configuration_impl::configuration_impl()
+ : is_loaded_(false),
+ is_logging_loaded_(false),
+ diagnosis_(VSOMEIP_DIAGNOSIS_ADDRESS),
+ has_console_log_(true),
+ has_file_log_(false),
+ has_dlt_log_(false),
+ logfile_("/tmp/vsomeip.log"),
+ loglevel_(boost::log::trivial::severity_level::info),
+ is_sd_enabled_(VSOMEIP_SD_DEFAULT_ENABLED),
+ sd_protocol_(VSOMEIP_SD_DEFAULT_PROTOCOL),
+ sd_multicast_(VSOMEIP_SD_DEFAULT_MULTICAST),
+ sd_port_(VSOMEIP_SD_DEFAULT_PORT),
+ sd_initial_delay_min_(VSOMEIP_SD_DEFAULT_INITIAL_DELAY_MIN),
+ sd_initial_delay_max_(VSOMEIP_SD_DEFAULT_INITIAL_DELAY_MAX),
+ sd_repetitions_base_delay_(VSOMEIP_SD_DEFAULT_REPETITIONS_BASE_DELAY),
+ sd_repetitions_max_(VSOMEIP_SD_DEFAULT_REPETITIONS_MAX),
+ sd_ttl_(VSOMEIP_SD_DEFAULT_TTL),
+ sd_cyclic_offer_delay_(VSOMEIP_SD_DEFAULT_CYCLIC_OFFER_DELAY),
+ sd_request_response_delay_(VSOMEIP_SD_DEFAULT_REQUEST_RESPONSE_DELAY),
+ sd_offer_debounce_time_(VSOMEIP_SD_DEFAULT_OFFER_DEBOUNCE_TIME),
+ max_configured_message_size_(0),
+ trace_(std::make_shared<trace>()),
+ watchdog_(std::make_shared<watchdog>()),
+ log_version_(true),
+ log_version_interval_(10),
+ permissions_shm_(VSOMEIP_DEFAULT_SHM_PERMISSION),
+ umask_(VSOMEIP_DEFAULT_UMASK_LOCAL_ENDPOINTS),
+ policy_enabled_(false),
+ check_credentials_(false) {
unicast_ = unicast_.from_string(VSOMEIP_UNICAST_ADDRESS);
for (auto i = 0; i < ET_MAX; i++)
is_configured_[i] = false;
}
-configuration_impl::configuration_impl(const configuration_impl &_other) :
- max_configured_message_size_(0),
- permissions_shm_(VSOMEIP_DEFAULT_SHM_PERMISSION),
- umask_(VSOMEIP_DEFAULT_UMASK_LOCAL_ENDPOINTS) {
+configuration_impl::configuration_impl(const configuration_impl &_other)
+ : std::enable_shared_from_this<configuration_impl>(_other),
+ is_loaded_(_other.is_loaded_),
+ is_logging_loaded_(_other.is_logging_loaded_),
+ mandatory_(_other.mandatory_),
+ max_configured_message_size_(0),
+ permissions_shm_(VSOMEIP_DEFAULT_SHM_PERMISSION),
+ umask_(VSOMEIP_DEFAULT_UMASK_LOCAL_ENDPOINTS) {
applications_.insert(_other.applications_.begin(), _other.applications_.end());
services_.insert(_other.services_.begin(), _other.services_.end());
@@ -180,57 +107,216 @@ configuration_impl::configuration_impl(const configuration_impl &_other) :
sd_ttl_ = _other.sd_ttl_;
sd_cyclic_offer_delay_= _other.sd_cyclic_offer_delay_;
sd_request_response_delay_= _other.sd_request_response_delay_;
+ sd_offer_debounce_time_ = _other.sd_offer_debounce_time_;
trace_ = std::make_shared<trace>(*_other.trace_.get());
watchdog_ = std::make_shared<watchdog>(*_other.watchdog_.get());
+ log_version_ = _other.log_version_;
+ log_version_interval_ = _other.log_version_interval_;
magic_cookies_.insert(_other.magic_cookies_.begin(), _other.magic_cookies_.end());
for (auto i = 0; i < ET_MAX; i++)
is_configured_[i] = _other.is_configured_[i];
+
+ policy_enabled_ = _other.policy_enabled_;
+ check_credentials_ = _other.check_credentials_;
}
configuration_impl::~configuration_impl() {
}
-void configuration_impl::load(const element &_element) {
- try {
- // Read the configuration data
- get_someip_configuration(_element);
- get_services_configuration(_element.tree_);
- get_clients_configuration(_element.tree_);
- get_payload_sizes_configuration(_element.tree_);
- get_routing_configuration(_element);
- get_permission_configuration(_element);
- get_service_discovery_configuration(_element);
- get_applications_configuration(_element);
- get_trace_configuration(_element);
- get_supports_selective_broadcasts(_element.tree_);
- get_watchdog_configuration(_element);
- get_internal_services(_element.tree_);
- } catch (std::exception &e) {
-#ifdef WIN32
- e; // silence MSVC warning C4101
-#endif
+bool configuration_impl::load(const std::string &_name) {
+ std::lock_guard<std::mutex> its_lock(mutex_);
+ if (is_loaded_)
+ return true;
+
+ // Predefine file / folder
+ std::string its_file(VSOMEIP_DEFAULT_CONFIGURATION_FILE); // configuration file
+ std::string its_folder(VSOMEIP_DEFAULT_CONFIGURATION_FOLDER); // configuration folder
+
+ // Override with local file / folder (if existing)
+ std::string its_local_file(VSOMEIP_LOCAL_CONFIGURATION_FILE);
+ if (utility::is_file(its_local_file)) {
+ its_file = its_local_file;
+ }
+
+ std::string its_local_folder(VSOMEIP_LOCAL_CONFIGURATION_FOLDER);
+ if (utility::is_folder(its_local_folder)) {
+ its_folder = its_local_folder;
+ }
+
+ // Finally, 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)) {
+ its_file = its_env;
+ its_folder = "";
+ } else if (utility::is_folder(its_env)) {
+ its_folder = its_env;
+ its_file = "";
+ }
+ }
+
+ std::set<std::string> its_input;
+ if (its_file != "") {
+ its_input.insert(its_file);
+ }
+ if (its_folder != "") {
+ its_input.insert(its_folder);
+ }
+
+ // Determine standard configuration file
+ its_env = getenv(VSOMEIP_ENV_MANDATORY_CONFIGURATION_FILES);
+ if (nullptr != its_env) {
+ std::string its_temp(its_env);
+ set_mandatory(its_temp);
+ } else {
+ set_mandatory(VSOMEIP_MANDATORY_CONFIGURATION_FILES);
+ }
+
+ // Start reading
+ std::set<std::string> its_failed;
+
+ std::chrono::steady_clock::time_point begin = std::chrono::steady_clock::now();
+ std::vector<element> its_mandatory_elements;
+ std::vector<element> its_optional_elements;
+
+ // Dummy initialization; maybe we'll find no logging configuration
+ logger_impl::init(shared_from_this());
+
+ // Look for the standard configuration file
+ read_data(its_input, its_mandatory_elements, its_failed, true);
+ load_data(its_mandatory_elements, true, false);
+
+ // If the configuration is incomplete, this is the routing manager configuration or
+ // the routing is yet unknown, read the full set of configuration files
+ if (its_mandatory_elements.empty() ||
+ _name == get_routing_host() ||
+ "" == get_routing_host()) {
+ read_data(its_input, its_optional_elements, its_failed, false);
+ load_data(its_mandatory_elements, false, true);
+ load_data(its_optional_elements, true, true);
+ }
+
+ // Tell, if reading of configuration file(s) failed.
+ // (This may file if the logger configuration is incomplete/missing).
+ for (auto f : its_failed)
+ VSOMEIP_WARNING << "Reading of configuration file \""
+ << f << "\" failed. Configuration may be incomplete.";
+
+ // set global unicast address for all services with magic cookies enabled
+ set_magic_cookies_unicast_address();
+
+ std::chrono::steady_clock::time_point end = std::chrono::steady_clock::now();
+ VSOMEIP_DEBUG << "Parsed vsomeip configuration in "
+ << std::chrono::duration_cast<std::chrono::milliseconds>(end - begin).count()
+ << "ms";
+
+ if (utility::is_file(its_file))
+ VSOMEIP_INFO << "Using configuration file: \"" << its_file << "\".";
+
+ if (utility::is_folder(its_folder))
+ VSOMEIP_INFO << "Using configuration folder: \"" << its_folder << "\".";
+
+ if (policy_enabled_ && check_credentials_)
+ VSOMEIP_INFO << "Security configuration is active.";
+
+ is_loaded_ = true;
+
+ return is_loaded_;
+}
+
+void configuration_impl::read_data(const std::set<std::string> &_input,
+ std::vector<element> &_elements, std::set<std::string> &_failed,
+ bool _mandatory_only) {
+ for (auto i : _input) {
+ if (utility::is_file(i)) {
+ if (is_mandatory(i) != _mandatory_only) {
+ boost::property_tree::ptree its_tree;
+ try {
+ boost::property_tree::json_parser::read_json(i, its_tree);
+ _elements.push_back({ i, its_tree });
+ }
+ catch (boost::property_tree::json_parser_error &e) {
+ #ifdef WIN32
+ e; // silence MSVC warning C4101
+ #endif
+ _failed.insert(i);
+ }
+ }
+ } else if (utility::is_folder(i)) {
+ boost::filesystem::path its_path(i);
+ for (auto j = boost::filesystem::directory_iterator(its_path);
+ j != boost::filesystem::directory_iterator();
+ j++) {
+ auto its_file_path = j->path();
+ if (!boost::filesystem::is_directory(its_file_path)) {
+ std::string its_name = its_file_path.string();
+ if (is_mandatory(its_name) == _mandatory_only) {
+ boost::property_tree::ptree its_tree;
+ try {
+ boost::property_tree::json_parser::read_json(its_name, its_tree);
+ _elements.push_back({its_name, its_tree});
+ }
+ catch (...) {
+ _failed.insert(its_name);
+ }
+ }
+ }
+ }
+ }
}
}
-void configuration_impl::load_log(const std::vector<element> &_elements) {
+
+bool configuration_impl::load_data(const std::vector<element> &_elements,
+ bool _load_mandatory, bool _load_optional) {
+ // Load logging configuration data
std::set<std::string> its_warnings;
+ if (!is_logging_loaded_) {
+ for (auto e : _elements)
+ is_logging_loaded_
+ = load_logging(e, its_warnings) || is_logging_loaded_;
+
+ if (is_logging_loaded_) {
+ logger_impl::init(shared_from_this());
+ for (auto w : its_warnings)
+ VSOMEIP_WARNING << w;
+ }
+ }
- // Read the logger configuration(s)
- for (auto e : _elements)
- get_logging_configuration(e, its_warnings);
+ bool has_routing(false);
+ bool has_applications(false);
+ if (_load_mandatory) {
+ // Load mandatory configuration data
+ for (auto e : _elements) {
+ has_routing = load_routing(e) || has_routing;
+ has_applications = load_applications(e) || has_applications;
+ load_diagnosis_address(e);
+ load_payload_sizes(e);
+ load_permissions(e);
+ load_policies(e);
+ load_tracing(e);
+ }
+ }
- // Initialize logger
- logger_impl::init(the_configuration);
+ if (_load_optional) {
+ for (auto e : _elements) {
+ load_unicast_address(e);
+ load_service_discovery(e);
+ load_services(e);
+ load_internal_services(e);
+ load_clients(e);
+ load_watchdog(e);
+ load_selective_broadcasts_support(e);
+ }
+ }
- // Print warnings after(!) logger initialization
- for (auto w : its_warnings)
- VSOMEIP_WARNING << w;
+ return is_logging_loaded_ && has_routing && has_applications;
}
-void configuration_impl::get_logging_configuration(
+bool configuration_impl::load_logging(
const element &_element, std::set<std::string> &_warnings) {
try {
auto its_logging = _element.tree_.get_child("logging");
@@ -307,165 +393,383 @@ void configuration_impl::get_logging_configuration(
}
}
} catch (...) {
+ return false;
}
+ return true;
}
-void configuration_impl::get_someip_configuration(
- const element &_element) {
+bool configuration_impl::load_routing(const element &_element) {
try {
- if (is_configured_[ET_UNICAST]) {
- VSOMEIP_WARNING << "Multiple definitions for unicast."
- "Ignoring definition from " << _element.name_;
+ auto its_routing = _element.tree_.get_child("routing");
+ if (is_configured_[ET_ROUTING]) {
+ VSOMEIP_WARNING << "Multiple definitions of routing."
+ << " Ignoring definition from " << _element.name_;
} else {
- std::string its_value = _element.tree_.get<std::string>("unicast");
- unicast_ = unicast_.from_string(its_value);
- is_configured_[ET_UNICAST] = true;
+ routing_host_ = its_routing.data();
+ is_configured_[ET_ROUTING] = true;
}
} catch (...) {
+ return false;
}
+ return true;
+}
+
+bool configuration_impl::load_applications(const element &_element) {
try {
- if (is_configured_[ET_DIAGNOSIS]) {
- VSOMEIP_WARNING << "Multiple definitions for diagnosis."
- "Ignoring definition from " << _element.name_;
- } else {
- std::string its_value = _element.tree_.get<std::string>("diagnosis");
- std::stringstream its_converter;
+ std::stringstream its_converter;
+ auto its_applications = _element.tree_.get_child("applications");
+ for (auto i = its_applications.begin();
+ i != its_applications.end();
+ ++i) {
+ load_application_data(i->second, _element.name_);
+ }
+ } catch (...) {
+ return false;
+ }
+ return true;
+}
+void configuration_impl::load_application_data(
+ const boost::property_tree::ptree &_tree, const std::string &_file_name) {
+ std::string its_name("");
+ client_t its_id(0);
+ std::size_t its_max_dispatchers(VSOMEIP_MAX_DISPATCHERS);
+ std::size_t its_max_dispatch_time(VSOMEIP_MAX_DISPATCH_TIME);
+ for (auto i = _tree.begin(); i != _tree.end(); ++i) {
+ std::string its_key(i->first);
+ std::string its_value(i->second.data());
+ std::stringstream its_converter;
+ if (its_key == "name") {
+ its_name = its_value;
+ } else if (its_key == "id") {
if (its_value.size() > 1 && its_value[0] == '0' && its_value[1] == 'x') {
its_converter << std::hex << its_value;
} else {
its_converter << std::dec << its_value;
}
- its_converter >> diagnosis_;
- is_configured_[ET_DIAGNOSIS] = true;
+ its_converter >> its_id;
+ } else if (its_key == "max_dispatchers") {
+ its_converter << std::dec << its_value;
+ its_converter >> its_max_dispatchers;
+ } else if (its_key == "max_dispatch_time") {
+ its_converter << std::dec << its_value;
+ its_converter >> its_max_dispatch_time;
+ }
+ }
+ if (its_name != "" && its_id != 0) {
+ if (applications_.find(its_name) == applications_.end()) {
+ if (!is_configured_client_id(its_id)) {
+ applications_[its_name]
+ = std::make_tuple(its_id, its_max_dispatchers, its_max_dispatch_time);
+ client_identifiers_.insert(its_id);
+ } else {
+ VSOMEIP_WARNING << "Multiple configurations for application "
+ << its_name << ". Ignoring a configuration from "
+ << _file_name;
+ }
+ } else {
+ VSOMEIP_WARNING << "Multiple configurations for application "
+ << its_name << ". Ignoring a configuration from "
+ << _file_name;
+ }
+ }
+}
+
+void configuration_impl::load_tracing(const element &_element) {
+ try {
+ std::stringstream its_converter;
+ auto its_trace_configuration = _element.tree_.get_child("tracing");
+ for(auto i = its_trace_configuration.begin();
+ i != its_trace_configuration.end();
+ ++i) {
+ std::string its_key(i->first);
+ std::string its_value(i->second.data());
+ if(its_key == "enable") {
+ if (is_configured_[ET_TRACING_ENABLE]) {
+ VSOMEIP_WARNING << "Multiple definitions of tracing.enable."
+ << " Ignoring definition from " << _element.name_;
+ } else {
+ trace_->is_enabled_ = (its_value == "true");
+ is_configured_[ET_TRACING_ENABLE] = true;
+ }
+ } else if (its_key == "sd_enable") {
+ if (is_configured_[ET_TRACING_SD_ENABLE]) {
+ VSOMEIP_WARNING << "Multiple definitions of tracing.sd_enable."
+ << " Ignoring definition from " << _element.name_;
+ } else {
+ trace_->is_sd_enabled_ = (its_value == "true");
+ is_configured_[ET_TRACING_SD_ENABLE] = true;
+ }
+ } else if(its_key == "channels") {
+ load_trace_channels(i->second);
+ } else if(its_key == "filters") {
+ load_trace_filters(i->second);
+ }
}
} catch (...) {
+ // intentionally left empty
}
}
-void configuration_impl::get_services_configuration(
+void configuration_impl::load_trace_channels(
const boost::property_tree::ptree &_tree) {
try {
- auto its_services = _tree.get_child("services");
- for (auto i = its_services.begin(); i != its_services.end(); ++i)
- get_service_configuration(i->second, "local");
- } catch (...) {
- try {
- auto its_servicegroups = _tree.get_child("servicegroups");
- for (auto i = its_servicegroups.begin(); i != its_servicegroups.end(); ++i)
- get_servicegroup_configuration(i->second);
- } catch (...) {
- // intentionally left empty!
+ for(auto i = _tree.begin(); i != _tree.end(); ++i) {
+ if(i == _tree.begin())
+ trace_->channels_.clear();
+ load_trace_channel(i->second);
}
+ } catch (...) {
+ // intentionally left empty
}
}
-void configuration_impl::set_magic_cookies_unicast_address() {
- // get services with static routing that have magic cookies enabled
- std::map<std::string, std::set<uint16_t> > its_magic_cookies_ = magic_cookies_;
- its_magic_cookies_.erase("local");
-
- //set unicast address of host for all services without static routing
- its_magic_cookies_[get_unicast_address().to_string()].insert(magic_cookies_["local"].begin(),
- magic_cookies_["local"].end());
- magic_cookies_.clear();
- magic_cookies_ = its_magic_cookies_;
+void configuration_impl::load_trace_channel(
+ const boost::property_tree::ptree &_tree) {
+ std::shared_ptr<trace_channel> its_channel = std::make_shared<trace_channel>();
+ for(auto i = _tree.begin(); i != _tree.end(); ++i) {
+ std::string its_key = i->first;
+ std::string its_value = i->second.data();
+ if(its_key == "name") {
+ its_channel->name_ = its_value;
+ } else if(its_key == "id") {
+ its_channel->id_ = its_value;
+ }
+ }
+ trace_->channels_.push_back(its_channel);
}
-
-void configuration_impl::get_clients_configuration(
+void configuration_impl::load_trace_filters(
const boost::property_tree::ptree &_tree) {
try {
- auto its_clients = _tree.get_child("clients");
- for (auto i = its_clients.begin(); i != its_clients.end(); ++i)
- get_client_configuration(i->second);
+ for(auto i = _tree.begin(); i != _tree.end(); ++i) {
+ load_trace_filter(i->second);
+ }
} catch (...) {
- // intentionally left empty!
+ // intentionally left empty
}
}
-void configuration_impl::get_payload_sizes_configuration(
+void configuration_impl::load_trace_filter(
const boost::property_tree::ptree &_tree) {
- const std::string payload_sizes("payload-sizes");
- try {
- if (_tree.get_child_optional(payload_sizes)) {
- const std::string unicast("unicast");
- const std::string ports("ports");
- const std::string port("port");
- const std::string max_payload_size("max-payload-size");
- auto its_ps = _tree.get_child(payload_sizes);
- for (auto i = its_ps.begin(); i != its_ps.end(); ++i) {
- if (!i->second.get_child_optional(unicast)
- || !i->second.get_child_optional(ports)) {
- continue;
- }
- std::string its_unicast(i->second.get_child(unicast).data());
- for (auto j = i->second.get_child(ports).begin();
- j != i->second.get_child(ports).end(); ++j) {
-
- if (!j->second.get_child_optional(port)
- || !j->second.get_child_optional(max_payload_size)) {
- continue;
- }
-
- std::uint16_t its_port = ILLEGAL_PORT;
- std::uint32_t its_message_size = 0;
-
- try {
- std::string p(j->second.get_child(port).data());
- its_port = static_cast<std::uint16_t>(std::stoul(p.c_str(),
- NULL, 10));
- std::string s(j->second.get_child(max_payload_size).data());
- // add 16 Byte for the SOME/IP header
- its_message_size = static_cast<std::uint32_t>(std::stoul(
- s.c_str(),
- NULL, 10) + 16);
- } catch (const std::exception &e) {
- VSOMEIP_ERROR << __func__ << ":" << e.what();
- }
+ std::shared_ptr<trace_filter_rule> its_filter_rule = std::make_shared<trace_filter_rule>();
+ for(auto i = _tree.begin(); i != _tree.end(); ++i) {
+ std::string its_key = i->first;
+ std::string its_value = i->second.data();
+ if(its_key == "channel") {
+ its_filter_rule->channel_ = its_value;
+ } else {
+ load_trace_filter_expressions(i->second, its_key, its_filter_rule);
+ }
+ }
+ trace_->filter_rules_.push_back(its_filter_rule);
+}
- if (its_port == ILLEGAL_PORT || its_message_size == 0) {
- continue;
- }
- if(max_configured_message_size_ < its_message_size) {
- max_configured_message_size_ = its_message_size;
- }
+void configuration_impl::load_trace_filter_expressions(
+ const boost::property_tree::ptree &_tree,
+ std::string &_criteria,
+ std::shared_ptr<trace_filter_rule> &_filter_rule) {
+ for(auto i = _tree.begin(); i != _tree.end(); ++i) {
+ std::string its_value = i->second.data();
+ std::stringstream its_converter;
- message_sizes_[its_unicast][its_port] = its_message_size;
- }
+ if(_criteria == "services") {
+ service_t its_id = NO_TRACE_FILTER_EXPRESSION;
+ if (its_value.size() > 1 && its_value[0] == '0' && its_value[1] == 'x') {
+ its_converter << std::hex << its_value;
+ } else {
+ its_converter << std::dec << its_value;
}
+ its_converter >> its_id;
+ _filter_rule->services_.push_back(its_id);
+ } else if(_criteria == "methods") {
+ method_t its_id = NO_TRACE_FILTER_EXPRESSION;
+ if (its_value.size() > 1 && its_value[0] == '0' && its_value[1] == 'x') {
+ its_converter << std::hex << its_value;
+ } else {
+ its_converter << std::dec << its_value;
+ }
+ its_converter >> its_id;
+ _filter_rule->methods_.push_back(its_id);
+ } else if(_criteria == "clients") {
+ client_t its_id = NO_TRACE_FILTER_EXPRESSION;
+ if (its_value.size() > 1 && its_value[0] == '0' && its_value[1] == 'x') {
+ its_converter << std::hex << its_value;
+ } else {
+ its_converter << std::dec << its_value;
+ }
+ its_converter >> its_id;
+ _filter_rule->clients_.push_back(its_id);
+ }
+ }
+}
+
+void configuration_impl::load_unicast_address(const element &_element) {
+ try {
+ std::string its_value = _element.tree_.get<std::string>("unicast");
+ if (is_configured_[ET_UNICAST]) {
+ VSOMEIP_WARNING << "Multiple definitions for unicast."
+ "Ignoring definition from " << _element.name_;
+ } else {
+ unicast_ = unicast_.from_string(its_value);
+ is_configured_[ET_UNICAST] = true;
}
} catch (...) {
+ // intentionally left empty!
}
}
-void configuration_impl::get_servicegroup_configuration(
- const boost::property_tree::ptree &_tree) {
+void configuration_impl::load_diagnosis_address(const element &_element) {
try {
- std::string its_unicast_address("local");
+ std::string its_value = _element.tree_.get<std::string>("diagnosis");
+ if (is_configured_[ET_DIAGNOSIS]) {
+ VSOMEIP_WARNING << "Multiple definitions for diagnosis."
+ "Ignoring definition from " << _element.name_;
+ } else {
+ std::stringstream its_converter;
- for (auto i = _tree.begin(); i != _tree.end(); ++i) {
- std::string its_key(i->first);
- if (its_key == "unicast") {
- its_unicast_address = i->second.data();
- break;
+ if (its_value.size() > 1 && its_value[0] == '0' && its_value[1] == 'x') {
+ its_converter << std::hex << its_value;
+ } else {
+ its_converter << std::dec << its_value;
}
+ its_converter >> diagnosis_;
+ is_configured_[ET_DIAGNOSIS] = true;
}
+ } catch (...) {
+ // intentionally left empty
+ }
+}
- for (auto i = _tree.begin(); i != _tree.end(); ++i) {
+void configuration_impl::load_service_discovery(
+ const element &_element) {
+ try {
+ auto its_service_discovery = _element.tree_.get_child("service-discovery");
+ for (auto i = its_service_discovery.begin();
+ i != its_service_discovery.end(); ++i) {
std::string its_key(i->first);
- if (its_key == "delays") {
- get_delays_configuration(i->second);
- } else if (its_key == "services") {
- for (auto j = i->second.begin(); j != i->second.end(); ++j)
- get_service_configuration(j->second, its_unicast_address);
+ std::string its_value(i->second.data());
+ std::stringstream its_converter;
+ if (its_key == "enable") {
+ if (is_configured_[ET_SERVICE_DISCOVERY_ENABLE]) {
+ VSOMEIP_WARNING << "Multiple definitions for service_discovery.enabled."
+ " Ignoring definition from " << _element.name_;
+ } else {
+ is_sd_enabled_ = (its_value == "true");
+ is_configured_[ET_SERVICE_DISCOVERY_ENABLE] = true;
+ }
+ } else if (its_key == "multicast") {
+ if (is_configured_[ET_SERVICE_DISCOVERY_MULTICAST]) {
+ VSOMEIP_WARNING << "Multiple definitions for service_discovery.multicast."
+ " Ignoring definition from " << _element.name_;
+ } else {
+ sd_multicast_ = its_value;
+ is_configured_[ET_SERVICE_DISCOVERY_MULTICAST] = true;
+ }
+ } else if (its_key == "port") {
+ if (is_configured_[ET_SERVICE_DISCOVERY_PORT]) {
+ VSOMEIP_WARNING << "Multiple definitions for service_discovery.port."
+ " Ignoring definition from " << _element.name_;
+ } else {
+ its_converter << its_value;
+ its_converter >> sd_port_;
+ if (!sd_port_) {
+ sd_port_ = VSOMEIP_SD_DEFAULT_PORT;
+ } else {
+ is_configured_[ET_SERVICE_DISCOVERY_PORT] = true;
+ }
+ }
+ } else if (its_key == "protocol") {
+ if (is_configured_[ET_SERVICE_DISCOVERY_PROTOCOL]) {
+ VSOMEIP_WARNING << "Multiple definitions for service_discovery.protocol."
+ " Ignoring definition from " << _element.name_;
+ } else {
+ sd_protocol_ = its_value;
+ is_configured_[ET_SERVICE_DISCOVERY_PROTOCOL] = true;
+ }
+ } else if (its_key == "initial_delay_min") {
+ if (is_configured_[ET_SERVICE_DISCOVERY_INITIAL_DELAY_MIN]) {
+ VSOMEIP_WARNING << "Multiple definitions for service_discovery.initial_delay_min."
+ " Ignoring definition from " << _element.name_;
+ } else {
+ its_converter << its_value;
+ its_converter >> sd_initial_delay_min_;
+ is_configured_[ET_SERVICE_DISCOVERY_INITIAL_DELAY_MIN] = true;
+ }
+ } else if (its_key == "initial_delay_max") {
+ if (is_configured_[ET_SERVICE_DISCOVERY_INITIAL_DELAY_MAX]) {
+ VSOMEIP_WARNING << "Multiple definitions for service_discovery.initial_delay_max."
+ " Ignoring definition from " << _element.name_;
+ } else {
+ its_converter << its_value;
+ its_converter >> sd_initial_delay_max_;
+ is_configured_[ET_SERVICE_DISCOVERY_INITIAL_DELAY_MAX] = true;
+ }
+ } else if (its_key == "repetitions_base_delay") {
+ if (is_configured_[ET_SERVICE_DISCOVERY_REPETITION_BASE_DELAY]) {
+ VSOMEIP_WARNING << "Multiple definitions for service_discovery.repetition_base_delay."
+ " Ignoring definition from " << _element.name_;
+ } else {
+ its_converter << its_value;
+ its_converter >> sd_repetitions_base_delay_;
+ is_configured_[ET_SERVICE_DISCOVERY_REPETITION_BASE_DELAY] = true;
+ }
+ } else if (its_key == "repetitions_max") {
+ if (is_configured_[ET_SERVICE_DISCOVERY_REPETITION_MAX]) {
+ VSOMEIP_WARNING << "Multiple definitions for service_discovery.repetition_max."
+ " Ignoring definition from " << _element.name_;
+ } else {
+ int tmp;
+ its_converter << its_value;
+ its_converter >> tmp;
+ sd_repetitions_max_ = (uint8_t)tmp;
+ is_configured_[ET_SERVICE_DISCOVERY_REPETITION_MAX] = true;
+ }
+ } else if (its_key == "ttl") {
+ if (is_configured_[ET_SERVICE_DISCOVERY_TTL]) {
+ VSOMEIP_WARNING << "Multiple definitions for service_discovery.ttl."
+ " Ignoring definition from " << _element.name_;
+ } else {
+ its_converter << its_value;
+ its_converter >> sd_ttl_;
+ // We do _not_ accept 0 as this would mean "STOP OFFER"
+ if (sd_ttl_ == 0) sd_ttl_ = VSOMEIP_SD_DEFAULT_TTL;
+ else is_configured_[ET_SERVICE_DISCOVERY_TTL] = true;
+ }
+ } else if (its_key == "cyclic_offer_delay") {
+ if (is_configured_[ET_SERVICE_DISCOVERY_CYCLIC_OFFER_DELAY]) {
+ VSOMEIP_WARNING << "Multiple definitions for service_discovery.cyclic_offer_delay."
+ " Ignoring definition from " << _element.name_;
+ } else {
+ its_converter << its_value;
+ its_converter >> sd_cyclic_offer_delay_;
+ is_configured_[ET_SERVICE_DISCOVERY_CYCLIC_OFFER_DELAY] = true;
+ }
+ } else if (its_key == "request_response_delay") {
+ if (is_configured_[ET_SERVICE_DISCOVERY_REQUEST_RESPONSE_DELAY]) {
+ VSOMEIP_WARNING << "Multiple definitions for service_discovery.request_response_delay."
+ " Ignoring definition from " << _element.name_;
+ } else {
+ its_converter << its_value;
+ its_converter >> sd_request_response_delay_;
+ is_configured_[ET_SERVICE_DISCOVERY_REQUEST_RESPONSE_DELAY] = true;
+ }
+ } else if (its_key == "offer_debounce_time") {
+ if (is_configured_[ET_SERVICE_DISCOVERY_OFFER_DEBOUNCE_TIME]) {
+ VSOMEIP_WARNING << "Multiple definitions for service_discovery.offer_debounce."
+ " Ignoring definition from " << _element.name_;
+ } else {
+ its_converter << its_value;
+ its_converter >> sd_offer_debounce_time_;
+ is_configured_[ET_SERVICE_DISCOVERY_OFFER_DEBOUNCE_TIME] = true;
+ }
}
}
} catch (...) {
}
}
-void configuration_impl::get_delays_configuration(
+void configuration_impl::load_delays(
const boost::property_tree::ptree &_tree) {
try {
std::stringstream its_converter;
@@ -488,6 +792,9 @@ void configuration_impl::get_delays_configuration(
} else if (its_key == "cyclic-request") {
its_converter << std::dec << i->second.data();
its_converter >> sd_request_response_delay_;
+ } else if (its_key == "ttl") {
+ its_converter << std::dec << i->second.data();
+ its_converter >> sd_ttl_;
}
its_converter.str("");
its_converter.clear();
@@ -496,7 +803,50 @@ void configuration_impl::get_delays_configuration(
}
}
-void configuration_impl::get_service_configuration(
+void configuration_impl::load_services(const element &_element) {
+ try {
+ auto its_services = _element.tree_.get_child("services");
+ for (auto i = its_services.begin(); i != its_services.end(); ++i)
+ load_service(i->second, "local");
+ } catch (...) {
+ try {
+ auto its_servicegroups = _element.tree_.get_child("servicegroups");
+ for (auto i = its_servicegroups.begin(); i != its_servicegroups.end(); ++i)
+ load_servicegroup(i->second);
+ } catch (...) {
+ // intentionally left empty
+ }
+ }
+}
+
+void configuration_impl::load_servicegroup(
+ const boost::property_tree::ptree &_tree) {
+ try {
+ std::string its_unicast_address("local");
+
+ for (auto i = _tree.begin(); i != _tree.end(); ++i) {
+ std::string its_key(i->first);
+ if (its_key == "unicast") {
+ its_unicast_address = i->second.data();
+ break;
+ }
+ }
+
+ for (auto i = _tree.begin(); i != _tree.end(); ++i) {
+ std::string its_key(i->first);
+ if (its_key == "delays") {
+ load_delays(i->second);
+ } else if (its_key == "services") {
+ for (auto j = i->second.begin(); j != i->second.end(); ++j)
+ load_service(j->second, its_unicast_address);
+ }
+ }
+ } catch (...) {
+ // Intentionally left empty
+ }
+}
+
+void configuration_impl::load_service(
const boost::property_tree::ptree &_tree,
const std::string &_unicast_address) {
try {
@@ -554,9 +904,9 @@ void configuration_impl::get_service_configuration(
} else if (its_key == "protocol") {
its_service->protocol_ = its_value;
} else if (its_key == "events") {
- get_event_configuration(its_service, i->second);
+ load_event(its_service, i->second);
} else if (its_key == "eventgroups") {
- get_eventgroup_configuration(its_service, i->second);
+ load_eventgroup(its_service, i->second);
} else {
// Trim "its_value"
if (its_value.size() > 1 && its_value[0] == '0' && its_value[1] == 'x') {
@@ -593,80 +943,11 @@ void configuration_impl::get_service_configuration(
}
}
} catch (...) {
+ // Intentionally left empty
}
}
-void configuration_impl::get_client_configuration(
- const boost::property_tree::ptree &_tree) {
- try {
- bool is_loaded(true);
-
- std::shared_ptr<client> its_client(std::make_shared<client>());
-
- for (auto i = _tree.begin(); i != _tree.end(); ++i) {
- std::string its_key(i->first);
- std::string its_value(i->second.data());
- std::stringstream its_converter;
-
- if (its_key == "reliable") {
- its_client->ports_[true] = get_client_port_configuration(i->second);
- } else if (its_key == "unreliable") {
- its_client->ports_[false] = get_client_port_configuration(i->second);
- } else {
- // Trim "its_value"
- if (its_value.size() > 1 && its_value[0] == '0' && its_value[1] == 'x') {
- its_converter << std::hex << its_value;
- } else {
- its_converter << std::dec << its_value;
- }
-
- if (its_key == "service") {
- its_converter >> its_client->service_;
- } else if (its_key == "instance") {
- its_converter >> its_client->instance_;
- }
- }
- }
-
- auto found_service = clients_.find(its_client->service_);
- if (found_service != clients_.end()) {
- auto found_instance = found_service->second.find(
- its_client->instance_);
- if (found_instance != found_service->second.end()) {
- VSOMEIP_ERROR << "Multiple client configurations for service ["
- << std::hex << its_client->service_ << "."
- << its_client->instance_ << "]";
- is_loaded = false;
- }
- }
-
- if (is_loaded) {
- clients_[its_client->service_][its_client->instance_] = its_client;
- }
- } catch (...) {
- }
-}
-
-std::set<uint16_t> configuration_impl::get_client_port_configuration(
- const boost::property_tree::ptree &_tree) {
- std::set<uint16_t> its_ports;
- for (auto i = _tree.begin(); i != _tree.end(); ++i) {
- std::string its_value(i->second.data());
- uint16_t its_port_value;
-
- std::stringstream its_converter;
- if (its_value.size() > 1 && its_value[0] == '0' && its_value[1] == 'x') {
- its_converter << std::hex << its_value;
- } else {
- its_converter << std::dec << its_value;
- }
- its_converter >> its_port_value;
- its_ports.insert(its_port_value);
- }
- return its_ports;
-}
-
-void configuration_impl::get_event_configuration(
+void configuration_impl::load_event(
std::shared_ptr<service> &_service,
const boost::property_tree::ptree &_tree) {
for (auto i = _tree.begin(); i != _tree.end(); ++i) {
@@ -708,7 +989,7 @@ void configuration_impl::get_event_configuration(
}
}
-void configuration_impl::get_eventgroup_configuration(
+void configuration_impl::load_eventgroup(
std::shared_ptr<service> &_service,
const boost::property_tree::ptree &_tree) {
for (auto i = _tree.begin(); i != _tree.end(); ++i) {
@@ -782,360 +1063,281 @@ void configuration_impl::get_eventgroup_configuration(
}
}
-void configuration_impl::get_routing_configuration(const element &_element) {
+void configuration_impl::load_internal_services(const element &_element) {
try {
- if (is_configured_[ET_ROUTING]) {
- VSOMEIP_WARNING << "Multiple definitions of routing."
- << " Ignoring definition from " << _element.name_;
- } else {
- auto its_routing = _element.tree_.get_child("routing");
- routing_host_ = its_routing.data();
- is_configured_[ET_ROUTING] = true;
+ auto optional = _element.tree_.get_child_optional("internal_services");
+ if (!optional) {
+ return;
+ }
+ auto its_internal_services = _element.tree_.get_child("internal_services");
+ for (auto found_range = its_internal_services.begin();
+ found_range != its_internal_services.end(); ++found_range) {
+ service_instance_range range;
+ range.first_service_ = 0x0;
+ range.last_service_ = 0x0;
+ range.first_instance_ = 0x0;
+ range.last_instance_ = 0xffff;
+ for (auto i = found_range->second.begin();
+ i != found_range->second.end(); ++i) {
+ if (i->first == "first") {
+ if (i->second.size() == 0) {
+ std::stringstream its_converter;
+ std::string value = i->second.data();
+ its_converter << std::hex << value;
+ its_converter >> range.first_service_;
+ }
+ for (auto n = i->second.begin();
+ n != i->second.end(); ++n) {
+ if (n->first == "service") {
+ std::stringstream its_converter;
+ std::string value = n->second.data();
+ its_converter << std::hex << value;
+ its_converter >> range.first_service_;
+ } else if (n->first == "instance") {
+ std::stringstream its_converter;
+ std::string value = n->second.data();
+ its_converter << std::hex << value;
+ its_converter >> range.first_instance_;
+ }
+ }
+ } else if (i->first == "last") {
+ if (i->second.size() == 0) {
+ std::stringstream its_converter;
+ std::string value = i->second.data();
+ its_converter << std::hex << value;
+ its_converter >> range.last_service_;
+ }
+ for (auto n = i->second.begin();
+ n != i->second.end(); ++n) {
+ if (n->first == "service") {
+ std::stringstream its_converter;
+ std::string value = n->second.data();
+ its_converter << std::hex << value;
+ its_converter >> range.last_service_;
+ } else if (n->first == "instance") {
+ std::stringstream its_converter;
+ std::string value = n->second.data();
+ its_converter << std::hex << value;
+ its_converter >> range.last_instance_;
+ }
+ }
+ }
+ }
+ if (range.last_service_ >= range.first_service_) {
+ if (range.last_instance_ >= range.first_instance_) {
+ internal_service_ranges_.push_back(range);
+ }
+ }
}
} catch (...) {
+ VSOMEIP_ERROR << "Error parsing internal service range configuration!";
}
}
-void configuration_impl::get_permission_configuration(const element &_element) {
- const std::string file_permissions("file-permissions");
+void configuration_impl::load_clients(const element &_element) {
try {
- if (_element.tree_.get_child_optional(file_permissions)) {
- auto its_permissions = _element.tree_.get_child(file_permissions);
- for (auto i = its_permissions.begin(); i != its_permissions.end();
- ++i) {
- std::string its_key(i->first);
- std::stringstream its_converter;
- if (its_key == "permissions-shm") {
- std::string its_value(i->second.data());
- its_converter << std::oct << its_value;
- its_converter >> permissions_shm_;
- } else if (its_key == "umask") {
- std::string its_value(i->second.data());
- its_converter << std::oct << its_value;
- its_converter >> umask_;
- }
- }
- }
+ auto its_clients = _element.tree_.get_child("clients");
+ for (auto i = its_clients.begin(); i != its_clients.end(); ++i)
+ load_client(i->second);
} catch (...) {
+ // intentionally left empty!
}
}
-std::uint32_t configuration_impl::get_umask() const {
- return umask_;
-}
+void configuration_impl::load_client(const boost::property_tree::ptree &_tree) {
+ try {
+ bool is_loaded(true);
-std::uint32_t configuration_impl::get_permissions_shm() const {
- return permissions_shm_;
-}
+ std::shared_ptr<client> its_client(std::make_shared<client>());
-void configuration_impl::get_service_discovery_configuration(
- const element &_element) {
- try {
- auto its_service_discovery = _element.tree_.get_child("service-discovery");
- for (auto i = its_service_discovery.begin();
- i != its_service_discovery.end(); ++i) {
+ for (auto i = _tree.begin(); i != _tree.end(); ++i) {
std::string its_key(i->first);
std::string its_value(i->second.data());
std::stringstream its_converter;
- if (its_key == "enable") {
- if (is_configured_[ET_SERVICE_DISCOVERY_ENABLE]) {
- VSOMEIP_WARNING << "Multiple definitions for service_discovery.enabled."
- " Ignoring definition from " << _element.name_;
- } else {
- is_sd_enabled_ = (its_value == "true");
- is_configured_[ET_SERVICE_DISCOVERY_ENABLE] = true;
- }
- } else if (its_key == "multicast") {
- if (is_configured_[ET_SERVICE_DISCOVERY_MULTICAST]) {
- VSOMEIP_WARNING << "Multiple definitions for service_discovery.multicast."
- " Ignoring definition from " << _element.name_;
- } else {
- sd_multicast_ = its_value;
- is_configured_[ET_SERVICE_DISCOVERY_MULTICAST] = true;
- }
- } else if (its_key == "port") {
- if (is_configured_[ET_SERVICE_DISCOVERY_PORT]) {
- VSOMEIP_WARNING << "Multiple definitions for service_discovery.port."
- " Ignoring definition from " << _element.name_;
- } else {
- its_converter << its_value;
- its_converter >> sd_port_;
- if (!sd_port_) {
- sd_port_ = VSOMEIP_SD_DEFAULT_PORT;
- } else {
- is_configured_[ET_SERVICE_DISCOVERY_PORT] = true;
- }
- }
- } else if (its_key == "protocol") {
- if (is_configured_[ET_SERVICE_DISCOVERY_PROTOCOL]) {
- VSOMEIP_WARNING << "Multiple definitions for service_discovery.protocol."
- " Ignoring definition from " << _element.name_;
- } else {
- sd_protocol_ = its_value;
- is_configured_[ET_SERVICE_DISCOVERY_PROTOCOL] = true;
- }
- } else if (its_key == "initial_delay_min") {
- if (is_configured_[ET_SERVICE_DISCOVERY_INITIAL_DELAY_MIN]) {
- VSOMEIP_WARNING << "Multiple definitions for service_discovery.initial_delay_min."
- " Ignoring definition from " << _element.name_;
- } else {
- its_converter << its_value;
- its_converter >> sd_initial_delay_min_;
- is_configured_[ET_SERVICE_DISCOVERY_INITIAL_DELAY_MIN] = true;
- }
- } else if (its_key == "initial_delay_max") {
- if (is_configured_[ET_SERVICE_DISCOVERY_INITIAL_DELAY_MAX]) {
- VSOMEIP_WARNING << "Multiple definitions for service_discovery.initial_delay_max."
- " Ignoring definition from " << _element.name_;
- } else {
- its_converter << its_value;
- its_converter >> sd_initial_delay_max_;
- is_configured_[ET_SERVICE_DISCOVERY_INITIAL_DELAY_MAX] = true;
- }
- } else if (its_key == "repetitions_base_delay") {
- if (is_configured_[ET_SERVICE_DISCOVERY_REPETITION_BASE_DELAY]) {
- VSOMEIP_WARNING << "Multiple definitions for service_discovery.repetition_base_delay."
- " Ignoring definition from " << _element.name_;
- } else {
- its_converter << its_value;
- its_converter >> sd_repetitions_base_delay_;
- is_configured_[ET_SERVICE_DISCOVERY_REPETITION_BASE_DELAY] = true;
- }
- } else if (its_key == "repetitions_max") {
- if (is_configured_[ET_SERVICE_DISCOVERY_REPETITION_MAX]) {
- VSOMEIP_WARNING << "Multiple definitions for service_discovery.repetition_max."
- " Ignoring definition from " << _element.name_;
- } else {
- int tmp;
- its_converter << its_value;
- its_converter >> tmp;
- sd_repetitions_max_ = (uint8_t)tmp;
- is_configured_[ET_SERVICE_DISCOVERY_REPETITION_MAX] = true;
- }
- } else if (its_key == "ttl") {
- if (is_configured_[ET_SERVICE_DISCOVERY_TTL]) {
- VSOMEIP_WARNING << "Multiple definitions for service_discovery.ttl."
- " Ignoring definition from " << _element.name_;
- } else {
- its_converter << its_value;
- its_converter >> sd_ttl_;
- // We do _not_ accept 0 as this would mean "STOP OFFER"
- if (sd_ttl_ == 0) sd_ttl_ = VSOMEIP_SD_DEFAULT_TTL;
- else is_configured_[ET_SERVICE_DISCOVERY_TTL] = true;
- }
- } else if (its_key == "cyclic_offer_delay") {
- if (is_configured_[ET_SERVICE_DISCOVERY_CYCLIC_OFFER_DELAY]) {
- VSOMEIP_WARNING << "Multiple definitions for service_discovery.cyclic_offer_delay."
- " Ignoring definition from " << _element.name_;
+
+ if (its_key == "reliable") {
+ its_client->ports_[true] = load_client_ports(i->second);
+ } else if (its_key == "unreliable") {
+ its_client->ports_[false] = load_client_ports(i->second);
+ } else {
+ // Trim "its_value"
+ if (its_value.size() > 1 && its_value[0] == '0' && its_value[1] == 'x') {
+ its_converter << std::hex << its_value;
} else {
- its_converter << its_value;
- its_converter >> sd_cyclic_offer_delay_;
- is_configured_[ET_SERVICE_DISCOVERY_CYCLIC_OFFER_DELAY] = true;
+ its_converter << std::dec << its_value;
}
- } else if (its_key == "request_response_delay") {
- if (is_configured_[ET_SERVICE_DISCOVERY_REQUEST_RESPONSE_DELAY]) {
- VSOMEIP_WARNING << "Multiple definitions for service_discovery.request_response_delay."
- " Ignoring definition from " << _element.name_;
- } else {
- its_converter << its_value;
- its_converter >> sd_request_response_delay_;
- is_configured_[ET_SERVICE_DISCOVERY_REQUEST_RESPONSE_DELAY] = true;
+
+ if (its_key == "service") {
+ its_converter >> its_client->service_;
+ } else if (its_key == "instance") {
+ its_converter >> its_client->instance_;
}
}
}
- } catch (...) {
- }
-}
-void configuration_impl::get_applications_configuration(
- const element &_element) {
- try {
- std::stringstream its_converter;
- auto its_applications = _element.tree_.get_child("applications");
- for (auto i = its_applications.begin();
- i != its_applications.end();
- ++i) {
- get_application_configuration(i->second, _element.name_);
+ auto found_service = clients_.find(its_client->service_);
+ if (found_service != clients_.end()) {
+ auto found_instance = found_service->second.find(
+ its_client->instance_);
+ if (found_instance != found_service->second.end()) {
+ VSOMEIP_ERROR << "Multiple client configurations for service ["
+ << std::hex << its_client->service_ << "."
+ << its_client->instance_ << "]";
+ is_loaded = false;
+ }
+ }
+
+ if (is_loaded) {
+ clients_[its_client->service_][its_client->instance_] = its_client;
}
} catch (...) {
}
}
-void configuration_impl::get_application_configuration(
- const boost::property_tree::ptree &_tree, const std::string &_file_name) {
- std::string its_name("");
- client_t its_id(0);
- std::size_t its_max_dispatchers(VSOMEIP_MAX_DISPATCHERS);
- std::size_t its_max_dispatch_time(VSOMEIP_MAX_DISPATCH_TIME);
+std::set<uint16_t> configuration_impl::load_client_ports(
+ const boost::property_tree::ptree &_tree) {
+ std::set<uint16_t> its_ports;
for (auto i = _tree.begin(); i != _tree.end(); ++i) {
- std::string its_key(i->first);
std::string its_value(i->second.data());
+ uint16_t its_port_value;
+
std::stringstream its_converter;
- if (its_key == "name") {
- its_name = its_value;
- } else if (its_key == "id") {
- if (its_value.size() > 1 && its_value[0] == '0' && its_value[1] == 'x') {
- its_converter << std::hex << its_value;
- } else {
- its_converter << std::dec << its_value;
- }
- its_converter >> its_id;
- } else if (its_key == "max_dispatchers") {
- its_converter << std::dec << its_value;
- its_converter >> its_max_dispatchers;
- } else if (its_key == "max_dispatch_time") {
- its_converter << std::dec << its_value;
- its_converter >> its_max_dispatch_time;
- }
- }
- if (its_name != "" && its_id != 0) {
- if (applications_.find(its_name) == applications_.end()) {
- if (!is_configured_client_id(its_id)) {
- applications_[its_name]
- = std::make_tuple(its_id, its_max_dispatchers, its_max_dispatch_time);
- client_identifiers_.insert(its_id);
- } else {
- VSOMEIP_WARNING << "Multiple configurations for application "
- << its_name << ". Ignoring a configuration from "
- << _file_name;
- }
+ if (its_value.size() > 1 && its_value[0] == '0' && its_value[1] == 'x') {
+ its_converter << std::hex << its_value;
} else {
- VSOMEIP_WARNING << "Multiple configurations for application "
- << its_name << ". Ignoring a configuration from "
- << _file_name;
+ its_converter << std::dec << its_value;
}
+ its_converter >> its_port_value;
+ its_ports.insert(its_port_value);
}
+ return its_ports;
}
-void configuration_impl::get_trace_configuration(const element &_element) {
+void configuration_impl::load_watchdog(const element &_element) {
+ watchdog_->is_enabeled_ = false;
+ watchdog_->timeout_in_ms_ = VSOMEIP_DEFAULT_WATCHDOG_TIMEOUT;
+ watchdog_->missing_pongs_allowed_ = VSOMEIP_DEFAULT_MAX_MISSING_PONGS;
try {
- std::stringstream its_converter;
- auto its_trace_configuration = _element.tree_.get_child("tracing");
- for(auto i = its_trace_configuration.begin();
- i != its_trace_configuration.end();
- ++i) {
+ auto its_service_discovery = _element.tree_.get_child("watchdog");
+ for (auto i = its_service_discovery.begin();
+ i != its_service_discovery.end(); ++i) {
std::string its_key(i->first);
std::string its_value(i->second.data());
- if(its_key == "enable") {
- if (is_configured_[ET_TRACING_ENABLE]) {
- VSOMEIP_WARNING << "Multiple definitions of tracing.enable."
- << " Ignoring definition from " << _element.name_;
+ std::stringstream its_converter;
+ if (its_key == "enable") {
+ if (is_configured_[ET_WATCHDOG_ENABLE]) {
+ VSOMEIP_WARNING << "Multiple definitions of watchdog.enable."
+ " Ignoring definition from " << _element.name_;
} else {
- trace_->is_enabled_ = (its_value == "true");
- is_configured_[ET_TRACING_ENABLE] = true;
+ watchdog_->is_enabeled_ = (its_value == "true");
+ is_configured_[ET_WATCHDOG_ENABLE] = true;
}
- } else if (its_key == "sd_enable") {
- if (is_configured_[ET_TRACING_SD_ENABLE]) {
- VSOMEIP_WARNING << "Multiple definitions of tracing.sd_enable."
- << " Ignoring definition from " << _element.name_;
+ } else if (its_key == "timeout") {
+ if (is_configured_[ET_WATCHDOG_TIMEOUT]) {
+ VSOMEIP_WARNING << "Multiple definitions of watchdog.timeout."
+ " Ignoring definition from " << _element.name_;
} else {
- trace_->is_sd_enabled_ = (its_value == "true");
- is_configured_[ET_TRACING_SD_ENABLE] = true;
+ its_converter << std::dec << its_value;
+ its_converter >> watchdog_->timeout_in_ms_;
+ is_configured_[ET_WATCHDOG_TIMEOUT] = true;
+ }
+ } else if (its_key == "allowed_missing_pongs") {
+ if (is_configured_[ET_WATCHDOG_ALLOWED_MISSING_PONGS]) {
+ VSOMEIP_WARNING << "Multiple definitions of watchdog.allowed_missing_pongs."
+ " Ignoring definition from " << _element.name_;
+ } else {
+ its_converter << std::dec << its_value;
+ its_converter >> watchdog_->missing_pongs_allowed_;
+ is_configured_[ET_WATCHDOG_ALLOWED_MISSING_PONGS] = true;
}
- } else if(its_key == "channels") {
- get_trace_channels_configuration(i->second);
- } else if(its_key == "filters") {
- get_trace_filters_configuration(i->second);
}
}
} catch (...) {
}
}
-void configuration_impl::get_trace_channels_configuration(
- const boost::property_tree::ptree &_tree) {
+void configuration_impl::load_payload_sizes(const element &_element) {
+ const std::string payload_sizes("payload-sizes");
try {
- for(auto i = _tree.begin(); i != _tree.end(); ++i) {
- if(i == _tree.begin())
- trace_->channels_.clear();
- get_trace_channel_configuration(i->second);
- }
- } catch (...) {
- }
-}
+ if (_element.tree_.get_child_optional(payload_sizes)) {
+ const std::string unicast("unicast");
+ const std::string ports("ports");
+ const std::string port("port");
+ const std::string max_payload_size("max-payload-size");
+ auto its_ps = _element.tree_.get_child(payload_sizes);
+ for (auto i = its_ps.begin(); i != its_ps.end(); ++i) {
+ if (!i->second.get_child_optional(unicast)
+ || !i->second.get_child_optional(ports)) {
+ continue;
+ }
+ std::string its_unicast(i->second.get_child(unicast).data());
+ for (auto j = i->second.get_child(ports).begin();
+ j != i->second.get_child(ports).end(); ++j) {
-void configuration_impl::get_trace_channel_configuration(
- const boost::property_tree::ptree &_tree) {
- std::shared_ptr<trace_channel> its_channel = std::make_shared<trace_channel>();
- for(auto i = _tree.begin(); i != _tree.end(); ++i) {
- std::string its_key = i->first;
- std::string its_value = i->second.data();
- if(its_key == "name") {
- its_channel->name_ = its_value;
- } else if(its_key == "id") {
- its_channel->id_ = its_value;
- }
- }
- trace_->channels_.push_back(its_channel);
-}
+ if (!j->second.get_child_optional(port)
+ || !j->second.get_child_optional(max_payload_size)) {
+ continue;
+ }
-void configuration_impl::get_trace_filters_configuration(
- const boost::property_tree::ptree &_tree) {
- try {
- for(auto i = _tree.begin(); i != _tree.end(); ++i) {
- get_trace_filter_configuration(i->second);
- }
- } catch (...) {
- }
-}
+ std::uint16_t its_port = ILLEGAL_PORT;
+ std::uint32_t its_message_size = 0;
-void configuration_impl::get_trace_filter_configuration(
- const boost::property_tree::ptree &_tree) {
- std::shared_ptr<trace_filter_rule> its_filter_rule = std::make_shared<trace_filter_rule>();
- for(auto i = _tree.begin(); i != _tree.end(); ++i) {
- std::string its_key = i->first;
- std::string its_value = i->second.data();
- if(its_key == "channel") {
- its_filter_rule->channel_ = its_value;
- } else {
- get_trace_filter_expressions(i->second, its_key, its_filter_rule);
+ try {
+ std::string p(j->second.get_child(port).data());
+ its_port = static_cast<std::uint16_t>(std::stoul(p.c_str(),
+ NULL, 10));
+ std::string s(j->second.get_child(max_payload_size).data());
+ // add 16 Byte for the SOME/IP header
+ its_message_size = static_cast<std::uint32_t>(std::stoul(
+ s.c_str(),
+ NULL, 10) + 16);
+ } catch (const std::exception &e) {
+ VSOMEIP_ERROR << __func__ << ":" << e.what();
+ }
+
+ if (its_port == ILLEGAL_PORT || its_message_size == 0) {
+ continue;
+ }
+ if(max_configured_message_size_ < its_message_size) {
+ max_configured_message_size_ = its_message_size;
+ }
+
+ message_sizes_[its_unicast][its_port] = its_message_size;
+ }
+ }
}
+ } catch (...) {
}
- trace_->filter_rules_.push_back(its_filter_rule);
}
-void configuration_impl::get_trace_filter_expressions(
- const boost::property_tree::ptree &_tree,
- std::string &_criteria,
- std::shared_ptr<trace_filter_rule> &_filter_rule) {
- for(auto i = _tree.begin(); i != _tree.end(); ++i) {
- std::string its_value = i->second.data();
- std::stringstream its_converter;
+void configuration_impl::load_permissions(const element &_element) {
+ const std::string file_permissions("file-permissions");
+ try {
+ if (_element.tree_.get_child_optional(file_permissions)) {
+ auto its_permissions = _element.tree_.get_child(file_permissions);
+ for (auto i = its_permissions.begin(); i != its_permissions.end();
+ ++i) {
+ std::string its_key(i->first);
+ std::stringstream its_converter;
+ if (its_key == "permissions-shm") {
+ std::string its_value(i->second.data());
+ its_converter << std::oct << its_value;
+ its_converter >> permissions_shm_;
+ } else if (its_key == "umask") {
+ std::string its_value(i->second.data());
+ its_converter << std::oct << its_value;
+ its_converter >> umask_;
- if(_criteria == "services") {
- service_t its_id = NO_TRACE_FILTER_EXPRESSION;
- if (its_value.size() > 1 && its_value[0] == '0' && its_value[1] == 'x') {
- its_converter << std::hex << its_value;
- } else {
- its_converter << std::dec << its_value;
- }
- its_converter >> its_id;
- _filter_rule->services_.push_back(its_id);
- } else if(_criteria == "methods") {
- method_t its_id = NO_TRACE_FILTER_EXPRESSION;
- if (its_value.size() > 1 && its_value[0] == '0' && its_value[1] == 'x') {
- its_converter << std::hex << its_value;
- } else {
- its_converter << std::dec << its_value;
- }
- its_converter >> its_id;
- _filter_rule->methods_.push_back(its_id);
- } else if(_criteria == "clients") {
- client_t its_id = NO_TRACE_FILTER_EXPRESSION;
- if (its_value.size() > 1 && its_value[0] == '0' && its_value[1] == 'x') {
- its_converter << std::hex << its_value;
- } else {
- its_converter << std::dec << its_value;
+ }
}
- its_converter >> its_id;
- _filter_rule->clients_.push_back(its_id);
}
+ } catch (...) {
}
}
-void configuration_impl::get_supports_selective_broadcasts(const boost::property_tree::ptree &_tree) {
+void configuration_impl::load_selective_broadcasts_support(const element &_element) {
try {
- auto its_service_discovery = _tree.get_child("supports_selective_broadcasts");
+ auto its_service_discovery = _element.tree_.get_child("supports_selective_broadcasts");
for (auto i = its_service_discovery.begin();
i != its_service_discovery.end(); ++i) {
std::string its_key(i->first);
@@ -1149,42 +1351,32 @@ void configuration_impl::get_supports_selective_broadcasts(const boost::property
}
}
-void configuration_impl::get_watchdog_configuration(const element &_element) {
- watchdog_->is_enabeled_ = false;
- watchdog_->timeout_in_ms_ = VSOMEIP_DEFAULT_WATCHDOG_TIMEOUT;
- watchdog_->missing_pongs_allowed_ = VSOMEIP_DEFAULT_MAX_MISSING_PONGS;
+
+
+void configuration_impl::load_policies(const element &_element) {
+#ifdef WIN32
+ return;
+#endif
try {
- auto its_service_discovery = _element.tree_.get_child("watchdog");
- for (auto i = its_service_discovery.begin();
- i != its_service_discovery.end(); ++i) {
- std::string its_key(i->first);
- std::string its_value(i->second.data());
- std::stringstream its_converter;
- if (its_key == "enable") {
- if (is_configured_[ET_WATCHDOG_ENABLE]) {
- VSOMEIP_WARNING << "Multiple definitions of watchdog.enable."
- " Ignoring definition from " << _element.name_;
- } else {
- watchdog_->is_enabeled_ = (its_value == "true");
- is_configured_[ET_WATCHDOG_ENABLE] = true;
- }
- } else if (its_key == "timeout") {
- if (is_configured_[ET_WATCHDOG_TIMEOUT]) {
- VSOMEIP_WARNING << "Multiple definitions of watchdog.timeout."
- " Ignoring definition from " << _element.name_;
+ auto optional = _element.tree_.get_child_optional("security");
+ if (!optional) {
+ return;
+ }
+ policy_enabled_ = true;
+ auto found_policy = _element.tree_.get_child("security");
+ for (auto its_security = found_policy.begin();
+ its_security != found_policy.end(); ++its_security) {
+ if (its_security->first == "check_credentials") {
+ if (its_security->second.data() == "true") {
+ check_credentials_ = true;
} else {
- its_converter << std::dec << its_value;
- its_converter >> watchdog_->timeout_in_ms_;
- is_configured_[ET_WATCHDOG_TIMEOUT] = true;
+ check_credentials_ = false;
}
- } else if (its_key == "allowed_missing_pongs") {
- if (is_configured_[ET_WATCHDOG_ALLOWED_MISSING_PONGS]) {
- VSOMEIP_WARNING << "Multiple definitions of watchdog.allowed_missing_pongs."
- " Ignoring definition from " << _element.name_;
- } else {
- its_converter << std::dec << its_value;
- its_converter >> watchdog_->missing_pongs_allowed_;
- is_configured_[ET_WATCHDOG_ALLOWED_MISSING_PONGS] = true;
+ }
+ if (its_security->first == "policies") {
+ for (auto its_policy = its_security->second.begin();
+ its_policy != its_security->second.end(); ++its_policy) {
+ load_policy(its_policy->second);
}
}
}
@@ -1192,78 +1384,209 @@ void configuration_impl::get_watchdog_configuration(const element &_element) {
}
}
-void configuration_impl::get_internal_services(
- const boost::property_tree::ptree &_tree) {
- try {
- auto optional = _tree.get_child_optional("internal_services");
- if (!optional) {
- return;
- }
- auto its_internal_services = _tree.get_child("internal_services");
- for (auto found_range = its_internal_services.begin();
- found_range != its_internal_services.end(); ++found_range) {
- service_instance_range range;
- range.first_service_ = 0x0;
- range.last_service_ = 0x0;
- range.first_instance_ = 0x0;
- range.last_instance_ = 0xffff;
- for (auto i = found_range->second.begin();
- i != found_range->second.end(); ++i) {
- if (i->first == "first") {
- if (i->second.size() == 0) {
+void configuration_impl::load_policy(const boost::property_tree::ptree &_tree) {
+ client_t client = 0x0;
+ std::shared_ptr<policy> policy(std::make_shared<policy>());
+ bool allow_deny_set(false);
+ for (auto i = _tree.begin(); i != _tree.end(); ++i) {
+ if (i->first == "client") {
+ std::string value = i->second.data();
+ if (value == "") {
+ client_t firstClient, lastClient;
+ for (auto n = i->second.begin();
+ n != i->second.end(); ++n) {
+ if (n->first == "first") {
std::stringstream its_converter;
- std::string value = i->second.data();
+ std::string value = n->second.data();
its_converter << std::hex << value;
- its_converter >> range.first_service_;
+ its_converter >> firstClient;
+ } else if (n->first == "last") {
+ std::stringstream its_converter;
+ std::string value = n->second.data();
+ its_converter << std::hex << value;
+ its_converter >> lastClient;
}
- for (auto n = i->second.begin();
- n != i->second.end(); ++n) {
- if (n->first == "service") {
- std::stringstream its_converter;
- std::string value = n->second.data();
- its_converter << std::hex << value;
- its_converter >> range.first_service_;
- } else if (n->first == "instance") {
- std::stringstream its_converter;
- std::string value = n->second.data();
- its_converter << std::hex << value;
- its_converter >> range.first_instance_;
+ }
+ if (firstClient < lastClient) {
+ uint32_t overrides(0);
+ for (client_t c = firstClient; c <= lastClient; ++c) {
+ if (policies_.find(c) != policies_.end()) {
+ overrides++;
+ }
+ policies_[c] = policy;
+ if (c == 0xffff) {
+ break;
}
}
- } else if (i->first == "last") {
- if (i->second.size() == 0) {
- std::stringstream its_converter;
- std::string value = i->second.data();
- its_converter << std::hex << value;
- its_converter >> range.last_service_;
+ if (overrides) {
+ VSOMEIP_WARNING << std::hex << "Security configuration: "
+ << "Client range 0x" << firstClient
+ << " - 0x" << lastClient << " overrides policy of "
+ << std::dec << overrides << " clients";
}
- for (auto n = i->second.begin();
- n != i->second.end(); ++n) {
- if (n->first == "service") {
+ } else {
+ VSOMEIP_WARNING << std::hex << "Security configuration: "
+ << "Client range have to be ascending, \"first\"=0x"
+ << firstClient << " : \"last\"=0x" << lastClient
+ << " ~> Skip policy.";
+ }
+ } else {
+ std::stringstream its_converter;
+ its_converter << std::hex << value;
+ its_converter >> client;
+ if (client != 0x0) {
+ if (policies_.find(client) != policies_.end()) {
+ VSOMEIP_WARNING << std::hex << "Security configuration: "
+ << "Overriding policy for client 0x" << client << ".";
+ }
+ policies_[client] = policy;
+ }
+ }
+ } else if (i->first == "credentials") {
+ uint32_t uid = 0x0;
+ uint32_t gid = 0x0;
+ for (auto n = i->second.begin();
+ n != i->second.end(); ++n) {
+ if (n->first == "uid") {
+ std::stringstream its_converter;
+ std::string value = n->second.data();
+ its_converter << std::dec << value;
+ its_converter >> uid;
+ } else if (n->first == "gid") {
+ std::stringstream its_converter;
+ std::string value = n->second.data();
+ its_converter << std::dec << value;
+ its_converter >> gid;
+ }
+ }
+ policy->uid_ = uid;
+ policy->gid_ = gid;
+ } else if (i->first == "allow") {
+ if (allow_deny_set) {
+ VSOMEIP_WARNING << "Security configuration: \"allow\" tag overrides "
+ << "already set \"deny\" tag. "
+ << "Either \"deny\" or \"allow\" is allowed.";
+ }
+ allow_deny_set = true;
+ policy->allow_ = true;
+ for (auto l = i->second.begin(); l != i->second.end(); ++l) {
+ if (l->first == "requests") {
+ for (auto n = l->second.begin(); n != l->second.end(); ++n) {
+ service_t service = 0x0;
+ instance_t instance = 0x0;
+ for (auto k = n->second.begin(); k != n->second.end(); ++k) {
std::stringstream its_converter;
- std::string value = n->second.data();
- its_converter << std::hex << value;
- its_converter >> range.last_service_;
- } else if (n->first == "instance") {
+ if (k->first == "service") {
+ std::string value = k->second.data();
+ its_converter << std::hex << value;
+ its_converter >> service;
+ } else if (k->first == "instance") {
+ std::string value = k->second.data();
+ its_converter << std::hex << value;
+ its_converter >> instance;
+ }
+ }
+ if (service != 0x0 && instance != 0x0) {
+ policy->allowed_services_.insert(
+ std::make_pair(service, instance));
+ }
+ }
+ } else if (l->first == "offers") {
+ for (auto n = l->second.begin(); n != l->second.end(); ++n) {
+ service_t service = 0x0;
+ instance_t instance = 0x0;
+ for (auto k = n->second.begin(); k != n->second.end(); ++k) {
std::stringstream its_converter;
- std::string value = n->second.data();
- its_converter << std::hex << value;
- its_converter >> range.last_instance_;
+ if (k->first == "service") {
+ std::string value = k->second.data();
+ its_converter << std::hex << value;
+ its_converter >> service;
+ } else if (k->first == "instance") {
+ std::string value = k->second.data();
+ its_converter << std::hex << value;
+ its_converter >> instance;
+ }
+ }
+ if (service != 0x0 && instance != 0x0) {
+ policy->allowed_offers_.insert(
+ std::make_pair(service, instance));
}
}
}
}
- if (range.last_service_ >= range.first_service_) {
- if (range.last_instance_ >= range.first_instance_) {
- internal_service_ranges_.push_back(range);
+ } else if (i->first == "deny") {
+ if (allow_deny_set) {
+ VSOMEIP_WARNING << "Security configuration: \"deny\" tag overrides "
+ << "already set \"allow\" tag. "
+ << "Either \"deny\" or \"allow\" is allowed.";
+ }
+ allow_deny_set = true;
+ policy->allow_ = false;
+ for (auto l = i->second.begin(); l != i->second.end(); ++l) {
+ if (l->first == "requests") {
+ for (auto n = l->second.begin(); n != l->second.end(); ++n) {
+ service_t service = 0x0;
+ instance_t instance = 0x0;
+ for (auto k = n->second.begin(); k != n->second.end(); ++k) {
+ std::stringstream its_converter;
+ if (k->first == "service") {
+ std::string value = k->second.data();
+ its_converter << std::hex << value;
+ its_converter >> service;
+ } else if (k->first == "instance") {
+ std::string value = k->second.data();
+ its_converter << std::hex << value;
+ its_converter >> instance;
+ }
+ }
+ if (service != 0x0 && instance != 0x0) {
+ policy->denied_services_.insert(
+ std::make_pair(service, instance));
+ }
+ }
+ }
+ if (l->first == "offers") {
+ for (auto n = l->second.begin(); n != l->second.end(); ++n) {
+ service_t service = 0x0;
+ instance_t instance = 0x0;
+ for (auto k = n->second.begin(); k != n->second.end(); ++k) {
+ std::stringstream its_converter;
+ if (k->first == "service") {
+ std::string value = k->second.data();
+ its_converter << std::hex << value;
+ its_converter >> service;
+ } else if (k->first == "instance") {
+ std::string value = k->second.data();
+ its_converter << std::hex << value;
+ its_converter >> instance;
+ }
+ }
+ if (service != 0x0 && instance != 0x0) {
+ policy->denied_offers_.insert(
+ std::make_pair(service, instance));
+ }
+ }
}
}
}
- } catch (...) {
- VSOMEIP_ERROR << "Error parsing internal service range configuration!";
}
}
+///////////////////////////////////////////////////////////////////////////////
+// Internal helper
+///////////////////////////////////////////////////////////////////////////////
+void configuration_impl::set_magic_cookies_unicast_address() {
+ // get services with static routing that have magic cookies enabled
+ std::map<std::string, std::set<uint16_t> > its_magic_cookies_ = magic_cookies_;
+ its_magic_cookies_.erase("local");
+
+ //set unicast address of host for all services without static routing
+ its_magic_cookies_[get_unicast_address().to_string()].insert(magic_cookies_["local"].begin(),
+ magic_cookies_["local"].end());
+ magic_cookies_.clear();
+ magic_cookies_ = its_magic_cookies_;
+}
+
bool configuration_impl::is_internal_service(service_t _service,
instance_t _instance) const {
@@ -1278,7 +1601,9 @@ bool configuration_impl::is_internal_service(service_t _service,
return false;
}
+///////////////////////////////////////////////////////////////////////////////
// Public interface
+///////////////////////////////////////////////////////////////////////////////
const boost::asio::ip::address & configuration_impl::get_unicast_address() const {
return unicast_;
}
@@ -1453,6 +1778,62 @@ configuration_impl::get_remote_services() const {
return its_remote_services;
}
+bool configuration_impl::is_mandatory(const std::string &_name) const {
+ std::set<std::string> its_candidates;
+ for (auto m : mandatory_) {
+ if (m.size() <= _name.size()) {
+ its_candidates.insert(m);
+ }
+ }
+
+ if (its_candidates.empty())
+ return false;
+
+ for (auto c : its_candidates) {
+ if (std::equal(c.rbegin(), c.rend(), _name.rbegin())) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void configuration_impl::set_mandatory(const std::string &_input) {
+ if (_input.length() > 0) {
+ auto found_separator = _input.find(',');
+ std::string its_mandatory_file = _input.substr(0, found_separator);
+ trim(its_mandatory_file);
+ mandatory_.insert(its_mandatory_file);
+ while (found_separator != std::string::npos) {
+ auto last_separator = found_separator+1;
+ found_separator = _input.find(',', last_separator);
+ its_mandatory_file
+ = _input.substr(last_separator, found_separator - last_separator);
+ trim(its_mandatory_file);
+ mandatory_.insert(its_mandatory_file);
+ }
+ }
+}
+
+void configuration_impl::trim(std::string &_s) {
+ _s.erase(
+ _s.begin(),
+ std::find_if(
+ _s.begin(),
+ _s.end(),
+ std::not1(std::ptr_fun(isspace))
+ )
+ );
+
+ _s.erase(
+ std::find_if(
+ _s.rbegin(),
+ _s.rend(),
+ std::not1(std::ptr_fun(isspace))).base(),
+ _s.end()
+ );
+}
+
bool configuration_impl::is_remote(std::shared_ptr<service> _service) const {
return (_service->unicast_address_ != "local" &&
_service->unicast_address_ != "" &&
@@ -1540,7 +1921,7 @@ std::uint32_t configuration_impl::get_max_message_size_local() const {
// to the routing_manager stub
return std::uint32_t(its_max_message_size
+ VSOMEIP_COMMAND_HEADER_SIZE + sizeof(instance_t)
- + sizeof(bool) + sizeof(bool));
+ + sizeof(bool) + sizeof(bool) + sizeof(client_t));
}
std::uint32_t configuration_impl::get_message_size_reliable(
@@ -1630,6 +2011,10 @@ int32_t configuration_impl::get_sd_request_response_delay() const {
return sd_request_response_delay_;
}
+std::uint32_t configuration_impl::get_sd_offer_debounce_time() const {
+ return sd_offer_debounce_time_;
+}
+
// Trace configuration
std::shared_ptr<cfg::trace> configuration_impl::get_trace() const {
return trace_;
@@ -1647,7 +2032,85 @@ uint32_t configuration_impl::get_watchdog_timeout() const {
uint32_t configuration_impl::get_allowed_missing_pongs() const {
return watchdog_->missing_pongs_allowed_;
}
+std::uint32_t configuration_impl::get_umask() const {
+ return umask_;
+}
+std::uint32_t configuration_impl::get_permissions_shm() const {
+ return permissions_shm_;
+}
+
+bool configuration_impl::is_security_enabled() const {
+ return policy_enabled_;
+}
+
+bool configuration_impl::check_credentials(client_t _client, uint32_t _uid,
+ uint32_t _gid) const {
+ if (!policy_enabled_) {
+ return true;
+ }
+ auto its_client = policies_.find(_client);
+ if (its_client != policies_.end()) {
+ if (its_client->second->uid_ == _uid && its_client->second->gid_ == _gid) {
+ return true;
+ }
+ }
+ return !check_credentials_;
+}
+
+bool configuration_impl::is_client_allowed(client_t _client, service_t _service,
+ instance_t _instance) const {
+ if (!policy_enabled_) {
+ return true;
+ }
+ auto its_client = policies_.find(_client);
+ if (its_client == policies_.end()) {
+ return !check_credentials_;
+ }
+
+ if (!its_client->second->allow_) {
+ auto its_denied_service = its_client->second->denied_services_.find(
+ std::make_pair(_service, _instance));
+ if (its_denied_service == its_client->second->denied_services_.end()) {
+ return true;
+ }
+ } else {
+ auto its_allowed_service = its_client->second->allowed_services_.find(
+ std::make_pair(_service, _instance));
+ if (its_allowed_service != its_client->second->allowed_services_.end()) {
+ return true;
+ }
+ }
+
+ return !check_credentials_;
+}
+
+bool configuration_impl::is_offer_allowed(client_t _client, service_t _service,
+ instance_t _instance) const {
+ if (!policy_enabled_) {
+ return true;
+ }
+ auto its_client = policies_.find(_client);
+ if (its_client == policies_.end()) {
+ return !check_credentials_;
+ }
+
+ if (!its_client->second->allow_) {
+ auto its_denied_service = its_client->second->denied_offers_.find(
+ std::make_pair(_service, _instance));
+ if (its_denied_service == its_client->second->denied_offers_.end()) {
+ return true;
+ }
+ } else {
+ auto its_allowed_service = its_client->second->allowed_offers_.find(
+ std::make_pair(_service, _instance));
+ if (its_allowed_service != its_client->second->allowed_offers_.end()) {
+ return true;
+ }
+ }
+
+ return !check_credentials_;
+}
} // namespace config
} // namespace vsomeip
diff --git a/implementation/endpoints/include/client_endpoint_impl.hpp b/implementation/endpoints/include/client_endpoint_impl.hpp
index 9d4fb25..9a889f3 100644
--- a/implementation/endpoints/include/client_endpoint_impl.hpp
+++ b/implementation/endpoints/include/client_endpoint_impl.hpp
@@ -15,7 +15,6 @@
#include <boost/asio/io_service.hpp>
#include <boost/asio/ip/udp.hpp>
#include <boost/utility.hpp>
-
#include <vsomeip/constants.hpp>
#include "buffer.hpp"
@@ -70,8 +69,6 @@ protected:
socket_type socket_;
endpoint_type remote_;
- uint16_t local_port_;
-
boost::asio::steady_timer flush_timer_;
boost::asio::steady_timer connect_timer_;
uint32_t connect_timeout_;
@@ -87,6 +84,8 @@ protected:
std::mutex error_handler_mutex_;
endpoint_error_handler_t error_handler_;
+
+ std::mutex stop_mutex_;
};
} // namespace vsomeip
diff --git a/implementation/endpoints/include/credentials.hpp b/implementation/endpoints/include/credentials.hpp
new file mode 100644
index 0000000..c5d6ba8
--- /dev/null
+++ b/implementation/endpoints/include/credentials.hpp
@@ -0,0 +1,26 @@
+// Copyright (C) 2014-2016 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 ENDPOINTS_INCLUDE_CREDENTIALS_HPP_
+#define ENDPOINTS_INCLUDE_CREDENTIALS_HPP_
+
+#include <vsomeip/primitive_types.hpp>
+
+namespace vsomeip {
+
+class credentials {
+public:
+ static void activate_credentials(const int _fd);
+
+ static void deactivate_credentials(const int _fd);
+
+ static client_t receive_credentials(const int _fd, uid_t& _uid, gid_t& _gid);
+
+ static void send_credentials(const int _fd, client_t _client);
+};
+
+} // namespace vsomeip
+
+#endif /* ENDPOINTS_INCLUDE_CREDENTIALS_HPP_ */
diff --git a/implementation/endpoints/include/endpoint_host.hpp b/implementation/endpoints/include/endpoint_host.hpp
index 1c78f39..8834158 100644
--- a/implementation/endpoints/include/endpoint_host.hpp
+++ b/implementation/endpoints/include/endpoint_host.hpp
@@ -9,25 +9,33 @@
#include <memory>
#include <boost/asio/ip/address.hpp>
+#include "../../configuration/include/internal.hpp"
#include <vsomeip/primitive_types.hpp>
namespace vsomeip {
+class configuration;
class endpoint;
class endpoint_host {
public:
virtual ~endpoint_host() {}
+ virtual const std::shared_ptr<configuration> get_configuration() const = 0;
virtual void on_connect(std::shared_ptr<endpoint> _endpoint) = 0;
virtual void on_disconnect(std::shared_ptr<endpoint> _endpoint) = 0;
virtual void on_message(const byte_t *_data, length_t _length,
endpoint *_receiver, const boost::asio::ip::address &_destination
- = boost::asio::ip::address()) = 0;
+ = boost::asio::ip::address(),
+ client_t _bound_client = VSOMEIP_ROUTING_CLIENT) = 0;
virtual void on_error(const byte_t *_data, length_t _length,
endpoint *_receiver) = 0;
virtual void release_port(uint16_t _port, bool _reliable) = 0;
+ virtual client_t get_client() const = 0;
+#ifndef WIN32
+ virtual bool check_credentials(client_t _client, uid_t _uid, gid_t _gid) = 0;
+#endif
};
} // namespace vsomeip
diff --git a/implementation/endpoints/include/local_client_endpoint_impl.hpp b/implementation/endpoints/include/local_client_endpoint_impl.hpp
index 6b57e96..79a0420 100644
--- a/implementation/endpoints/include/local_client_endpoint_impl.hpp
+++ b/implementation/endpoints/include/local_client_endpoint_impl.hpp
@@ -51,6 +51,8 @@ private:
void receive();
void receive_cbk(boost::system::error_code const &_error,
std::size_t _bytes);
+
+ receive_buffer_t recv_buffer_;
};
} // namespace vsomeip
diff --git a/implementation/endpoints/include/local_server_endpoint_impl.hpp b/implementation/endpoints/include/local_server_endpoint_impl.hpp
index b0ac2ba..66c1fc2 100644
--- a/implementation/endpoints/include/local_server_endpoint_impl.hpp
+++ b/implementation/endpoints/include/local_server_endpoint_impl.hpp
@@ -7,6 +7,8 @@
#define VSOMEIP_LOCAL_SERVER_ENDPOINT_IMPL_HPP
#include <map>
+#include <thread>
+#include <condition_variable>
#include <boost/asio/io_service.hpp>
#include <boost/asio/local/stream_protocol.hpp>
@@ -40,6 +42,13 @@ public:
endpoint_type _local,
boost::asio::io_service &_io,
std::uint32_t _max_message_size);
+
+ local_server_endpoint_impl(std::shared_ptr<endpoint_host> _host,
+ endpoint_type _local,
+ boost::asio::io_service &_io,
+ std::uint32_t _max_message_size,
+ int native_socket);
+
virtual ~local_server_endpoint_impl();
void start();
@@ -52,11 +61,12 @@ public:
const byte_t *_data, uint32_t _size, bool _flush);
void send_queued(queue_iterator_type _queue_iterator);
- endpoint_type get_remote() const;
bool get_default_target(service_t, endpoint_type &) const;
bool is_local() const;
+ void accept_client_func();
+
private:
class connection: public boost::enable_shared_from_this<connection> {
@@ -72,6 +82,8 @@ private:
void send_queued(queue_iterator_type _queue_iterator);
+ void set_bound_client(client_t _client);
+
private:
connection(std::weak_ptr<local_server_endpoint_impl> _server,
std::uint32_t _max_message_size);
@@ -86,6 +98,8 @@ private:
receive_buffer_t recv_buffer_;
size_t recv_buffer_size_;
+ client_t bound_client_;
+
private:
void receive_cbk(boost::system::error_code const &_error,
std::size_t _bytes);
diff --git a/implementation/endpoints/include/server_endpoint_impl.hpp b/implementation/endpoints/include/server_endpoint_impl.hpp
index c3f6b59..894c76f 100644
--- a/implementation/endpoints/include/server_endpoint_impl.hpp
+++ b/implementation/endpoints/include/server_endpoint_impl.hpp
@@ -55,8 +55,6 @@ public:
uint32_t _port, bool _flush);
virtual void send_queued(queue_iterator_type _queue_iterator) = 0;
- virtual endpoint_type get_remote() const = 0;
-
virtual bool get_default_target(service_t _service,
endpoint_type &_target) const = 0;
diff --git a/implementation/endpoints/include/tcp_server_endpoint_impl.hpp b/implementation/endpoints/include/tcp_server_endpoint_impl.hpp
index eb0047a..e976644 100644
--- a/implementation/endpoints/include/tcp_server_endpoint_impl.hpp
+++ b/implementation/endpoints/include/tcp_server_endpoint_impl.hpp
@@ -39,7 +39,6 @@ public:
VSOMEIP_EXPORT bool is_established(std::shared_ptr<endpoint_definition> _endpoint);
- endpoint_type get_remote() const;
bool get_remote_address(boost::asio::ip::address &_address) const;
unsigned short get_remote_port() const;
bool get_default_target(service_t, endpoint_type &) const;
diff --git a/implementation/endpoints/include/udp_server_endpoint_impl.hpp b/implementation/endpoints/include/udp_server_endpoint_impl.hpp
index 907e022..0f2f830 100644
--- a/implementation/endpoints/include/udp_server_endpoint_impl.hpp
+++ b/implementation/endpoints/include/udp_server_endpoint_impl.hpp
@@ -37,7 +37,6 @@ public:
const byte_t *_data, uint32_t _size, bool _flush);
void send_queued(queue_iterator_type _queue_iterator);
- endpoint_type get_remote() const;
bool get_remote_address(boost::asio::ip::address &_address) const;
unsigned short get_remote_port() const;
diff --git a/implementation/endpoints/src/client_endpoint_impl.cpp b/implementation/endpoints/src/client_endpoint_impl.cpp
index 3d2a752..9a33aad 100644
--- a/implementation/endpoints/src/client_endpoint_impl.cpp
+++ b/implementation/endpoints/src/client_endpoint_impl.cpp
@@ -73,9 +73,11 @@ void client_endpoint_impl<Protocol>::stop() {
times_slept++;
}
}
-
- if (socket_.is_open()) {
- socket_.cancel();
+ {
+ std::lock_guard<std::mutex> its_lock(stop_mutex_);
+ if (socket_.is_open()) {
+ socket_.cancel();
+ }
}
}
}
@@ -86,6 +88,7 @@ void client_endpoint_impl<Protocol>::restart() {
std::lock_guard<std::mutex> its_lock(mutex_);
queue_.clear();
}
+ shutdown_and_close_socket();
is_connected_ = false;
connect_timer_.expires_from_now(
std::chrono::milliseconds(connect_timeout_));
@@ -141,10 +144,12 @@ bool client_endpoint_impl<Protocol>::send(const uint8_t *_data,
flush_timer_.expires_from_now(
std::chrono::milliseconds(VSOMEIP_DEFAULT_FLUSH_TIMEOUT)); // TODO: use config variable
flush_timer_.async_wait(
- std::bind(
- &client_endpoint_impl<Protocol>::flush_cbk,
- this->shared_from_this(),
- std::placeholders::_1));
+ std::bind(
+ &client_endpoint_impl<Protocol>::flush_cbk,
+ this->shared_from_this(),
+ std::placeholders::_1
+ )
+ );
}
if (queue_size_zero_on_entry && !queue_.empty()) { // no writing in progress
@@ -251,9 +256,7 @@ void client_endpoint_impl<Protocol>::send_cbk(
}
}
if (socket_.is_open()) {
- boost::system::error_code its_error;
- socket_.shutdown(Protocol::socket::shutdown_both, its_error);
- socket_.close(its_error);
+ shutdown_and_close_socket();
}
connect();
} else if (_error == boost::asio::error::not_connected
@@ -283,6 +286,7 @@ void client_endpoint_impl<Protocol>::register_error_callback(
template<typename Protocol>
void client_endpoint_impl<Protocol>::shutdown_and_close_socket() {
+ std::lock_guard<std::mutex> its_lock(stop_mutex_);
if (socket_.is_open()) {
boost::system::error_code its_error;
socket_.shutdown(Protocol::socket::shutdown_both, its_error);
diff --git a/implementation/endpoints/src/credentials.cpp b/implementation/endpoints/src/credentials.cpp
new file mode 100644
index 0000000..b718bd4
--- /dev/null
+++ b/implementation/endpoints/src/credentials.cpp
@@ -0,0 +1,109 @@
+// Copyright (C) 2014-2016 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 WIN32
+
+#include <sys/socket.h>
+
+#include "../include/credentials.hpp"
+
+#include "../../configuration/include/internal.hpp"
+#include "../../logging/include/logger.hpp"
+
+namespace vsomeip {
+
+void credentials::activate_credentials(const int _fd) {
+ int optval = 1;
+ if (setsockopt(_fd, SOL_SOCKET, SO_PASSCRED, &optval, sizeof(optval)) == -1) {
+ VSOMEIP_ERROR << "Activating socket option for receiving credentials failed.";
+ }
+}
+
+void credentials::deactivate_credentials(const int _fd) {
+ int optval = 0;
+ if (setsockopt(_fd, SOL_SOCKET, SO_PASSCRED, &optval, sizeof(optval)) == -1) {
+ VSOMEIP_ERROR << "Deactivating socket option for receiving credentials failed.";
+ }
+}
+
+client_t credentials::receive_credentials(const int _fd, uid_t& _uid, gid_t& _gid) {
+ struct ucred *ucredp;
+ struct msghdr msgh;
+ struct iovec iov;
+ union {
+ struct cmsghdr cmh;
+ char control[CMSG_SPACE(sizeof(struct ucred))];
+ } control_un;
+ struct cmsghdr *cmhp;
+ // Sender client_id will be received as data
+ client_t client = VSOMEIP_ROUTING_CLIENT;
+
+ // Set 'control_un' to describe ancillary data that we want to receive
+ control_un.cmh.cmsg_len = CMSG_LEN(sizeof(struct ucred));
+ control_un.cmh.cmsg_level = SOL_SOCKET;
+ control_un.cmh.cmsg_type = SCM_CREDENTIALS;
+
+ // Set 'msgh' fields to describe 'control_un'
+ msgh.msg_control = control_un.control;
+ msgh.msg_controllen = sizeof(control_un.control);
+
+ // Set fields of 'msgh' to point to buffer used to receive (real) data read by recvmsg()
+ msgh.msg_iov = &iov;
+ msgh.msg_iovlen = 1;
+ iov.iov_base = &client;
+ iov.iov_len = sizeof(client_t);
+
+ // We don't need address of peer as we using connect
+ msgh.msg_name = NULL;
+ msgh.msg_namelen = 0;
+
+ // Receive client_id plus ancillary data
+ ssize_t nr = recvmsg(_fd, &msgh, 0);
+ if (nr == -1) {
+ VSOMEIP_ERROR << "Receiving credentials failed. No data.";
+ }
+
+ cmhp = CMSG_FIRSTHDR(&msgh);
+ if (cmhp == NULL || cmhp->cmsg_len != CMSG_LEN(sizeof(struct ucred))
+ || cmhp->cmsg_level != SOL_SOCKET || cmhp->cmsg_type != SCM_CREDENTIALS) {
+ VSOMEIP_ERROR << "Receiving credentials failed. Invalid data.";
+ } else {
+ ucredp = (struct ucred *) CMSG_DATA(cmhp);
+ _uid = ucredp->uid;
+ _gid = ucredp->gid;
+ }
+
+ return client;
+}
+
+void credentials::send_credentials(const int _fd, client_t _client) {
+ struct msghdr msgh;
+ struct iovec iov;
+
+ // data to send
+ msgh.msg_iov = &iov;
+ msgh.msg_iovlen = 1;
+ iov.iov_base = &_client;
+ iov.iov_len = sizeof(client_t);
+
+ // destination not needed as we use connect
+ msgh.msg_name = NULL;
+ msgh.msg_namelen = 0;
+
+ // credentials not need to set explicitly
+ msgh.msg_control = NULL;
+ msgh.msg_controllen = 0;
+
+ // send client id with credentials
+ ssize_t ns = sendmsg(_fd, &msgh, 0);
+ if (ns == -1) {
+ VSOMEIP_ERROR << "Sending credentials failed.";
+ }
+}
+
+} // namespace vsomeip
+
+#endif
+
diff --git a/implementation/endpoints/src/local_client_endpoint_impl.cpp b/implementation/endpoints/src/local_client_endpoint_impl.cpp
index 7e633e0..1a13e91 100644
--- a/implementation/endpoints/src/local_client_endpoint_impl.cpp
+++ b/implementation/endpoints/src/local_client_endpoint_impl.cpp
@@ -13,6 +13,13 @@
#include "../include/endpoint_host.hpp"
#include "../include/local_client_endpoint_impl.hpp"
#include "../../logging/include/logger.hpp"
+#include "../include/local_server_endpoint_impl.hpp"
+#include "../../configuration/include/configuration.hpp"
+
+// Credentials
+#ifndef WIN32
+#include "../include/credentials.hpp"
+#endif
namespace vsomeip {
@@ -21,9 +28,10 @@ local_client_endpoint_impl::local_client_endpoint_impl(
endpoint_type _remote,
boost::asio::io_service &_io,
std::uint32_t _max_message_size)
- : local_client_endpoint_base_impl(_host, _remote, _remote, _io, _max_message_size) {
- // Using _remote for the local(!) endpoint is ok,
- // because we have no bind for local endpoints!
+ : local_client_endpoint_base_impl(_host, _remote, _remote, _io, _max_message_size),
+ // Using _remote for the local(!) endpoint is ok,
+ // because we have no bind for local endpoints!
+ recv_buffer_(1,0) {
is_supporting_magic_cookies_ = false;
}
@@ -38,10 +46,13 @@ bool local_client_endpoint_impl::is_local() const {
void local_client_endpoint_impl::start() {
if (socket_.is_open()) {
sending_blocked_ = false;
- boost::system::error_code its_error;
- socket_.cancel(its_error);
- socket_.shutdown(socket_type::shutdown_both, its_error);
- socket_.close(its_error);
+ {
+ std::lock_guard<std::mutex> its_lock(stop_mutex_);
+ boost::system::error_code its_error;
+ socket_.cancel(its_error);
+ socket_.shutdown(socket_type::shutdown_both, its_error);
+ socket_.close(its_error);
+ }
restart();
} else {
connect();
@@ -53,9 +64,23 @@ void local_client_endpoint_impl::connect() {
socket_.open(remote_.protocol(), its_error);
if (!its_error || its_error == boost::asio::error::already_open) {
- socket_.set_option(boost::asio::socket_base::reuse_address(true));
boost::system::error_code error;
+ socket_.set_option(boost::asio::socket_base::reuse_address(true), error);
error = socket_.connect(remote_, error);
+
+// Credentials
+#ifndef WIN32
+ if (!error) {
+ auto its_host = host_.lock();
+ if (its_host) {
+ if (its_host->get_configuration()->is_security_enabled()) {
+ credentials::send_credentials(socket_.native(),
+ its_host->get_client());
+ }
+ }
+ }
+#endif
+
connect_cbk(error);
} else {
VSOMEIP_WARNING << "local_client_endpoint::connect: Error opening socket: "
@@ -65,9 +90,8 @@ void local_client_endpoint_impl::connect() {
void local_client_endpoint_impl::receive() {
#ifndef WIN32
- receive_buffer_t its_buffer(VSOMEIP_MAX_LOCAL_MESSAGE_SIZE , 0);
socket_.async_receive(
- boost::asio::buffer(its_buffer),
+ boost::asio::buffer(recv_buffer_),
std::bind(
&local_client_endpoint_impl::receive_cbk,
std::dynamic_pointer_cast<
@@ -129,11 +153,15 @@ void local_client_endpoint_impl::receive_cbk(
// endpoint was stopped
shutdown_and_close_socket();
} else if (_error == boost::asio::error::connection_reset
- || _error == boost::asio::error::eof) {
- VSOMEIP_TRACE << "local_client_endpoint: connection_reseted/EOF";
- } else {
+ || _error == boost::asio::error::eof
+ || _error != boost::asio::error::bad_descriptor) {
+ VSOMEIP_TRACE << "local_client_endpoint:"
+ " connection_reseted/EOF/bad_descriptor";
+ } else if (_error) {
VSOMEIP_ERROR << "Local endpoint received message ("
<< _error.message() << ")";
+ } else {
+ receive();
}
}
diff --git a/implementation/endpoints/src/local_server_endpoint_impl.cpp b/implementation/endpoints/src/local_server_endpoint_impl.cpp
index 42ffc2b..851185a 100644
--- a/implementation/endpoints/src/local_server_endpoint_impl.cpp
+++ b/implementation/endpoints/src/local_server_endpoint_impl.cpp
@@ -7,12 +7,19 @@
#include <iomanip>
#include <sstream>
+#include <sys/types.h>
#include <boost/asio/write.hpp>
#include "../include/endpoint_host.hpp"
#include "../include/local_server_endpoint_impl.hpp"
#include "../../logging/include/logger.hpp"
+#include "../../configuration/include/configuration.hpp"
+
+// Credentials
+#ifndef WIN32
+#include "../include/credentials.hpp"
+#endif
namespace vsomeip {
@@ -33,6 +40,32 @@ local_server_endpoint_impl::local_server_endpoint_impl(
boost::asio::detail::throw_error(ec, "acceptor bind");
acceptor_.listen(boost::asio::socket_base::max_connections, ec);
boost::asio::detail::throw_error(ec, "acceptor listen");
+
+#ifndef WIN32
+ if (_host->get_configuration()->is_security_enabled()) {
+ credentials::activate_credentials(acceptor_.native());
+ }
+#endif
+}
+
+local_server_endpoint_impl::local_server_endpoint_impl(
+ std::shared_ptr< endpoint_host > _host,
+ endpoint_type _local, boost::asio::io_service &_io,
+ std::uint32_t _max_message_size,
+ int native_socket)
+ : local_server_endpoint_base_impl(_host, _local, _io, _max_message_size),
+ acceptor_(_io), current_(nullptr) {
+ is_supporting_magic_cookies_ = false;
+
+ boost::system::error_code ec;
+ acceptor_.assign(_local.protocol(), native_socket, ec);
+ boost::asio::detail::throw_error(ec, "acceptor assign native socket");
+
+#ifndef WIN32
+ if (_host->get_configuration()->is_security_enabled()) {
+ credentials::activate_credentials(acceptor_.native());
+ }
+#endif
}
local_server_endpoint_impl::~local_server_endpoint_impl() {
@@ -106,12 +139,6 @@ void local_server_endpoint_impl::restart() {
current_->start();
}
-local_server_endpoint_impl::endpoint_type
-local_server_endpoint_impl::get_remote() const {
- boost::system::error_code its_error;
- return current_->get_socket().remote_endpoint(its_error);
-}
-
bool local_server_endpoint_impl::get_default_target(
service_t,
local_server_endpoint_impl::endpoint_type &) const {
@@ -134,21 +161,43 @@ void local_server_endpoint_impl::remove_connection(
void local_server_endpoint_impl::accept_cbk(
connection::ptr _connection, boost::system::error_code const &_error) {
+ if (_error != boost::asio::error::bad_descriptor &&
+ _error != boost::asio::error::operation_aborted) {
+ start();
+ }
+
if (!_error) {
socket_type &new_connection_socket = _connection->get_socket();
+#ifndef WIN32
+ auto its_host = host_.lock();
+ if (its_host) {
+ if (its_host->get_configuration()->is_security_enabled()) {
+ uid_t uid;
+ gid_t gid;
+ client_t client = credentials::receive_credentials(
+ new_connection_socket.native(), uid, gid);
+ if (!its_host->check_credentials(client, uid, gid)) {
+ VSOMEIP_WARNING << std::hex << "Client 0x" << its_host->get_client()
+ << " received client credentials from client 0x" << client
+ << " which violates the security policy : uid/gid="
+ << std::dec << uid << "/" << gid;
+ boost::system::error_code er;
+ new_connection_socket.close(er);
+ return;
+ }
+ _connection->set_bound_client(client);
+ credentials::deactivate_credentials(new_connection_socket.native());
+ }
+ }
+#endif
boost::system::error_code its_error;
endpoint_type remote = new_connection_socket.remote_endpoint(its_error);
- if(!its_error) {
+ if (!its_error) {
std::lock_guard<std::mutex> its_lock(connections_mutex_);
connections_[remote] = _connection;
_connection->start();
}
}
-
- if (_error != boost::asio::error::bad_descriptor &&
- _error != boost::asio::error::operation_aborted) {
- start();
- }
}
///////////////////////////////////////////////////////////////////////////////
@@ -162,7 +211,7 @@ local_server_endpoint_impl::connection::connection(
server_(_server),
max_message_size_(_max_message_size + 8),
recv_buffer_(max_message_size_, 0),
- recv_buffer_size_(0) {
+ recv_buffer_size_(0), bound_client_(VSOMEIP_ROUTING_CLIENT) {
}
local_server_endpoint_impl::connection::ptr
@@ -303,7 +352,8 @@ void local_server_endpoint_impl::connection::receive_cbk(
if (its_start != MESSAGE_IS_EMPTY &&
its_end + 3 < recv_buffer_size_ + its_iteration_gap) {
its_host->on_message(&recv_buffer_[its_start],
- uint32_t(its_end - its_start), its_server.get());
+ uint32_t(its_end - its_start), its_server.get(),
+ boost::asio::ip::address(), bound_client_);
#if 0
std::stringstream local_msg;
@@ -342,4 +392,8 @@ void local_server_endpoint_impl::connection::receive_cbk(
}
}
+void local_server_endpoint_impl::connection::set_bound_client(client_t _client) {
+ bound_client_ = _client;
+}
+
} // namespace vsomeip
diff --git a/implementation/endpoints/src/tcp_client_endpoint_impl.cpp b/implementation/endpoints/src/tcp_client_endpoint_impl.cpp
index 97e5579..5165e4b 100644
--- a/implementation/endpoints/src/tcp_client_endpoint_impl.cpp
+++ b/implementation/endpoints/src/tcp_client_endpoint_impl.cpp
@@ -52,12 +52,12 @@ void tcp_client_endpoint_impl::connect() {
if (!its_error || its_error == boost::asio::error::already_open) {
// Nagle algorithm off
- socket_.set_option(ip::tcp::no_delay(true));
+ socket_.set_option(ip::tcp::no_delay(true), its_error);
// Enable SO_REUSEADDR to avoid bind problems with services going offline
// and coming online again and the user has specified only a small number
// of ports in the clients section for one service instance
- socket_.set_option(boost::asio::socket_base::reuse_address(true));
+ socket_.set_option(boost::asio::socket_base::reuse_address(true), its_error);
// In case a client endpoint port was configured,
// bind to it before connecting
diff --git a/implementation/endpoints/src/tcp_server_endpoint_impl.cpp b/implementation/endpoints/src/tcp_server_endpoint_impl.cpp
index f3035ef..8e98fd0 100644
--- a/implementation/endpoints/src/tcp_server_endpoint_impl.cpp
+++ b/implementation/endpoints/src/tcp_server_endpoint_impl.cpp
@@ -121,12 +121,6 @@ bool tcp_server_endpoint_impl::is_established(std::shared_ptr<endpoint_definitio
return is_connected;
}
-tcp_server_endpoint_impl::endpoint_type
-tcp_server_endpoint_impl::get_remote() const {
- boost::system::error_code its_error;
- return current_->get_socket().remote_endpoint(its_error);
-}
-
bool tcp_server_endpoint_impl::get_remote_address(
boost::asio::ip::address &_address) const {
@@ -232,7 +226,8 @@ tcp_server_endpoint_impl::connection::get_socket() {
void tcp_server_endpoint_impl::connection::start() {
receive();
// Nagle algorithm off
- socket_.set_option(ip::tcp::no_delay(true));
+ boost::system::error_code ec;
+ socket_.set_option(ip::tcp::no_delay(true), ec);
}
void tcp_server_endpoint_impl::connection::receive() {
diff --git a/implementation/endpoints/src/udp_server_endpoint_impl.cpp b/implementation/endpoints/src/udp_server_endpoint_impl.cpp
index f1cd692..1585826 100644
--- a/implementation/endpoints/src/udp_server_endpoint_impl.cpp
+++ b/implementation/endpoints/src/udp_server_endpoint_impl.cpp
@@ -32,26 +32,30 @@ udp_server_endpoint_impl::udp_server_endpoint_impl(
boost::system::error_code ec;
boost::asio::socket_base::reuse_address optionReuseAddress(true);
- socket_.set_option(optionReuseAddress);
+ socket_.set_option(optionReuseAddress, ec);
+ boost::asio::detail::throw_error(ec, "reuse address");
+
+ socket_.bind(_local, ec);
+ boost::asio::detail::throw_error(ec, "bind");
if (_local.address().is_v4()) {
boost::asio::ip::address_v4 its_unicast_address
- = configuration::get()->get_unicast_address().to_v4();
+ = _host->get_configuration()->get_unicast_address().to_v4();
boost::asio::ip::multicast::outbound_interface option(its_unicast_address);
- socket_.set_option(option);
+ socket_.set_option(option, ec);
+ boost::asio::detail::throw_error(ec, "outbound interface option IPv4");
} else if (_local.address().is_v6()) {
boost::asio::ip::address_v6 its_unicast_address
- = configuration::get()->get_unicast_address().to_v6();
+ = _host->get_configuration()->get_unicast_address().to_v6();
boost::asio::ip::multicast::outbound_interface option(
static_cast<unsigned int>(its_unicast_address.scope_id()));
- socket_.set_option(option);
+ socket_.set_option(option, ec);
+ boost::asio::detail::throw_error(ec, "outbound interface option IPv6");
}
- socket_.bind(_local, ec);
- boost::asio::detail::throw_error(ec, "bind");
-
boost::asio::socket_base::broadcast option(true);
- socket_.set_option(option);
+ socket_.set_option(option, ec);
+ boost::asio::detail::throw_error(ec, "broadcast option");
#ifdef WIN32
const char* optval("0001");
@@ -140,11 +144,6 @@ void udp_server_endpoint_impl::send_queued(
);
}
-udp_server_endpoint_impl::endpoint_type
-udp_server_endpoint_impl::get_remote() const {
- return remote_;
-}
-
bool udp_server_endpoint_impl::get_remote_address(
boost::asio::ip::address &_address) const {
boost::asio::ip::address its_address = remote_.address();
@@ -171,16 +170,31 @@ void udp_server_endpoint_impl::join(const std::string &_address) {
socket_.set_option(ip::udp_ext::socket::reuse_address(true));
socket_.set_option(
boost::asio::ip::multicast::enable_loopback(false));
+#ifdef WIN32
+ socket_.set_option(boost::asio::ip::multicast::join_group(
+ boost::asio::ip::address::from_string(_address).to_v4(),
+ local_.address().to_v4()));
+#else
socket_.set_option(boost::asio::ip::multicast::join_group(
boost::asio::ip::address::from_string(_address).to_v4()));
+#endif
} else if (local_.address().is_v6()) {
socket_.set_option(ip::udp_ext::socket::reuse_address(true));
socket_.set_option(
boost::asio::ip::multicast::enable_loopback(false));
+#ifdef WIN32
+ socket_.set_option(boost::asio::ip::multicast::join_group(
+ boost::asio::ip::address::from_string(_address).to_v6(),
+ local_.address().to_v6().scope_id()));
+#else
socket_.set_option(boost::asio::ip::multicast::join_group(
boost::asio::ip::address::from_string(_address).to_v6()));
+#endif
}
joined_.insert(_address);
+ } else {
+ VSOMEIP_DEBUG << "udp_server_endpoint_impl::join: "
+ "Trying to join already joined address: " << _address;
}
}
catch (const std::exception &e) {
diff --git a/implementation/logging/include/defines.hpp b/implementation/logging/include/defines.hpp
index bef1a72..6107979 100644
--- a/implementation/logging/include/defines.hpp
+++ b/implementation/logging/include/defines.hpp
@@ -7,7 +7,7 @@
#define LOGGING_DEFINES_HPP_
#define VSOMEIP_LOG_DEFAULT_APPLICATION_ID "VSIP"
-#define VSOMEIP_LOG_DEFAULT_APPLICATION_NAME "vSomeIP application"
+#define VSOMEIP_LOG_DEFAULT_APPLICATION_NAME "vSomeIP application|SysInfra|IPC"
#define VSOMEIP_LOG_DEFAULT_CONTEXT_ID "VSIP"
#define VSOMEIP_LOG_DEFAULT_CONTEXT_NAME "vSomeIP context"
diff --git a/implementation/logging/include/logger_impl.hpp b/implementation/logging/include/logger_impl.hpp
index 9c7d0bf..c4fa14a 100644
--- a/implementation/logging/include/logger_impl.hpp
+++ b/implementation/logging/include/logger_impl.hpp
@@ -33,7 +33,7 @@ typedef boost::log::sinks::synchronous_sink<
class logger_impl: public logger {
public:
static std::shared_ptr<logger_impl> & get();
- static void init(const std::shared_ptr<configuration> &_configuration);
+ VSOMEIP_IMPORT_EXPORT static void init(const std::shared_ptr<configuration> &_configuration);
logger_impl();
@@ -42,12 +42,17 @@ public:
private:
void enable_console();
+ void disable_console();
+
void enable_file(const std::string &_path);
+ void disable_file();
+
void enable_dlt(const std::string &_app_id,
const std::string &_context_id);
+ void disable_dlt();
private:
- static boost::log::sources::severity_logger_mt<
+ boost::log::sources::severity_logger_mt<
boost::log::trivial::severity_level> logger_;
boost::log::trivial::severity_level loglevel_;
diff --git a/implementation/logging/src/logger_impl.cpp b/implementation/logging/src/logger_impl.cpp
index f7c1948..87a7af7 100644
--- a/implementation/logging/src/logger_impl.cpp
+++ b/implementation/logging/src/logger_impl.cpp
@@ -46,9 +46,6 @@ using namespace boost::log::trivial;
namespace vsomeip {
-boost::log::sources::severity_logger_mt<
- boost::log::trivial::severity_level> logger_impl::logger_;
-
std::shared_ptr<logger_impl> & logger_impl::get() {
static std::shared_ptr<logger_impl> the_logger__ = std::make_shared<
logger_impl>();
@@ -74,9 +71,13 @@ void logger_impl::init(const std::shared_ptr<configuration> &_configuration) {
if (_configuration->has_console_log())
get()->enable_console();
+ else
+ get()->disable_console();
if (_configuration->has_file_log())
get()->enable_file(_configuration->get_logfile());
+ else
+ get()->disable_file();
if (_configuration->has_dlt_log()) {
std::string app_id = runtime::get_property("LogApplication");
@@ -84,6 +85,13 @@ void logger_impl::init(const std::shared_ptr<configuration> &_configuration) {
std::string context_id = runtime::get_property("LogContext");
if (context_id == "") context_id = VSOMEIP_LOG_DEFAULT_CONTEXT_ID;
get()->enable_dlt(app_id, context_id);
+ } else
+ get()->disable_dlt();
+
+ if (!_configuration->has_console_log() &&
+ !_configuration->has_file_log() &&
+ !_configuration->has_dlt_log()) {
+ get()->use_null_logger();
}
}
@@ -114,6 +122,11 @@ void logger_impl::enable_console() {
logging::core::get()->add_sink(console_sink_);
}
+void logger_impl::disable_console() {
+ if (console_sink_)
+ logging::core::get()->remove_sink(console_sink_);
+}
+
void logger_impl::enable_file(const std::string &_path) {
if (file_sink_)
return;
@@ -135,6 +148,12 @@ void logger_impl::enable_file(const std::string &_path) {
logging::core::get()->add_sink(file_sink_);
}
+void logger_impl::disable_file() {
+ if (file_sink_)
+ logging::core::get()->remove_sink(file_sink_);
+}
+
+
void logger_impl::enable_dlt(const std::string &_app_id,
const std::string &_context_id) {
#ifdef USE_DLT
@@ -151,6 +170,11 @@ void logger_impl::enable_dlt(const std::string &_app_id,
#endif
}
+void logger_impl::disable_dlt() {
+ if (dlt_sink_)
+ logging::core::get()->remove_sink(dlt_sink_);
+}
+
void logger_impl::use_null_logger() {
boost::shared_ptr<sinks::text_ostream_backend> backend = boost::make_shared<
sinks::text_ostream_backend>();
diff --git a/implementation/routing/include/event.hpp b/implementation/routing/include/event.hpp
index 2a76ad8..ef7e7eb 100644
--- a/implementation/routing/include/event.hpp
+++ b/implementation/routing/include/event.hpp
@@ -46,16 +46,16 @@ public:
const std::shared_ptr<payload> get_payload() const;
void set_payload(const std::shared_ptr<payload> &_payload,
- const client_t _client, bool _force = false);
+ const client_t _client, bool _force, bool _flush);
void set_payload(const std::shared_ptr<payload> &_payload,
const std::shared_ptr<endpoint_definition> _target,
- bool _force = false);
+ bool _force, bool _flush);
void set_payload_dont_notify(const std::shared_ptr<payload> &_payload);
void set_payload(const std::shared_ptr<payload> &_payload,
- bool _force = false);
+ bool _force, bool _flush);
void unset_payload(bool _force = false);
bool is_field() const;
@@ -80,8 +80,8 @@ public:
void add_eventgroup(eventgroup_t _eventgroup);
void set_eventgroups(const std::set<eventgroup_t> &_eventgroups);
- void notify_one(const std::shared_ptr<endpoint_definition> &_target);
- void notify_one(client_t _client);
+ void notify_one(const std::shared_ptr<endpoint_definition> &_target, bool _flush);
+ void notify_one(client_t _client, bool _flush);
void add_ref(client_t _client, bool _is_provided);
void remove_ref(client_t _client, bool _is_provided);
@@ -95,7 +95,7 @@ public:
private:
void update_cbk(boost::system::error_code const &_error);
- void notify();
+ void notify(bool _flush);
void notify(client_t _client, const std::shared_ptr<endpoint_definition> &_target);
void start_cycle();
@@ -108,7 +108,7 @@ private:
private:
routing_manager *routing_;
- std::mutex mutex_;
+ mutable std::mutex mutex_;
std::shared_ptr<message> message_;
bool is_field_;
diff --git a/implementation/routing/include/routing_manager.hpp b/implementation/routing/include/routing_manager.hpp
index dcbdd5a..1fc63d4 100644
--- a/implementation/routing/include/routing_manager.hpp
+++ b/implementation/routing/include/routing_manager.hpp
@@ -22,7 +22,6 @@ class endpoint;
class endpoint_definition;
class event;
class payload;
-class service_info;
class routing_manager {
public:
@@ -66,10 +65,10 @@ public:
instance_t _instance, bool _flush, bool _reliable) = 0;
virtual bool send_to(const std::shared_ptr<endpoint_definition> &_target,
- std::shared_ptr<message>) = 0;
+ 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) = 0;
+ const byte_t *_data, uint32_t _size, bool _flush) = 0;
virtual void register_event(client_t _client, service_t _service,
instance_t _instance, event_t _event,
@@ -90,14 +89,16 @@ public:
virtual void notify(service_t _service, instance_t _instance,
event_t _event, std::shared_ptr<payload> _payload,
- bool _force) = 0;
+ bool _force, bool _flush) = 0;
virtual void notify_one(service_t _service, instance_t _instance,
event_t _event, std::shared_ptr<payload> _payload,
- client_t _client, bool _force) = 0;
+ client_t _client, bool _force, bool _flush) = 0;
virtual void on_identify_response(client_t _client, service_t _service,
instance_t _instance, bool _reliable) = 0;
+
+ virtual void set_routing_state(routing_state_e _routing_state) = 0;
};
} // namespace vsomeip
diff --git a/implementation/routing/include/routing_manager_base.hpp b/implementation/routing/include/routing_manager_base.hpp
index a7c127c..a1320ec 100644
--- a/implementation/routing/include/routing_manager_base.hpp
+++ b/implementation/routing/include/routing_manager_base.hpp
@@ -8,6 +8,8 @@
#include <mutex>
#include <unordered_set>
+#include <queue>
+#include <condition_variable>
#include <vsomeip/constants.hpp>
#include "routing_manager.hpp"
@@ -86,11 +88,12 @@ public:
instance_t _instance, eventgroup_t _eventgroup);
virtual void notify(service_t _service, instance_t _instance,
- event_t _event, std::shared_ptr<payload> _payload, bool _force);
+ event_t _event, std::shared_ptr<payload> _payload,
+ bool _force, bool _flush);
virtual void notify_one(service_t _service, instance_t _instance,
event_t _event, std::shared_ptr<payload> _payload,
- client_t _client, bool _force);
+ client_t _client, bool _force, bool _flush);
virtual bool send(client_t _client, std::shared_ptr<message> _message,
bool _flush);
@@ -103,12 +106,17 @@ public:
virtual void on_disconnect(std::shared_ptr<endpoint> _endpoint) = 0;
virtual void on_message(const byte_t *_data, length_t _length,
endpoint *_receiver, const boost::asio::ip::address &_destination
- = boost::asio::ip::address()) = 0;
+ = boost::asio::ip::address(), client_t _bound_client = VSOMEIP_ROUTING_CLIENT) = 0;
virtual void on_error(const byte_t *_data, length_t _length,
endpoint *_receiver) = 0;
+#ifndef WIN32
+ virtual bool check_credentials(client_t _client, uid_t _uid, gid_t _gid);
+#endif
virtual void on_clientendpoint_error(client_t _client);
+ virtual void set_routing_state(routing_state_e _routing_state) = 0;
+
protected:
std::shared_ptr<serviceinfo> find_service(service_t _service, instance_t _instance) const;
std::shared_ptr<serviceinfo> create_service_info(service_t _service,
@@ -152,16 +160,30 @@ protected:
bool insert_subscription(service_t _service, instance_t _instance,
eventgroup_t _eventgroup, client_t _client);
+ std::shared_ptr<deserializer> get_deserializer();
+ void put_deserializer(std::shared_ptr<deserializer>);
+
+ void send_pending_subscriptions(service_t _service,
+ instance_t _instance, major_version_t _major);
+
+ virtual void send_subscribe(client_t _client, service_t _service,
+ instance_t _instance, eventgroup_t _eventgroup,
+ major_version_t _major, subscription_type_e _subscription_type) = 0;
+
+ void remove_pending_subscription(service_t _service, instance_t _instance);
+
routing_manager_host *host_;
boost::asio::io_service &io_;
client_t client_;
std::shared_ptr<configuration> configuration_;
std::shared_ptr<serializer> serializer_;
- std::shared_ptr<deserializer> deserializer_;
-
std::mutex serialize_mutex_;
+ std::queue<std::shared_ptr<deserializer>> deserializers_;
+ std::mutex deserializer_mutex_;
+ std::condition_variable deserializer_condition_;
+
std::mutex local_services_mutex_;
std::map<service_t, std::map<instance_t, std::tuple< major_version_t, minor_version_t, client_t> > > local_services_;
@@ -181,6 +203,24 @@ protected:
std::shared_ptr<tc::trace_connector> tc_;
#endif
+ struct eventgroup_data_t {
+ service_t service_;
+ instance_t instance_;
+ eventgroup_t eventgroup_;
+ major_version_t major_;
+ subscription_type_e subscription_type_;
+
+ bool operator<(const eventgroup_data_t &_other) const {
+ return (service_ < _other.service_
+ || (service_ == _other.service_
+ && instance_ < _other.instance_)
+ || (service_ == _other.service_
+ && instance_ == _other.instance_
+ && eventgroup_ < _other.eventgroup_));
+ }
+ };
+ std::set<eventgroup_data_t> pending_subscriptions_;
+
private:
services_t services_;
mutable std::mutex services_mutex_;
diff --git a/implementation/routing/include/routing_manager_impl.hpp b/implementation/routing/include/routing_manager_impl.hpp
index b08f2cd..81c1530 100644
--- a/implementation/routing/include/routing_manager_impl.hpp
+++ b/implementation/routing/include/routing_manager_impl.hpp
@@ -52,7 +52,7 @@ public:
boost::asio::io_service & get_io();
client_t get_client() const;
- std::shared_ptr<configuration> get_configuration() const;
+ const std::shared_ptr<configuration> get_configuration() const;
void init();
void start();
@@ -85,10 +85,10 @@ public:
instance_t _instance, bool _flush, bool _reliable);
bool send_to(const std::shared_ptr<endpoint_definition> &_target,
- std::shared_ptr<message> _message);
+ std::shared_ptr<message> _message, bool _flush);
bool send_to(const std::shared_ptr<endpoint_definition> &_target,
- const byte_t *_data, uint32_t _size);
+ const byte_t *_data, uint32_t _size, bool _flush);
bool send_to(const std::shared_ptr<endpoint_definition> &_target,
const byte_t *_data, uint32_t _size, uint16_t _sd_port);
@@ -103,11 +103,11 @@ public:
bool _is_provided);
void notify(service_t _service, instance_t _instance, event_t _event,
- std::shared_ptr<payload> _payload, bool _force);
+ std::shared_ptr<payload> _payload, bool _force, bool _flush);
void notify_one(service_t _service, instance_t _instance,
event_t _event, std::shared_ptr<payload> _payload,
- client_t _client, bool _force);
+ client_t _client, bool _force, bool _flush);
void on_subscribe_nack(client_t _client, service_t _service,
instance_t _instance, eventgroup_t _eventgroup);
@@ -119,8 +119,13 @@ public:
bool _reliable);
// interface to stub
- std::shared_ptr<endpoint> find_local(client_t _client);
- std::shared_ptr<endpoint> find_or_create_local(client_t _client);
+ inline std::shared_ptr<endpoint> find_local(client_t _client) {
+ return routing_manager_base::find_local(_client);
+ }
+ inline std::shared_ptr<endpoint> find_or_create_local(
+ client_t _client) {
+ return routing_manager_base::find_or_create_local(_client);
+ }
void remove_local(client_t _client);
void on_stop_offer_service(client_t _client, service_t _service, instance_t _instance,
major_version_t _major, minor_version_t _minor);
@@ -135,7 +140,8 @@ public:
void on_disconnect(std::shared_ptr<endpoint> _endpoint);
void on_error(const byte_t *_data, length_t _length, endpoint *_receiver);
void on_message(const byte_t *_data, length_t _length, endpoint *_receiver,
- const boost::asio::ip::address &_destination);
+ const boost::asio::ip::address &_destination,
+ client_t _bound_client);
void on_message(service_t _service, instance_t _instance,
const byte_t *_data, length_t _size, bool _reliable);
void on_notification(client_t _client, service_t _service,
@@ -188,6 +194,8 @@ public:
void on_clientendpoint_error(client_t _client);
void confirm_pending_offers(client_t _client);
+ void set_routing_state(routing_state_e _routing_state);
+
private:
bool deliver_message(const byte_t *_data, length_t _length,
instance_t _instance, bool _reliable);
@@ -268,6 +276,14 @@ private:
void remove_identifying_client(service_t _service, instance_t _instance, client_t _client);
+ inline std::shared_ptr<endpoint> find_local(service_t _service, instance_t _instance) {
+ return routing_manager_base::find_local(_service, _instance);
+ }
+
+ void send_subscribe(client_t _client, service_t _service,
+ instance_t _instance, eventgroup_t _eventgroup,
+ major_version_t _major, subscription_type_e _subscription_type);
+
std::shared_ptr<routing_manager_stub> stub_;
std::shared_ptr<sd::service_discovery> discovery_;
@@ -310,6 +326,7 @@ private:
std::shared_ptr<serviceinfo> sd_info_;
std::map<bool, std::set<uint16_t>> used_client_ports_;
+ std::mutex used_client_ports_mutex_;
boost::asio::steady_timer version_log_timer_;
@@ -326,6 +343,8 @@ private:
std::map<instance_t,
std::tuple<major_version_t, minor_version_t,
client_t, client_t>>> pending_offers_;
+
+ std::mutex pending_subscription_mutex_;
};
} // namespace vsomeip
diff --git a/implementation/routing/include/routing_manager_proxy.hpp b/implementation/routing/include/routing_manager_proxy.hpp
index bea1c24..33c6c26 100644
--- a/implementation/routing/include/routing_manager_proxy.hpp
+++ b/implementation/routing/include/routing_manager_proxy.hpp
@@ -22,6 +22,8 @@ class configuration;
class event;
class routing_manager_host;
+class logger;
+
class routing_manager_proxy: public routing_manager_base {
public:
routing_manager_proxy(routing_manager_host *_host);
@@ -31,6 +33,8 @@ public:
void start();
void stop();
+ const std::shared_ptr<configuration> get_configuration() const;
+
bool offer_service(client_t _client, service_t _service,
instance_t _instance, major_version_t _major,
minor_version_t _minor);
@@ -56,10 +60,10 @@ public:
instance_t _instance, bool _flush = true, bool _reliable = false);
bool send_to(const std::shared_ptr<endpoint_definition> &_target,
- std::shared_ptr<message> _message);
+ std::shared_ptr<message> _message, bool _flush);
bool send_to(const std::shared_ptr<endpoint_definition> &_target,
- const byte_t *_data, uint32_t _size);
+ const byte_t *_data, uint32_t _size, bool _flush);
void register_event(client_t _client, service_t _service,
instance_t _instance, event_t _event,
@@ -73,12 +77,13 @@ public:
bool _is_provided);
void notify(service_t _service, instance_t _instance, event_t _event,
- std::shared_ptr<payload> _payload, bool _force);
+ std::shared_ptr<payload> _payload, bool _force, bool _flush);
void on_connect(std::shared_ptr<endpoint> _endpoint);
void on_disconnect(std::shared_ptr<endpoint> _endpoint);
void on_message(const byte_t *_data, length_t _length, endpoint *_receiver,
- const boost::asio::ip::address &_destination);
+ const boost::asio::ip::address &_destination,
+ client_t _bound_client);
void on_error(const byte_t *_data, length_t _length, endpoint *_receiver);
void release_port(uint16_t _port, bool _reliable);
@@ -123,9 +128,6 @@ private:
void on_subscribe_ack(client_t _client, service_t _service,
instance_t _instance, eventgroup_t _eventgroup);
- void send_pending_subscriptions(service_t _service, instance_t _instance,
- major_version_t _major);
-
void cache_event_payload(const std::shared_ptr<message> &_message);
void on_stop_offer_service(service_t _service, instance_t _instance,
@@ -142,6 +144,15 @@ private:
eventgroup_t _eventgroup, bool _increment);
void register_application_timeout_cbk(boost::system::error_code const &_error);
+
+ void send_registered_ack();
+
+ void set_routing_state(routing_state_e _routing_state) {
+ (void)_routing_state;
+ };
+
+ bool is_client_known(client_t _client);
+
private:
enum class inner_state_type_e : std::uint8_t {
ST_REGISTERED = 0x0,
@@ -156,6 +167,7 @@ private:
std::shared_ptr<endpoint> sender_; // --> stub
std::shared_ptr<endpoint> receiver_; // --> from everybody
+ std::mutex known_clients_mutex_;
std::unordered_set<client_t> known_clients_;
struct service_data_t {
@@ -193,31 +205,14 @@ private:
};
std::set<event_data_t> pending_event_registrations_;
- struct eventgroup_data_t {
- service_t service_;
- instance_t instance_;
- eventgroup_t eventgroup_;
- major_version_t major_;
- subscription_type_e subscription_type_;
-
- bool operator<(const eventgroup_data_t &_other) const {
- return (service_ < _other.service_
- || (service_ == _other.service_
- && instance_ < _other.instance_)
- || (service_ == _other.service_
- && instance_ == _other.instance_
- && eventgroup_ < _other.eventgroup_));
- }
- };
- std::set<eventgroup_data_t> pending_subscriptions_;
std::map<client_t, std::set<eventgroup_data_t>> pending_ingoing_subscripitons_;
+ std::mutex pending_ingoing_subscripitons_mutex_;
std::map<service_t,
std::map<instance_t,
std::map<event_t,
std::shared_ptr<message> > > > pending_notifications_;
- std::mutex send_mutex_;
std::mutex deserialize_mutex_;
std::mutex state_mutex_;
@@ -229,6 +224,8 @@ private:
mutable std::recursive_mutex sender_mutex_;
boost::asio::steady_timer register_application_timer_;
+
+ std::shared_ptr<logger> logger_;
};
} // namespace vsomeip
diff --git a/implementation/routing/include/routing_manager_stub.hpp b/implementation/routing/include/routing_manager_stub.hpp
index 6255cda..f1e657a 100644
--- a/implementation/routing/include/routing_manager_stub.hpp
+++ b/implementation/routing/include/routing_manager_stub.hpp
@@ -13,11 +13,13 @@
#include <mutex>
#include <set>
#include <thread>
+#include <atomic>
#include <boost/asio/io_service.hpp>
#include <boost/asio/steady_timer.hpp>
#include "../../endpoints/include/endpoint_host.hpp"
+#include "../../configuration/include/internal.hpp"
namespace vsomeip {
@@ -36,10 +38,13 @@ public:
void start();
void stop();
+ const std::shared_ptr<configuration> get_configuration() const;
+
void on_connect(std::shared_ptr<endpoint> _endpoint);
void on_disconnect(std::shared_ptr<endpoint> _endpoint);
void on_message(const byte_t *_data, length_t _length, endpoint *_receiver,
- const boost::asio::ip::address &_destination);
+ const boost::asio::ip::address &_destination,
+ client_t _bound_client);
void on_error(const byte_t *_data, length_t _length, endpoint *_receiver);
void release_port(uint16_t _port, bool _reliable);
@@ -71,13 +76,18 @@ public:
void create_local_receiver();
bool send_ping(client_t _client);
void deregister_erroneous_client(client_t _client);
+ client_t get_client() const;
+#ifndef WIN32
+ virtual bool check_credentials(client_t _client, uid_t _uid, gid_t _gid);
+#endif
private:
void broadcast(const std::vector<byte_t> &_command) const;
void on_register_application(client_t _client);
void on_deregister_application(client_t _client);
- void broadcast_routing_info(bool _empty = false);
+ void broadcast_routing_info(bool _empty = false,
+ client_t _ignore = VSOMEIP_ROUTING_CLIENT);
void send_routing_info(client_t _client, bool _empty = false);
void broadcast_ping() const;
@@ -90,6 +100,9 @@ private:
void init_routing_endpoint();
void on_ping_timer_expired(boost::system::error_code const &_error);
void remove_from_pinged_clients(client_t _client);
+ void set_routing_state(routing_state_e _routing_state) {
+ (void)_routing_state;
+ };
private:
routing_manager_stub_host *host_;
@@ -108,7 +121,8 @@ private:
size_t routingCommandSize_;
- bool client_registration_running_;
+ bool is_socket_activated_;
+ std::atomic<bool> client_registration_running_;
std::shared_ptr<std::thread> client_registration_thread_;
std::mutex client_registration_mutex_;
std::condition_variable client_registration_condition_;
diff --git a/implementation/routing/include/routing_manager_stub_host.hpp b/implementation/routing/include/routing_manager_stub_host.hpp
index 0d1decb..aa8fe02 100644
--- a/implementation/routing/include/routing_manager_stub_host.hpp
+++ b/implementation/routing/include/routing_manager_stub_host.hpp
@@ -78,6 +78,7 @@ public:
virtual void on_pong(client_t _client) = 0;
virtual void on_clientendpoint_error(client_t _client) = 0;
virtual void confirm_pending_offers(client_t _client) = 0;
+ virtual void set_routing_state(routing_state_e _routing_state) = 0;
};
} // namespace vsomeip
diff --git a/implementation/routing/include/serviceinfo.hpp b/implementation/routing/include/serviceinfo.hpp
index 44050b8..4a8a69a 100644
--- a/implementation/routing/include/serviceinfo.hpp
+++ b/implementation/routing/include/serviceinfo.hpp
@@ -47,6 +47,9 @@ public:
VSOMEIP_EXPORT bool is_local() const;
+ VSOMEIP_EXPORT bool is_in_mainphase() const;
+ VSOMEIP_EXPORT void set_is_in_mainphase(bool _in_mainphase);
+
private:
servicegroup *group_;
@@ -60,6 +63,7 @@ private:
std::set<client_t> requesters_;
bool is_local_;
+ bool is_in_mainphase_;
};
} // namespace vsomeip
diff --git a/implementation/routing/src/event.cpp b/implementation/routing/src/event.cpp
index c077844..653f262 100644
--- a/implementation/routing/src/event.cpp
+++ b/implementation/routing/src/event.cpp
@@ -85,10 +85,12 @@ bool event::is_set() const {
}
const std::shared_ptr<payload> event::get_payload() const {
+ std::lock_guard<std::mutex> its_lock(mutex_);
return (message_->get_payload());
}
void event::set_payload_dont_notify(const std::shared_ptr<payload> &_payload) {
+ std::lock_guard<std::mutex> its_lock(mutex_);
if(is_cache_placeholder_) {
reset_payload(_payload);
is_set_ = true;
@@ -99,7 +101,9 @@ void event::set_payload_dont_notify(const std::shared_ptr<payload> &_payload) {
}
}
-void event::set_payload(const std::shared_ptr<payload> &_payload, bool _force) {
+void event::set_payload(const std::shared_ptr<payload> &_payload,
+ bool _force, bool _flush) {
+ std::lock_guard<std::mutex> its_lock(mutex_);
if (is_provided_) {
if (set_payload_helper(_payload, _force)) {
reset_payload(_payload);
@@ -107,7 +111,7 @@ void event::set_payload(const std::shared_ptr<payload> &_payload, bool _force) {
if (change_resets_cycle_)
stop_cycle();
- notify();
+ notify(_flush);
if (change_resets_cycle_)
start_cycle();
@@ -120,12 +124,13 @@ void event::set_payload(const std::shared_ptr<payload> &_payload, bool _force) {
}
void event::set_payload(const std::shared_ptr<payload> &_payload, client_t _client,
- bool _force) {
+ bool _force, bool _flush) {
+ std::lock_guard<std::mutex> its_lock(mutex_);
if (is_provided_) {
if (set_payload_helper(_payload, _force)) {
reset_payload(_payload);
if (is_updating_on_change_) {
- notify_one(_client);
+ notify_one(_client, _flush);
}
}
} else {
@@ -136,12 +141,13 @@ void event::set_payload(const std::shared_ptr<payload> &_payload, client_t _clie
void event::set_payload(const std::shared_ptr<payload> &_payload,
const std::shared_ptr<endpoint_definition> _target,
- bool _force) {
+ bool _force, bool _flush) {
+ std::lock_guard<std::mutex> its_lock(mutex_);
if (is_provided_) {
if (set_payload_helper(_payload, _force)) {
reset_payload(_payload);
if (is_updating_on_change_) {
- notify_one(_target);
+ notify_one(_target, _flush);
}
}
} else {
@@ -151,6 +157,7 @@ void event::set_payload(const std::shared_ptr<payload> &_payload,
}
void event::unset_payload(bool _force) {
+ std::lock_guard<std::mutex> its_lock(mutex_);
if (_force) {
is_set_ = false;
stop_cycle();
@@ -202,7 +209,7 @@ void event::set_eventgroups(const std::set<eventgroup_t> &_eventgroups) {
void event::update_cbk(boost::system::error_code const &_error) {
if (!_error) {
cycle_timer_.expires_from_now(cycle_);
- notify();
+ notify(true);
std::function<void(boost::system::error_code const &)> its_handler =
std::bind(&event::update_cbk, shared_from_this(),
std::placeholders::_1);
@@ -210,27 +217,27 @@ void event::update_cbk(boost::system::error_code const &_error) {
}
}
-void event::notify() {
+void event::notify(bool _flush) {
if (is_set_) {
- routing_->send(VSOMEIP_ROUTING_CLIENT, message_, true);
+ routing_->send(VSOMEIP_ROUTING_CLIENT, message_, _flush);
} else {
VSOMEIP_DEBUG << "Notify event " << std::hex << message_->get_method()
<< "failed. Event payload not set!";
}
}
-void event::notify_one(const std::shared_ptr<endpoint_definition> &_target) {
+void event::notify_one(const std::shared_ptr<endpoint_definition> &_target, bool _flush) {
if (is_set_) {
- routing_->send_to(_target, message_);
+ routing_->send_to(_target, message_, _flush);
} else {
VSOMEIP_DEBUG << "Notify one event " << std::hex << message_->get_method()
<< "failed. Event payload not set!";
}
}
-void event::notify_one(client_t _client) {
+void event::notify_one(client_t _client, bool _flush) {
if (is_set_) {
- routing_->send(_client, message_, true);
+ routing_->send(_client, message_, _flush);
} else {
VSOMEIP_DEBUG << "Notify one event " << std::hex << message_->get_method()
<< " to client " << _client << " failed. Event payload not set!";
diff --git a/implementation/routing/src/routing_manager_base.cpp b/implementation/routing/src/routing_manager_base.cpp
index e146d65..89a5843 100644
--- a/implementation/routing/src/routing_manager_base.cpp
+++ b/implementation/routing/src/routing_manager_base.cpp
@@ -20,12 +20,14 @@ routing_manager_base::routing_manager_base(routing_manager_host *_host) :
io_(host_->get_io()),
client_(host_->get_client()),
configuration_(host_->get_configuration()),
- serializer_(std::make_shared<serializer>()),
- deserializer_(std::make_shared<deserializer>())
+ serializer_(std::make_shared<serializer>())
#ifdef USE_DLT
, tc_(tc::trace_connector::get())
#endif
{
+ for (int i = 0; i < VSOMEIP_MAX_DESERIALIZER; ++i) {
+ deserializers_.push(std::make_shared<deserializer>());
+ }
}
routing_manager_base::~routing_manager_base() {
@@ -303,7 +305,7 @@ void routing_manager_base::subscribe(client_t _client, service_t _service,
= its_eventgroup->get_events();
for (auto e : its_events) {
if (e->is_field())
- e->notify_one(_client);
+ e->notify_one(_client, true); // TODO: use _flush to send all events together!
}
}
}
@@ -325,10 +327,11 @@ void routing_manager_base::unsubscribe(client_t _client, service_t _service,
}
void routing_manager_base::notify(service_t _service, instance_t _instance,
- event_t _event, std::shared_ptr<payload> _payload, bool _force) {
+ event_t _event, std::shared_ptr<payload> _payload,
+ bool _force, bool _flush) {
std::shared_ptr<event> its_event = find_event(_service, _instance, _event);
if (its_event) {
- its_event->set_payload(_payload, _force);
+ its_event->set_payload(_payload, _force, _flush);
} else {
VSOMEIP_WARNING << "Attempt to update the undefined event/field ["
<< std::hex << _service << "." << _instance << "." << _event
@@ -338,7 +341,7 @@ void routing_manager_base::notify(service_t _service, instance_t _instance,
void routing_manager_base::notify_one(service_t _service, instance_t _instance,
event_t _event, std::shared_ptr<payload> _payload,
- client_t _client, bool _force) {
+ client_t _client, bool _force, bool _flush) {
std::shared_ptr<event> its_event = find_event(_service, _instance, _event);
if (its_event) {
// Event is valid for service/instance
@@ -354,7 +357,7 @@ void routing_manager_base::notify_one(service_t _service, instance_t _instance,
}
}
if (found_eventgroup) {
- its_event->set_payload(_payload, _client, _force);
+ its_event->set_payload(_payload, _client, _force, _flush);
}
} else {
VSOMEIP_WARNING << "Attempt to update the undefined event/field ["
@@ -757,11 +760,16 @@ bool routing_manager_base::send_local(
const byte_t *_data, uint32_t _size, instance_t _instance,
bool _flush, bool _reliable, uint8_t _command) const {
+ client_t sender = get_client();
+ size_t additional_size = 0;
+ if (_command == VSOMEIP_NOTIFY_ONE) {
+ additional_size +=sizeof(client_t);
+ }
std::vector<byte_t> its_command(
VSOMEIP_COMMAND_HEADER_SIZE + _size + sizeof(instance_t)
- + sizeof(bool) + sizeof(bool));
+ + sizeof(bool) + sizeof(bool) + additional_size);
its_command[VSOMEIP_COMMAND_TYPE_POS] = _command;
- std::memcpy(&its_command[VSOMEIP_COMMAND_CLIENT_POS], &_client,
+ std::memcpy(&its_command[VSOMEIP_COMMAND_CLIENT_POS], &sender,
sizeof(client_t));
std::memcpy(&its_command[VSOMEIP_COMMAND_SIZE_POS_MIN], &_size,
sizeof(_size));
@@ -773,6 +781,11 @@ 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));
+ 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));
+ }
return _target->send(&its_command[0], uint32_t(its_command.size()));
}
@@ -804,4 +817,57 @@ void routing_manager_base::on_clientendpoint_error(client_t _client) {
remove_local(_client);
}
+std::shared_ptr<deserializer> routing_manager_base::get_deserializer() {
+ std::unique_lock<std::mutex> its_lock(deserializer_mutex_);
+ while (deserializers_.empty()) {
+ VSOMEIP_INFO << std::hex << "client " << get_client() <<
+ "routing_manager_base::get_deserializer ~> all in use!";
+ deserializer_condition_.wait(its_lock);
+ VSOMEIP_INFO << std::hex << "client " << get_client() <<
+ "routing_manager_base::get_deserializer ~> wait finished!";
+ }
+ auto deserializer = deserializers_.front();
+ deserializers_.pop();
+ return deserializer;
+}
+
+void routing_manager_base::put_deserializer(std::shared_ptr<deserializer> _deserializer) {
+ {
+ std::lock_guard<std::mutex> its_lock(deserializer_mutex_);
+ deserializers_.push(_deserializer);
+ }
+ deserializer_condition_.notify_one();
+}
+
+#ifndef WIN32
+bool routing_manager_base::check_credentials(client_t _client, uid_t _uid, gid_t _gid) {
+ return configuration_->check_credentials(_client, _uid, _gid);
+}
+#endif
+
+void routing_manager_base::send_pending_subscriptions(service_t _service,
+ instance_t _instance, major_version_t _major) {
+ for (auto &ps : pending_subscriptions_) {
+ if (ps.service_ == _service &&
+ ps.instance_ == _instance && ps.major_ == _major) {
+ send_subscribe(client_, ps.service_, ps.instance_,
+ ps.eventgroup_, ps.major_, ps.subscription_type_);
+ }
+ }
+}
+
+void routing_manager_base::remove_pending_subscription(service_t _service,
+ instance_t _instance) {
+ auto it = pending_subscriptions_.begin();
+ while (it != pending_subscriptions_.end()) {
+ if (it->service_ == _service
+ && it->instance_ == _instance) {
+ break;
+ }
+ it++;
+ }
+ if (it != pending_subscriptions_.end()) pending_subscriptions_.erase(it);
+}
+
+
} // namespace vsomeip
diff --git a/implementation/routing/src/routing_manager_impl.cpp b/implementation/routing/src/routing_manager_impl.cpp
index 99c8c7d..7a27e4e 100644
--- a/implementation/routing/src/routing_manager_impl.cpp
+++ b/implementation/routing/src/routing_manager_impl.cpp
@@ -136,8 +136,6 @@ void routing_manager_impl::stop() {
bool routing_manager_impl::offer_service(client_t _client, service_t _service,
instance_t _instance, major_version_t _major, minor_version_t _minor) {
- std::shared_ptr<serviceinfo> its_info = find_service(_service, _instance);
-
VSOMEIP_DEBUG << "OFFER("
<< std::hex << std::setw(4) << std::setfill('0') << _client <<"): ["
<< std::hex << std::setw(4) << std::setfill('0') << _service << "."
@@ -165,9 +163,23 @@ bool routing_manager_impl::offer_service(client_t _client, service_t _service,
}
if (discovery_) {
- discovery_->on_offer_change();
+ std::shared_ptr<serviceinfo> its_info = find_service(_service, _instance);
+ if (its_info) {
+ discovery_->offer_service(_service, _instance, its_info);
+ }
}
+ {
+ std::lock_guard<std::mutex> ist_lock(pending_subscription_mutex_);
+ for (auto &ps : pending_subscriptions_) {
+ if (ps.service_ == _service &&
+ ps.instance_ == _instance && ps.major_ == _major) {
+ insert_subscription(ps.service_, ps.instance_,
+ ps.eventgroup_, client_);
+ }
+ }
+ send_pending_subscriptions(_service, _instance, _major);
+ }
stub_->on_offer_service(_client, _service, _instance, _major, _minor);
host_->on_availability(_service, _instance, true, _major, _minor);
return true;
@@ -368,14 +380,21 @@ void routing_manager_impl::subscribe(client_t _client, service_t _service,
= its_eventgroup->get_events();
for (auto e : its_events) {
if (e->is_field())
- e->notify_one(_client);
+ e->notify_one(_client, true); // TODO: use _flush to send all initial events together
}
}
} else {
- stub_->send_subscribe(routing_manager_base::find_local(_service, _instance),
- _client, _service, _instance, _eventgroup, _major, false);
+ std::lock_guard<std::mutex> ist_lock(pending_subscription_mutex_);
+ if (is_available(_service, _instance, _major)) {
+ stub_->send_subscribe(find_local(_service, _instance),
+ _client, _service, _instance, _eventgroup, _major, false);
+ }
}
}
+ std::lock_guard<std::mutex> ist_lock(pending_subscription_mutex_);
+ eventgroup_data_t subscription = { _service, _instance, _eventgroup, _major,
+ _subscription_type};
+ pending_subscriptions_.insert(subscription);
} else {
VSOMEIP_ERROR<< "SOME/IP eventgroups require SD to be enabled!";
}
@@ -431,10 +450,13 @@ void routing_manager_impl::unsubscribe(client_t _client, service_t _service,
if( last_subscriber_removed )
discovery_->unsubscribe(_service, _instance, _eventgroup, subscriber);
} else {
- stub_->send_unsubscribe(routing_manager_base::find_local(_service, _instance),
+ stub_->send_unsubscribe(find_local(_service, _instance),
_client, _service, _instance, _eventgroup, false);
}
clear_multicast_endpoints(_service, _instance);
+
+ std::lock_guard<std::mutex> ist_lock(pending_subscription_mutex_);
+ remove_pending_subscription(_service, _instance);
} else {
VSOMEIP_ERROR<< "SOME/IP eventgroups require SD to be enabled!";
}
@@ -449,7 +471,6 @@ bool routing_manager_impl::send(client_t _client, const byte_t *_data,
length_t _size, instance_t _instance,
bool _flush, bool _reliable) {
bool is_sent(false);
-
std::shared_ptr<endpoint> its_target;
bool is_request = utility::is_request(_data[VSOMEIP_MESSAGE_TYPE_POS]);
bool is_notification = utility::is_notification(_data[VSOMEIP_MESSAGE_TYPE_POS]);
@@ -466,12 +487,20 @@ bool routing_manager_impl::send(client_t _client, const byte_t *_data,
if (_size > VSOMEIP_MESSAGE_TYPE_POS) {
if (is_request) {
- its_target = routing_manager_base::find_local(its_service, _instance);
+ its_target = find_local(its_service, _instance);
} else if (!is_notification) {
its_target = find_local(its_client);
- } else if (is_notification && _client) {
- // Selective notifications!
+ } else if (is_notification && _client) { // Selective notifications!
if (_client == get_client()) {
+#ifdef USE_DLT
+ uint16_t its_data_size
+ = uint16_t(_size > USHRT_MAX ? USHRT_MAX : _size);
+
+ tc::trace_header its_header;
+ if (its_header.prepare(its_target, true))
+ tc_->trace(its_header.data_, VSOMEIP_TRACE_HEADER_SIZE,
+ _data, its_data_size);
+#endif
deliver_message(_data, _size, _instance, _reliable);
return true;
}
@@ -479,7 +508,16 @@ bool routing_manager_impl::send(client_t _client, const byte_t *_data,
}
if (its_target) {
- is_sent = send_local(its_target, _client, _data, _size, _instance, _flush, _reliable, VSOMEIP_SEND);
+#ifdef USE_DLT
+ uint16_t its_data_size
+ = uint16_t(_size > USHRT_MAX ? USHRT_MAX : _size);
+
+ tc::trace_header its_header;
+ if (its_header.prepare(its_target, true))
+ 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);
} else {
// Check whether hosting application should get the message
// If not, check routes to external
@@ -543,9 +581,9 @@ bool routing_manager_impl::send(client_t _client, const byte_t *_data,
// 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);
+ 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);
+ its_unreliable_target->send_to(its_remote.endpoint_, _data, _size, _flush);
}
#ifdef USE_DLT
has_sent = true;
@@ -554,7 +592,7 @@ bool routing_manager_impl::send(client_t _client, const byte_t *_data,
// 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);
+ its_unreliable_target->send_to(its_multicast_target.endpoint_, _data, _size, _flush);
#ifdef USE_DLT
has_sent = true;
#endif
@@ -612,12 +650,12 @@ bool routing_manager_impl::send(client_t _client, const byte_t *_data,
bool routing_manager_impl::send_to(
const std::shared_ptr<endpoint_definition> &_target,
- std::shared_ptr<message> _message) {
+ std::shared_ptr<message> _message, bool _flush) {
bool is_sent(false);
std::lock_guard<std::mutex> its_lock(serialize_mutex_);
if (serializer_->serialize(_message.get())) {
is_sent = send_to(_target,
- serializer_->get_data(), serializer_->get_size());
+ serializer_->get_data(), serializer_->get_size(), _flush);
serializer_->reset();
} else {
VSOMEIP_ERROR<< "routing_manager_impl::send_to: serialization failed.";
@@ -627,7 +665,7 @@ 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) {
+ const byte_t *_data, uint32_t _size, bool _flush) {
std::shared_ptr<endpoint> its_endpoint = find_server_endpoint(
_target->get_remote_port(), _target->is_reliable());
@@ -641,7 +679,7 @@ bool routing_manager_impl::send_to(
tc_->trace(its_header.data_, VSOMEIP_TRACE_HEADER_SIZE,
_data, its_data_size);
#endif
- return its_endpoint->send_to(_target, _data, _size);
+ return its_endpoint->send_to(_target, _data, _size, _flush);
}
return false;
}
@@ -687,10 +725,10 @@ void routing_manager_impl::unregister_shadow_event(client_t _client,
void routing_manager_impl::notify(
service_t _service, instance_t _instance, event_t _event,
- std::shared_ptr<payload> _payload, bool _force) {
+ std::shared_ptr<payload> _payload, bool _force, bool _flush) {
std::shared_ptr<event> its_event = find_event(_service, _instance, _event);
if (its_event) {
- its_event->set_payload(_payload, _force);
+ its_event->set_payload(_payload, _force, _flush);
} else {
VSOMEIP_WARNING << "Attempt to update the undefined event/field ["
<< std::hex << _service << "." << _instance << "." << _event
@@ -700,10 +738,10 @@ void routing_manager_impl::notify(
void routing_manager_impl::notify_one(service_t _service, instance_t _instance,
event_t _event, std::shared_ptr<payload> _payload, client_t _client,
- bool _force) {
+ bool _force, bool _flush) {
if (find_local(_client)) {
routing_manager_base::notify_one(_service, _instance, _event, _payload,
- _client, _force);
+ _client, _force, _flush);
} else {
std::shared_ptr<event> its_event = find_event(_service, _instance, _event);
if (its_event) {
@@ -730,7 +768,7 @@ void routing_manager_impl::notify_one(service_t _service, instance_t _instance,
auto its_subscriber = its_instance->second.find(_client);
if (its_subscriber != its_instance->second.end()) {
for (auto its_target : its_subscriber->second) {
- its_event->set_payload(_payload, its_target, _force);
+ its_event->set_payload(_payload, its_target, _force, _flush);
}
}
}
@@ -756,11 +794,13 @@ void routing_manager_impl::on_error(const byte_t *_data, length_t _length, endpo
}
void routing_manager_impl::release_port(uint16_t _port, bool _reliable) {
+ std::lock_guard<std::mutex> its_lock(used_client_ports_mutex_);
used_client_ports_[_reliable].erase(_port);
}
void routing_manager_impl::on_message(const byte_t *_data, length_t _size,
- endpoint *_receiver, const boost::asio::ip::address &_destination) {
+ endpoint *_receiver, const boost::asio::ip::address &_destination,
+ client_t _bound_client) {
#if 0
std::stringstream msg;
msg << "rmi::on_message: ";
@@ -768,6 +808,7 @@ void routing_manager_impl::on_message(const byte_t *_data, length_t _size,
msg << std::hex << std::setw(2) << std::setfill('0') << (int)_data[i] << " ";
VSOMEIP_DEBUG << msg.str();
#endif
+ (void)_bound_client;
service_t its_service;
method_t its_method;
if (_size >= VSOMEIP_SOMEIP_HEADER_SIZE) {
@@ -810,6 +851,34 @@ void routing_manager_impl::on_message(const byte_t *_data, length_t _size,
return;
}
+ // Security checks if enabled!
+ if (configuration_->is_security_enabled()) {
+ if (utility::is_request(_data[VSOMEIP_MESSAGE_TYPE_POS])) {
+ client_t requester = VSOMEIP_BYTES_TO_WORD(
+ _data[VSOMEIP_CLIENT_POS_MIN],
+ _data[VSOMEIP_CLIENT_POS_MAX]);
+ if (!configuration_->is_offered_remote(its_service, its_instance)) {
+ VSOMEIP_WARNING << std::hex << "Security: Received a remote request "
+ << "for service/instance " << its_service << "/" << its_instance
+ << " which isn't offered remote ~> Skip message!";
+ return;
+ }
+ if (find_local(requester)) {
+ VSOMEIP_WARNING << std::hex << "Security: Received a remote request "
+ << "from client identifier 0x" << requester
+ << " which is already used locally ~> Skip message!";
+ return;
+ }
+ if (!configuration_->is_client_allowed(requester, its_service, its_instance)) {
+ VSOMEIP_WARNING << std::hex << "Security: Received a remote request "
+ << "from client 0x" << requester << " for service/instance "
+ << its_service << "/" << its_instance
+ << " which violates the security policy ~> Skip message!";
+ return;
+ }
+ }
+ }
+
if (!deliver_specific_endpoint_message(
its_service, its_instance, _data, _size, _receiver)) {
// set client ID to zero for all messages
@@ -883,11 +952,11 @@ void routing_manager_impl::on_notification(client_t _client,
its_length);
if (_notify_one) {
- notify_one(_service, _instance, its_event->get_event(), its_payload, _client, true);
+ notify_one(_service, _instance, its_event->get_event(), its_payload, _client, true, true);
} else {
if (its_event->is_field()) {
if (its_event->is_set()) {
- its_event->set_payload(its_payload);
+ its_event->set_payload(its_payload, false, true);
} else {
// Set payload first time ~> notify all remote subscriber per unicast (inital field)
for (auto its_group : its_event->get_eventgroups()) {
@@ -895,13 +964,13 @@ void routing_manager_impl::on_notification(client_t _client,
if (its_eventgroup) {
//Unicast targets
for (auto its_remote : its_eventgroup->get_targets()) {
- its_event->set_payload(its_payload, its_remote.endpoint_, true);
+ its_event->set_payload(its_payload, its_remote.endpoint_, true, true);
}
}
}
}
} else {
- its_event->set_payload(its_payload);
+ its_event->set_payload(its_payload, false, true);
}
}
@@ -1089,11 +1158,10 @@ void routing_manager_impl::on_stop_offer_service(client_t _client, service_t _se
// Trigger "del_routing_info" either over SD or static
if (discovery_) {
- auto its_info = find_service(_service, _instance);
if (its_info) {
if (its_info->get_major() == _major && its_info->get_minor() == _minor) {
its_info->set_ttl(0);
- discovery_->on_offer_change();
+ discovery_->stop_offer_service(_service, _instance, its_info);
}
}
} else {
@@ -1158,8 +1226,13 @@ 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) {
bool is_delivered(false);
- deserializer_->set_data(_data, _size);
- std::shared_ptr<message> its_message(deserializer_->deserialize_message());
+
+ auto a_deserializer = get_deserializer();
+ a_deserializer->set_data(_data, _size);
+ std::shared_ptr<message> its_message(a_deserializer->deserialize_message());
+ a_deserializer->reset();
+ put_deserializer(a_deserializer);
+
if (its_message) {
its_message->set_instance(_instance);
its_message->set_reliable(_reliable);
@@ -1223,7 +1296,7 @@ std::shared_ptr<eventgroupinfo> routing_manager_impl::find_eventgroup(
return routing_manager_base::find_eventgroup(_service, _instance, _eventgroup);
}
-std::shared_ptr<configuration> routing_manager_impl::get_configuration() const {
+const std::shared_ptr<configuration> routing_manager_impl::get_configuration() const {
return (host_->get_configuration());
}
@@ -1278,6 +1351,14 @@ std::shared_ptr<endpoint> routing_manager_impl::find_or_create_remote_client(
void routing_manager_impl::init_service_info(
service_t _service, instance_t _instance, bool _is_local_service) {
std::shared_ptr<serviceinfo> its_info = find_service(_service, _instance);
+ if (!its_info) {
+ VSOMEIP_ERROR << "routing_manager_impl::init_service_info: couldn't "
+ "find serviceinfo for service: ["
+ << std::hex << std::setw(4) << std::setfill('0') << _service << "."
+ << std::hex << std::setw(4) << std::setfill('0') << _instance << "]"
+ << " is_local_service=" << _is_local_service;
+ return;
+ }
if (configuration_) {
std::shared_ptr<endpoint> its_reliable_endpoint;
std::shared_ptr<endpoint> its_unreliable_endpoint;
@@ -1392,11 +1473,13 @@ std::shared_ptr<endpoint> routing_manager_impl::create_server_endpoint(
its_endpoint->enable_magic_cookies();
}
} else {
+#ifndef WIN32
if (its_unicast.is_v4()) {
its_unicast = boost::asio::ip::address_v4::any();
} else if (its_unicast.is_v6()) {
its_unicast = boost::asio::ip::address_v6::any();
}
+#endif
boost::asio::ip::udp::endpoint ep(its_unicast, _port);
its_endpoint = std::make_shared<udp_server_endpoint_impl>(
shared_from_this(),
@@ -1445,15 +1528,6 @@ std::shared_ptr<endpoint> routing_manager_impl::find_or_create_server_endpoint(
return (its_endpoint);
}
-std::shared_ptr<endpoint> routing_manager_impl::find_local(client_t _client) {
- return routing_manager_base::find_local(_client);
-}
-
-std::shared_ptr<endpoint> routing_manager_impl::find_or_create_local(
- client_t _client) {
- return routing_manager_base::find_or_create_local(_client);
-}
-
void routing_manager_impl::remove_local(client_t _client) {
routing_manager_base::remove_local(_client);
std::forward_list<std::pair<service_t, instance_t>> services_to_release_;
@@ -1922,7 +1996,7 @@ std::chrono::milliseconds routing_manager_impl::update_routing_info(std::chrono:
for (auto &s : get_services()) {
for (auto &i : s.second) {
- if (routing_manager_base::find_local_client(s.first, i.first) != VSOMEIP_ROUTING_CLIENT) {
+ if (find_local_client(s.first, i.first) != VSOMEIP_ROUTING_CLIENT) {
continue; //don't expire local services
}
ttl_t its_ttl = i.second->get_ttl();
@@ -1964,7 +2038,7 @@ void routing_manager_impl::expire_services(const boost::asio::ip::address &_addr
for (auto &s : get_services()) {
for (auto &i : s.second) {
- if (routing_manager_base::find_local_client(s.first, i.first) != VSOMEIP_ROUTING_CLIENT) {
+ if (find_local_client(s.first, i.first) != VSOMEIP_ROUTING_CLIENT) {
continue; //don't expire local services
}
bool is_gone(false);
@@ -2016,7 +2090,7 @@ void routing_manager_impl::expire_subscriptions(const boost::asio::ip::address &
for (auto &its_endpoint : its_invalid_endpoints) {
its_eventgroup.second->remove_target(its_endpoint);
- auto target = routing_manager_base::find_local(its_service.first, its_instance.first);
+ auto target = find_local(its_service.first, its_instance.first);
if (target) {
stub_->send_unsubscribe(target, VSOMEIP_ROUTING_CLIENT, its_service.first,
its_instance.first, its_eventgroup.first, true);
@@ -2114,8 +2188,6 @@ bool routing_manager_impl::on_subscribe_accepted(service_t _service, instance_t
<< " from unknown client.";
}
- stub_->send_subscribe(routing_manager_base::find_local(_service, _instance),
- client, _service, _instance, _eventgroup, its_eventgroup->get_major(), true);
{
std::lock_guard<std::mutex> its_lock(remote_subscribers_mutex_);
remote_subscribers_[_service][_instance][client].insert(_target);
@@ -2156,10 +2228,30 @@ void routing_manager_impl::on_subscribe(
}
if (target_added) { // unicast or multicast
+ client_t client = VSOMEIP_ROUTING_CLIENT;
+ if (!_subscriber->is_reliable()) {
+ if (!its_eventgroup->is_multicast()) {
+ uint16_t unreliable_port = configuration_->get_unreliable_port(_service, _instance);
+ auto endpoint = find_server_endpoint(unreliable_port, false);
+ if (endpoint) {
+ client = std::dynamic_pointer_cast<udp_server_endpoint_impl>(endpoint)->
+ get_client(_subscriber);
+ }
+ }
+ } else {
+ uint16_t reliable_port = configuration_->get_reliable_port(_service, _instance);
+ auto endpoint = find_server_endpoint(reliable_port, true);
+ if (endpoint) {
+ client = std::dynamic_pointer_cast<tcp_server_endpoint_impl>(endpoint)->
+ get_client(_subscriber);
+ }
+ }
+ stub_->send_subscribe(find_local(_service, _instance),
+ client, _service, _instance, _eventgroup, its_eventgroup->get_major(), true);
// send initial events if we already have a cached field (is_set)
for (auto its_event : its_eventgroup->get_events()) {
if (its_event->is_field() && its_event->is_set()) {
- its_event->notify_one(_subscriber); // unicast
+ its_event->notify_one(_subscriber, true); // TODO: use _flush parameter to send all event at once
}
}
}
@@ -2188,7 +2280,7 @@ void routing_manager_impl::on_unsubscribe(service_t _service,
its_eventgroup->remove_target(_target);
clear_remote_subscriber(_service, _instance, its_client, _target);
- stub_->send_unsubscribe(routing_manager_base::find_local(_service, _instance),
+ stub_->send_unsubscribe(find_local(_service, _instance),
its_client, _service, _instance, _eventgroup, true);
host_->on_subscription(_service, _instance, _eventgroup, its_client, false);
@@ -2565,22 +2657,38 @@ void routing_manager_impl::send_error(return_code_e _return_code,
if(!endpoint) {
return;
}
- auto remote = endpoint->get_remote();
- adr = remote.address();
- port = remote.port();
+ if (!endpoint->get_remote_address(adr)) {
+ VSOMEIP_ERROR << "routing_manager_impl::send_error: "
+ "couldn't determine remote address (reliable)";
+ return;
+ }
+ port = endpoint->get_remote_port();
+ if (!port) {
+ VSOMEIP_ERROR << "routing_manager_impl::send_error: "
+ "couldn't determine remote port (reliable)";
+ return;
+ }
} else {
auto endpoint = dynamic_cast<udp_server_endpoint_impl*>(_receiver);
if (!endpoint) {
return;
}
- auto remote = endpoint->get_remote();
- adr = remote.address();
- port = remote.port();
+ if (!endpoint->get_remote_address(adr)) {
+ VSOMEIP_ERROR << "routing_manager_impl::send_error: "
+ "couldn't determine remote address (unreliable)";
+ return;
+ }
+ port = endpoint->get_remote_port();
+ if (!port) {
+ VSOMEIP_ERROR << "routing_manager_impl::send_error: "
+ "couldn't determine remote port (unreliable)";
+ return;
+ }
}
auto its_endpoint_def =
std::make_shared<endpoint_definition>(adr, port, _receiver->is_reliable());
its_endpoint_def->set_remote_port(_receiver->get_local_port());
- send_to(its_endpoint_def, serializer_->get_data(), serializer_->get_size());
+ send_to(its_endpoint_def, serializer_->get_data(), serializer_->get_size(), true);
}
serializer_->reset();
} else {
@@ -2770,7 +2878,7 @@ routing_manager_impl::expire_subscriptions() {
clear_remote_subscriber(its_service.first, its_instance.first,
its_client, its_endpoint);
- auto target = routing_manager_base::find_local(its_service.first, its_instance.first);
+ auto target = find_local(its_service.first, its_instance.first);
if (target) {
stub_->send_unsubscribe(target, VSOMEIP_ROUTING_CLIENT, its_service.first,
its_instance.first, its_eventgroup.first, true);
@@ -2855,7 +2963,6 @@ void routing_manager_impl::clear_remote_service_info(service_t _service, instanc
bool routing_manager_impl::handle_local_offer_service(client_t _client, service_t _service,
instance_t _instance, major_version_t _major,minor_version_t _minor) {
- bool previously_offered(false);
{
std::lock_guard<std::mutex> its_lock(local_services_mutex_);
auto found_service = local_services_.find(_service);
@@ -2875,7 +2982,7 @@ bool routing_manager_impl::handle_local_offer_service(client_t _client, service_
<< std::hex << std::setfill('0') << std::setw(4) << _instance << "."
<< std::dec << static_cast<std::uint32_t>(_major) << "."
<< _minor << "] offered previously by itself.";
- previously_offered = true;
+ return false;
} else if ( its_stored_major == _major
&& its_stored_minor == _minor
&& its_stored_client != _client) {
@@ -2975,7 +3082,7 @@ bool routing_manager_impl::handle_local_offer_service(client_t _client, service_
// check if the same service instance is already offered remotely
if (routing_manager_base::offer_service(_client, _service, _instance,
- _major, _minor) || previously_offered) {
+ _major, _minor)) {
local_services_[_service][_instance] = std::make_tuple(_major,
_minor, _client);
} else {
@@ -3199,4 +3306,76 @@ void routing_manager_impl::remove_identifying_client(service_t _service, instanc
}
}
}
+
+void routing_manager_impl::send_subscribe(client_t _client, service_t _service,
+ instance_t _instance, eventgroup_t _eventgroup, major_version_t _major,
+ subscription_type_e _subscription_type) {
+ (void)_subscription_type;
+ auto endpoint = find_local(_service, _instance);
+ if (endpoint) {
+ stub_->send_subscribe(endpoint, _client,
+ _service, _instance, _eventgroup, _major, false);
+ }
+}
+
+void routing_manager_impl::set_routing_state(routing_state_e _routing_state) {
+ if(discovery_) {
+ switch (_routing_state) {
+ case vsomeip::routing_state_e::RS_SUSPENDED:
+ {
+ // stop cycling offers for services and 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) {
+ its_instance.second->set_ttl(0);
+ discovery_->stop_offer_service(its_service.first, its_instance.first, its_instance.second);
+ }
+ }
+
+ // determine existing subscriptions to remote services and send StopSubscribe
+ for (auto &s : get_services()) {
+ for (auto &i : s.second) {
+ if (find_local_client(s.first, i.first) != VSOMEIP_ROUTING_CLIENT) {
+ continue; //don't expire local services
+ }
+ std::lock_guard<std::mutex> its_lock(eventgroup_clients_mutex_);
+
+ auto found_service = eventgroup_clients_.find(s.first);
+ if (found_service != eventgroup_clients_.end()) {
+ auto found_instance = found_service->second.find(i.first);
+ if (found_instance != found_service->second.end()) {
+ for (auto its_eventgroup : found_instance->second) {
+ discovery_->unsubscribe(s.first, i.first, its_eventgroup.first, 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.first, its_client);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ break;
+ }
+ case vsomeip::routing_state_e::RS_RESUMED:
+ {
+ discovery_->start();
+ break;
+ }
+ default:
+ break;
+ }
+ }
+}
+
+
} // namespace vsomeip
diff --git a/implementation/routing/src/routing_manager_proxy.cpp b/implementation/routing/src/routing_manager_proxy.cpp
index 9491544..b762a17 100644
--- a/implementation/routing/src/routing_manager_proxy.cpp
+++ b/implementation/routing/src/routing_manager_proxy.cpp
@@ -42,7 +42,8 @@ routing_manager_proxy::routing_manager_proxy(routing_manager_host *_host) :
state_(inner_state_type_e::ST_DEREGISTERED),
sender_(0),
receiver_(0),
- register_application_timer_(io_)
+ register_application_timer_(io_),
+ logger_(logger::get())
{
}
@@ -142,6 +143,10 @@ void routing_manager_proxy::stop() {
#endif
}
+const std::shared_ptr<configuration> routing_manager_proxy::get_configuration() const {
+ return host_->get_configuration();
+}
+
bool routing_manager_proxy::offer_service(client_t _client, service_t _service,
instance_t _instance, major_version_t _major, minor_version_t _minor) {
if(!routing_manager_base::offer_service(_client, _service, _instance, _major, _minor)) {
@@ -292,24 +297,21 @@ void routing_manager_proxy::register_event(client_t _client,
_epsilon_change_func,
_is_provided);
- if (!_is_provided ||
- configuration_->is_offered_remote(_service, _instance)) {
- {
- std::lock_guard<std::mutex> its_lock(state_mutex_);
- if (state_ == inner_state_type_e::ST_REGISTERED) {
- send_register_event(client_, _service, _instance,
- _event, _eventgroups, _is_field, _is_provided);
- }
- event_data_t registration = {
- _service,
- _instance,
- _event,
- _is_field,
- _is_provided,
- _eventgroups
- };
- pending_event_registrations_.insert(registration);
+ {
+ std::lock_guard<std::mutex> its_lock(state_mutex_);
+ if (state_ == inner_state_type_e::ST_REGISTERED) {
+ send_register_event(client_, _service, _instance,
+ _event, _eventgroups, _is_field, _is_provided);
}
+ event_data_t registration = {
+ _service,
+ _instance,
+ _event,
+ _is_field,
+ _is_provided,
+ _eventgroups
+ };
+ pending_event_registrations_.insert(registration);
}
}
@@ -320,48 +322,45 @@ void routing_manager_proxy::unregister_event(client_t _client,
routing_manager_base::unregister_event(_client, _service, _instance,
_event, _is_provided);
- if (!_is_provided ||
- configuration_->is_offered_remote(_service, _instance)) {
- {
- std::lock_guard<std::mutex> its_lock(state_mutex_);
- if (state_ == inner_state_type_e::ST_REGISTERED) {
- byte_t its_command[VSOMEIP_UNREGISTER_EVENT_COMMAND_SIZE];
- uint32_t its_size = VSOMEIP_UNREGISTER_EVENT_COMMAND_SIZE
- - VSOMEIP_COMMAND_HEADER_SIZE;
+ {
+ std::lock_guard<std::mutex> its_lock(state_mutex_);
+ if (state_ == inner_state_type_e::ST_REGISTERED) {
+ byte_t its_command[VSOMEIP_UNREGISTER_EVENT_COMMAND_SIZE];
+ uint32_t its_size = VSOMEIP_UNREGISTER_EVENT_COMMAND_SIZE
+ - VSOMEIP_COMMAND_HEADER_SIZE;
- its_command[VSOMEIP_COMMAND_TYPE_POS] = VSOMEIP_UNREGISTER_EVENT;
- std::memcpy(&its_command[VSOMEIP_COMMAND_CLIENT_POS], &client_,
- sizeof(client_));
- std::memcpy(&its_command[VSOMEIP_COMMAND_SIZE_POS_MIN], &its_size,
- sizeof(its_size));
- std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS], &_service,
- sizeof(_service));
- std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 2], &_instance,
- sizeof(_instance));
- std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 4], &_event,
- sizeof(_event));
- its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 6]
- = static_cast<byte_t>(_is_provided);
+ its_command[VSOMEIP_COMMAND_TYPE_POS] = VSOMEIP_UNREGISTER_EVENT;
+ std::memcpy(&its_command[VSOMEIP_COMMAND_CLIENT_POS], &client_,
+ sizeof(client_));
+ std::memcpy(&its_command[VSOMEIP_COMMAND_SIZE_POS_MIN], &its_size,
+ sizeof(its_size));
+ std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS], &_service,
+ sizeof(_service));
+ std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 2], &_instance,
+ sizeof(_instance));
+ std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 4], &_event,
+ sizeof(_event));
+ its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 6]
+ = static_cast<byte_t>(_is_provided);
- {
- std::lock_guard<std::recursive_mutex> its_lock(sender_mutex_);
- if (sender_) {
- sender_->send(its_command, sizeof(its_command));
- }
+ {
+ std::lock_guard<std::recursive_mutex> its_lock(sender_mutex_);
+ if (sender_) {
+ sender_->send(its_command, sizeof(its_command));
}
}
- auto it = pending_event_registrations_.begin();
- while (it != pending_event_registrations_.end()) {
- if (it->service_ == _service
- && it->instance_ == _instance
- && it->event_ == _event) {
- break;
- }
- it++;
+ }
+ auto it = pending_event_registrations_.begin();
+ while (it != pending_event_registrations_.end()) {
+ if (it->service_ == _service
+ && it->instance_ == _instance
+ && it->event_ == _event) {
+ break;
}
- if (it != pending_event_registrations_.end())
- pending_event_registrations_.erase(it);
+ it++;
}
+ if (it != pending_event_registrations_.end())
+ pending_event_registrations_.erase(it);
}
}
@@ -529,15 +528,7 @@ void routing_manager_proxy::unsubscribe(client_t _client, service_t _service,
};
}
}
- auto it = pending_subscriptions_.begin();
- while (it != pending_subscriptions_.end()) {
- if (it->service_ == _service
- && it->instance_ == _instance) {
- break;
- }
- it++;
- }
- if (it != pending_subscriptions_.end()) pending_subscriptions_.erase(it);
+ remove_pending_subscription(_service, _instance);
}
}
@@ -545,6 +536,7 @@ bool routing_manager_proxy::send(client_t _client, const byte_t *_data,
length_t _size, instance_t _instance,
bool _flush,
bool _reliable) {
+ (void)_client;
bool is_sent(false);
bool has_remote_subscribers(false);
if (_size > VSOMEIP_MESSAGE_TYPE_POS) {
@@ -554,10 +546,9 @@ bool routing_manager_proxy::send(client_t _client, const byte_t *_data,
service_t its_service = VSOMEIP_BYTES_TO_WORD(
_data[VSOMEIP_SERVICE_POS_MIN],
_data[VSOMEIP_SERVICE_POS_MAX]);
- std::lock_guard<std::mutex> its_lock(send_mutex_);
client_t its_client = find_local_client(its_service, _instance);
if (its_client != VSOMEIP_ROUTING_CLIENT) {
- if (known_clients_.find(its_client) != known_clients_.end()) {
+ if (is_client_known(its_client)) {
its_target = find_or_create_local(its_client);
}
}
@@ -566,9 +557,8 @@ bool routing_manager_proxy::send(client_t _client, const byte_t *_data,
client_t its_client = VSOMEIP_BYTES_TO_WORD(
_data[VSOMEIP_CLIENT_POS_MIN],
_data[VSOMEIP_CLIENT_POS_MAX]);
- std::lock_guard<std::mutex> its_lock(send_mutex_);
if (its_client != VSOMEIP_ROUTING_CLIENT) {
- if (known_clients_.find(its_client) != known_clients_.end()) {
+ if (is_client_known(its_client)) {
its_target = find_or_create_local(its_client);
}
}
@@ -582,6 +572,15 @@ bool routing_manager_proxy::send(client_t _client, const byte_t *_data,
// notify_one
its_target = find_local(_client);
if (its_target) {
+#ifdef USE_DLT
+ uint16_t its_data_size
+ = uint16_t(_size > USHRT_MAX ? USHRT_MAX : _size);
+
+ tc::trace_header its_header;
+ if (its_header.prepare(its_target, true))
+ 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);
}
@@ -600,17 +599,13 @@ bool routing_manager_proxy::send(client_t _client, const byte_t *_data,
uint8_t command = VSOMEIP_SEND;
if (utility::is_notification(_data[VSOMEIP_MESSAGE_TYPE_POS])) {
- if (_client) {
+ if (_client != VSOMEIP_ROUTING_CLIENT) {
command = VSOMEIP_NOTIFY_ONE;
} else {
command = VSOMEIP_NOTIFY;
// Do we need to deliver a notification to the routing manager?
- // Only for services offered remote which already have remote clients subscribed to
- service_t its_service = VSOMEIP_BYTES_TO_WORD(
- _data[VSOMEIP_SERVICE_POS_MIN],
- _data[VSOMEIP_SERVICE_POS_MAX]);
- send = configuration_->is_offered_remote(its_service, _instance)
- && has_remote_subscribers;
+ // Only for services which already have remote clients subscribed to
+ send = has_remote_subscribers;
}
}
#ifdef USE_DLT
@@ -625,8 +620,9 @@ bool routing_manager_proxy::send(client_t _client, const byte_t *_data,
}
#endif
if (send) {
- is_sent = send_local(its_target, _client, _data, _size,
- _instance, _flush, _reliable, command);
+ is_sent = send_local(its_target,
+ (command == VSOMEIP_NOTIFY_ONE ? _client : get_client()),
+ _data, _size, _instance, _flush, _reliable, command);
}
}
return (is_sent);
@@ -634,28 +630,32 @@ bool routing_manager_proxy::send(client_t _client, const byte_t *_data,
bool routing_manager_proxy::send_to(
const std::shared_ptr<endpoint_definition> &_target,
- std::shared_ptr<message> _message) {
+ std::shared_ptr<message> _message,
+ bool _flush) {
(void)_target;
(void)_message;
+ (void)_flush;
return (false);
}
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,
+ bool _flush) {
(void)_target;
(void)_data;
(void)_size;
+ (void)_flush;
return (false);
}
void routing_manager_proxy::notify(
service_t _service, instance_t _instance, event_t _event,
- std::shared_ptr<payload> _payload, bool _force) {
+ std::shared_ptr<payload> _payload, bool _force, bool _flush) {
{
std::lock_guard<std::mutex> its_lock(state_mutex_);
if (state_ == inner_state_type_e::ST_REGISTERED) {
- routing_manager_base::notify(_service, _instance, _event, _payload, _force);
+ routing_manager_base::notify(_service, _instance, _event, _payload, _force, _flush);
}
if (is_field(_service, _instance, _event)){
@@ -710,7 +710,8 @@ void routing_manager_proxy::release_port(uint16_t _port, bool _reliable) {
}
void routing_manager_proxy::on_message(const byte_t *_data, length_t _size,
- endpoint *_receiver, const boost::asio::ip::address &_destination) {
+ endpoint *_receiver, const boost::asio::ip::address &_destination,
+ client_t _bound_client) {
(void)_receiver;
(void)_destination;
#if 0
@@ -728,6 +729,7 @@ void routing_manager_proxy::on_message(const byte_t *_data, length_t _size,
eventgroup_t its_eventgroup;
major_version_t its_major;
bool is_remote_subscriber;
+ client_t routing_host_id = configuration_->get_id(configuration_->get_routing_host());
if (_size > VSOMEIP_COMMAND_SIZE_POS_MAX) {
its_command = _data[VSOMEIP_COMMAND_TYPE_POS];
@@ -736,6 +738,17 @@ void routing_manager_proxy::on_message(const byte_t *_data, length_t _size,
std::memcpy(&its_length, &_data[VSOMEIP_COMMAND_SIZE_POS_MIN],
sizeof(its_length));
+ if (configuration_->is_security_enabled() && _bound_client != routing_host_id &&
+ _bound_client != its_client) {
+ VSOMEIP_WARNING << std::hex << "Client " << std::setw(4) << std::setfill('0') << get_client()
+ << " received a message with command " << (uint32_t)its_command
+ << " from " << std::setw(4) << std::setfill('0')
+ << its_client << " which doesn't match the bound client "
+ << std::setw(4) << std::setfill('0') << _bound_client
+ << " ~> skip message!";
+ return;
+ }
+
switch (its_command) {
case VSOMEIP_SEND: {
instance_t its_instance;
@@ -745,27 +758,64 @@ void routing_manager_proxy::on_message(const byte_t *_data, length_t _size,
bool its_reliable;
std::memcpy(&its_reliable, &_data[_size - sizeof(bool)],
sizeof(its_reliable));
- deserializer_->set_data(&_data[VSOMEIP_COMMAND_PAYLOAD_POS],
+
+ auto a_deserializer = get_deserializer();
+ a_deserializer->set_data(&_data[VSOMEIP_COMMAND_PAYLOAD_POS],
its_length);
- std::shared_ptr<message> its_message(
- deserializer_->deserialize_message());
+ std::shared_ptr<message> its_message(a_deserializer->deserialize_message());
+ a_deserializer->reset();
+ put_deserializer(a_deserializer);
+
if (its_message) {
its_message->set_instance(its_instance);
its_message->set_reliable(its_reliable);
- if(its_message->get_message_type() == message_type_e::MT_NOTIFICATION) {
+ if (utility::is_notification(its_message->get_message_type())) {
+ if (!configuration_->is_client_allowed(get_client(), its_message->get_service(),
+ its_message->get_instance())) {
+ VSOMEIP_WARNING << std::hex << "Security: Client 0x" << get_client()
+ << " isn't allow receive a notification from to service/instance "
+ << its_message->get_service() << "/" << its_message->get_instance()
+ << " respectively from client 0x" << its_client
+ << " : Skip message!";
+ return;
+ }
cache_event_payload(its_message);
+ } else if (utility::is_request(its_message->get_message_type())) {
+ if (!configuration_->is_client_allowed(its_message->get_client(),
+ its_message->get_service(), its_message->get_instance())) {
+ VSOMEIP_WARNING << std::hex << "Security: Client 0x" << its_message->get_client()
+ << " isn't allow to send a request to service/instance "
+ << its_message->get_service() << "/" << its_message->get_instance()
+ << " : Skip message!";
+ return;
+ }
+ } else { // response
+ if (!configuration_->is_client_allowed(get_client(), its_message->get_service(),
+ its_message->get_instance())) {
+ VSOMEIP_WARNING << std::hex << "Security: Client 0x" << get_client()
+ << " isn't allow receive a response from to service/instance "
+ << its_message->get_service() << "/" << its_message->get_instance()
+ << " respectively from client 0x" << its_client
+ << " : Skip message!";
+ return;
+ }
}
host_->on_message(its_message);
} else {
VSOMEIP_ERROR << "Routing proxy: on_message: "
<< "SomeIP-Header deserialization failed!";
}
- deserializer_->reset();
}
break;
case VSOMEIP_ROUTING_INFO:
- on_routing_info(&_data[VSOMEIP_COMMAND_PAYLOAD_POS], its_length);
+ if (!configuration_->is_security_enabled() ||_bound_client == routing_host_id) {
+ on_routing_info(&_data[VSOMEIP_COMMAND_PAYLOAD_POS], its_length);
+ } else {
+ VSOMEIP_WARNING << std::hex << "Security: Client 0x" << get_client()
+ << " received an routing info from a client which isn't the routing manager"
+ << " : Skip message!";
+ }
break;
case VSOMEIP_PING:
@@ -796,11 +846,20 @@ void routing_manager_proxy::on_message(const byte_t *_data, length_t _size,
notify_remote_initally(its_service, its_instance, its_eventgroup);
}
(void)get_remote_subscriber_count(its_service, its_instance, its_eventgroup, true);
- } else if (known_clients_.find(its_client) != known_clients_.end()) {
+ } 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;
+ }
+
// 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);
- (void) find_or_create_local(its_client);
if (!subscription_accepted) {
send_subscribe_nack(its_client, its_service, its_instance, its_eventgroup);
} else {
@@ -813,8 +872,9 @@ void routing_manager_proxy::on_message(const byte_t *_data, length_t _size,
eventgroup_data_t subscription = { its_service, its_instance,
its_eventgroup, its_major,
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_DEBUG << "SUBSCRIBE("
<< std::hex << std::setw(4) << std::setfill('0') << its_client <<"): ["
<< std::hex << std::setw(4) << std::setfill('0') << its_service << "."
@@ -973,7 +1033,10 @@ void routing_manager_proxy::on_routing_info(const byte_t *_data,
clients_to_delete.insert(client);
}
}
- known_clients_ = known_clients;
+ {
+ std::lock_guard<std::mutex> its_lock(known_clients_mutex_);
+ known_clients_ = known_clients;
+ }
// Check for services that are no longer available
for (const auto &i : old_local_services) {
@@ -1022,51 +1085,82 @@ void routing_manager_proxy::on_routing_info(const byte_t *_data,
VSOMEIP_INFO << std::hex << "Application/Client " << get_client()
<< (its_state == inner_state_type_e::ST_REGISTERED ?
" is registered." : " is deregistered.");
+
+ // inform host about its own registration state changes
+ host_->on_state(static_cast<state_type_e>(its_state));
+
{
std::lock_guard<std::mutex> its_lock(state_mutex_);
if (its_state == inner_state_type_e::ST_REGISTERED) {
boost::system::error_code ec;
register_application_timer_.cancel(ec);
+ send_registered_ack();
send_pending_commands();
}
state_ = its_state;
}
- // inform host about its own registration state changes
- host_->on_state(static_cast<state_type_e>(its_state));
-
// Notify stop() call about clean deregistration
state_condition_.notify_one();
}
// Report services that are no longer available
- for (const struct service_info &sr : services_to_remove) {
+ for (const service_info &sr : services_to_remove) {
on_stop_offer_service(sr.service_id_, sr.instance_id_, sr.major_, sr.minor_);
host_->on_availability(sr.service_id_, sr.instance_id_, false, sr.major_, sr.minor_);
}
// Report services that are newly available
- for (const struct service_info &sa : services_to_add) {
- send_pending_subscriptions(sa.service_id_, sa.instance_id_, sa.major_);
+ for (const service_info &sa : services_to_add) {
+ {
+ std::lock_guard<std::mutex> its_lock(state_mutex_);
+ send_pending_subscriptions(sa.service_id_, sa.instance_id_, sa.major_);
+ }
host_->on_availability(sa.service_id_, sa.instance_id_, true, sa.major_, sa.minor_);
}
- if (pending_ingoing_subscripitons_.size()) {
- for (const client_t client : known_clients_) {
- auto its_client = pending_ingoing_subscripitons_.find(client);
- if (its_client != pending_ingoing_subscripitons_.end()) {
- for (const auto subscription : its_client->second) {
- bool subscription_accepted = host_->on_subscription(subscription.service_, subscription.instance_, subscription.eventgroup_, client, true);
- (void) find_or_create_local(client);
- if (!subscription_accepted) {
- send_subscribe_nack(client, subscription.service_, subscription.instance_, subscription.eventgroup_);
- } else {
- routing_manager_base::subscribe(client, subscription.service_, subscription.instance_, subscription.eventgroup_,
- subscription.major_, subscription_type_e::SU_RELIABLE_AND_UNRELIABLE);
- send_subscribe_ack(client, subscription.service_, subscription.instance_, subscription.eventgroup_);
+ {
+ struct subscription_info {
+ service_t service_id_;
+ instance_t instance_id_;
+ eventgroup_t eventgroup_id_;
+ client_t client_id_;
+ major_version_t major_;
+ };
+ std::lock_guard<std::mutex> its_lock(pending_ingoing_subscripitons_mutex_);
+ std::forward_list<struct subscription_info> subscription_actions;
+ if (pending_ingoing_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()) {
+ for (const auto subscription : its_client->second) {
+ subscription_actions.push_front(
+ { subscription.service_, subscription.instance_,
+ subscription.eventgroup_, client,
+ subscription.major_ });
+ }
}
}
}
- pending_ingoing_subscripitons_.erase(client);
+ for (const subscription_info &si : subscription_actions) {
+ bool subscription_accepted = host_->on_subscription(
+ si.service_id_, si.instance_id_, si.eventgroup_id_,
+ si.client_id_, true);
+ (void) find_or_create_local(si.client_id_);
+ if (!subscription_accepted) {
+ send_subscribe_nack(si.client_id_, si.service_id_,
+ si.instance_id_, si.eventgroup_id_);
+ } else {
+ routing_manager_base::subscribe(si.client_id_,
+ si.service_id_, si.instance_id_, si.eventgroup_id_,
+ si.major_,
+ subscription_type_e::SU_RELIABLE_AND_UNRELIABLE);
+ send_subscribe_ack(si.client_id_, si.service_id_,
+ si.instance_id_, si.eventgroup_id_);
+ }
+ pending_ingoing_subscripitons_.erase(si.client_id_);
+ }
}
}
@@ -1100,10 +1194,10 @@ void routing_manager_proxy::register_application() {
sizeof(uint32_t));
if (is_connected_) {
+ std::lock_guard<std::mutex> its_state_lock(state_mutex_);
std::lock_guard<std::recursive_mutex> its_lock(sender_mutex_);
if (sender_) {
{
- std::lock_guard<std::mutex> its_state_lock(state_mutex_);
state_ = inner_state_type_e::ST_REGISTERING;
}
sender_->send(its_command, sizeof(its_command));
@@ -1322,18 +1416,6 @@ void routing_manager_proxy::cache_event_payload(
}
-void routing_manager_proxy::send_pending_subscriptions(service_t _service,
- instance_t _instance, major_version_t _major) {
- std::lock_guard<std::mutex> its_lock(state_mutex_);
- for (auto &ps : pending_subscriptions_) {
- if (ps.service_ == _service &&
- ps.instance_ == _instance && ps.major_ == _major) {
- send_subscribe(client_, ps.service_, ps.instance_,
- ps.eventgroup_, ps.major_, ps.subscription_type_);
- }
- }
-}
-
void routing_manager_proxy::on_stop_offer_service(service_t _service,
instance_t _instance,
major_version_t _major,
@@ -1367,7 +1449,7 @@ void routing_manager_proxy::send_pending_commands() {
for (auto &i : s.second) {
for (auto &pn : i.second) {
routing_manager_base::notify(s.first, i.first,
- pn.first, pn.second->get_payload(), false);
+ pn.first, pn.second->get_payload(), false, true); // TODO: Use _flush argument to send all events at once
}
}
}
@@ -1385,6 +1467,12 @@ void routing_manager_proxy::init_receiver() {
::_unlink(its_client.str().c_str());
int port = VSOMEIP_INTERNAL_BASE_PORT + client_;
#else
+ if (!check_credentials(get_client(), getuid(), getgid())) {
+ VSOMEIP_ERROR << "routing_manager_proxy::init_receiver: "
+ << std::hex << "Client " << get_client() << " isn't allow"
+ << " to create a server endpoint due to credential check failed!";
+ return;
+ }
if (-1 == ::unlink(its_client.str().c_str()) && errno != ENOENT) {
VSOMEIP_ERROR << "routing_manager_proxy::init_receiver unlink failed ("
<< its_client.str() << "): "<< std::strerror(errno);
@@ -1503,4 +1591,24 @@ 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;
+ 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::recursive_mutex> its_lock(sender_mutex_);
+ if (sender_) {
+ sender_->send(its_command, VSOMEIP_COMMAND_HEADER_SIZE);
+ }
+ }
+}
+
+bool routing_manager_proxy::is_client_known(client_t _client) {
+ std::lock_guard<std::mutex> its_lock(known_clients_mutex_);
+ return (known_clients_.find(_client) != known_clients_.end());
+}
} // namespace vsomeip
diff --git a/implementation/routing/src/routing_manager_stub.cpp b/implementation/routing/src/routing_manager_stub.cpp
index 900f266..3874a07 100644
--- a/implementation/routing/src/routing_manager_stub.cpp
+++ b/implementation/routing/src/routing_manager_stub.cpp
@@ -21,6 +21,11 @@
#include <vsomeip/runtime.hpp>
#include <vsomeip/error.hpp>
+#ifndef WITHOUT_SYSTEMD
+#include <systemd/sd-daemon.h>
+#endif
+#define SD_LISTEN_FDS_START 3
+
#include "../include/routing_manager_stub.hpp"
#include "../include/routing_manager_stub_host.hpp"
#include "../../configuration/include/configuration.hpp"
@@ -94,16 +99,18 @@ void routing_manager_stub::stop() {
watchdog_timer_.cancel();
- endpoint_->stop();
- endpoint_ = nullptr;
+ if( !is_socket_activated_) {
+ endpoint_->stop();
+ endpoint_ = nullptr;
#ifdef WIN32
- ::_unlink(endpoint_path_.c_str());
+ ::_unlink(endpoint_path_.c_str());
#else
- if (-1 == ::unlink(endpoint_path_.c_str())) {
- VSOMEIP_ERROR << "routing_manager_stub::stop() unlink failed ("
- << endpoint_path_ << "): "<< std::strerror(errno);
- }
+ if (-1 == ::unlink(endpoint_path_.c_str())) {
+ VSOMEIP_ERROR << "routing_manager_stub::stop() unlink failed ("
+ << endpoint_path_ << "): "<< std::strerror(errno);
+ }
#endif
+ }
if(local_receiver_) {
local_receiver_->stop();
@@ -121,6 +128,10 @@ void routing_manager_stub::stop() {
broadcast_routing_info(true);
}
+const std::shared_ptr<configuration> routing_manager_stub::get_configuration() const {
+ return configuration_;
+}
+
void routing_manager_stub::on_connect(std::shared_ptr<endpoint> _endpoint) {
(void)_endpoint;
}
@@ -146,7 +157,8 @@ void routing_manager_stub::release_port(uint16_t _port, bool _reliable) {
}
void routing_manager_stub::on_message(const byte_t *_data, length_t _size,
- endpoint *_receiver, const boost::asio::ip::address &_destination) {
+ endpoint *_receiver, const boost::asio::ip::address &_destination,
+ client_t _bound_client) {
(void)_receiver;
(void)_destination;
#if 0
@@ -177,11 +189,23 @@ void routing_manager_stub::on_message(const byte_t *_data, length_t _size,
bool use_exclusive_proxy(false);
subscription_type_e its_subscription_type;
bool is_remote_subscriber(false);
+ client_t its_client_from_header;
+ client_t its_target_client;
its_command = _data[VSOMEIP_COMMAND_TYPE_POS];
std::memcpy(&its_client, &_data[VSOMEIP_COMMAND_CLIENT_POS],
sizeof(its_client));
+ if (configuration_->is_security_enabled() && _bound_client != its_client) {
+ VSOMEIP_WARNING << "Security: Routing Manager received a message from client "
+ << std::hex << std::setw(4) << std::setfill('0')
+ << its_client << " with command " << (uint32_t)its_command <<
+ " which doesn't match the bound client "
+ << std::setw(4) << std::setfill('0') << _bound_client
+ << " ~> skip message!";
+ return;
+ }
+
std::memcpy(&its_size, &_data[VSOMEIP_COMMAND_SIZE_POS_MIN],
sizeof(its_size));
@@ -257,8 +281,16 @@ void routing_manager_stub::on_message(const byte_t *_data, length_t _size,
sizeof(is_remote_subscriber));
std::memcpy(&its_subscription_type, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 8],
sizeof(its_subscription_type));
- host_->subscribe(its_client, its_service,
- its_instance, its_eventgroup, its_major, its_subscription_type);
+ if (configuration_->is_client_allowed(its_client,
+ its_service, its_instance)) {
+ host_->subscribe(its_client, its_service,
+ its_instance, its_eventgroup, its_major, its_subscription_type);
+ } else {
+ VSOMEIP_WARNING << "Security: Client " << std::hex
+ << its_client << " subscribes to service/instance "
+ << its_service << "/" << its_instance
+ << " which violates the security policy ~> Skip subscribe!";
+ }
break;
case VSOMEIP_UNSUBSCRIBE:
@@ -307,9 +339,33 @@ void routing_manager_stub::on_message(const byte_t *_data, length_t _size,
its_service = VSOMEIP_BYTES_TO_WORD(
its_data[VSOMEIP_SERVICE_POS_MIN],
its_data[VSOMEIP_SERVICE_POS_MAX]);
+ its_client_from_header = VSOMEIP_BYTES_TO_WORD(
+ 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));
+ if (utility::is_request(its_data[VSOMEIP_MESSAGE_TYPE_POS])) {
+ if (!configuration_->is_client_allowed(its_client_from_header,
+ its_service, its_instance)) {
+ VSOMEIP_WARNING << std::hex << "Security: Client 0x" << its_client_from_header
+ << " isn't allow to send a request to service/instance "
+ << its_service << "/" << its_instance
+ << " : Skip message!";
+ return;
+ }
+ } else {
+ if (!configuration_->is_client_allowed(get_client(), its_service,
+ its_instance)) {
+ VSOMEIP_WARNING << std::hex << "Security: Client 0x"
+ << get_client()
+ << " isn't allow receive a response from to service/instance "
+ << its_service << "/" << its_instance
+ << " respectively from client 0x" << its_client
+ << " : Skip message!";
+ return;
+ }
+ }
host_->on_message(its_service, its_instance, its_data, its_size, its_reliable);
break;
@@ -318,21 +374,22 @@ void routing_manager_stub::on_message(const byte_t *_data, length_t _size,
its_service = VSOMEIP_BYTES_TO_WORD(
its_data[VSOMEIP_SERVICE_POS_MIN],
its_data[VSOMEIP_SERVICE_POS_MAX]);
- its_client = VSOMEIP_BYTES_TO_WORD(
- 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));
- host_->on_notification(its_client, its_service, its_instance, its_data, its_size);
+ host_->on_notification(VSOMEIP_ROUTING_CLIENT, its_service, its_instance,
+ its_data, its_size);
break;
case VSOMEIP_NOTIFY_ONE:
its_data = &_data[VSOMEIP_COMMAND_PAYLOAD_POS];
its_service = VSOMEIP_BYTES_TO_WORD(
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));
- host_->on_notification(its_client, its_service, its_instance, its_data, its_size, true);
+ std::memcpy(&its_instance, &_data[_size - sizeof(instance_t) -
+ sizeof(bool) - sizeof(bool) - sizeof(client_t)],
+ sizeof(its_instance));
+ std::memcpy(&its_target_client, &_data[_size - sizeof(client_t)], sizeof(client_t));
+ host_->on_notification(its_target_client, its_service, its_instance,
+ its_data, its_size, true);
break;
case VSOMEIP_REQUEST_SERVICE:
@@ -347,8 +404,15 @@ void routing_manager_stub::on_message(const byte_t *_data, length_t _size,
sizeof(its_minor));
std::memcpy(&use_exclusive_proxy, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 9],
sizeof(use_exclusive_proxy));
- host_->request_service(its_client, its_service, its_instance,
- its_major, its_minor, use_exclusive_proxy);
+ if (configuration_->is_client_allowed(its_client, its_service, its_instance)) {
+ host_->request_service(its_client, its_service, its_instance,
+ its_major, its_minor, use_exclusive_proxy);
+ } else {
+ VSOMEIP_WARNING << "Security: Client " << std::hex
+ << its_client << " requests service/instance "
+ << its_service << "/" << its_instance
+ << " which violates the security policy ~> Skip request!";
+ }
break;
case VSOMEIP_RELEASE_SERVICE:
@@ -376,6 +440,11 @@ void routing_manager_stub::on_message(const byte_t *_data, length_t _size,
std::memcpy(&is_provided,
&_data[VSOMEIP_COMMAND_PAYLOAD_POS + 7],
sizeof(is_provided));
+ if (is_provided
+ && !configuration_->is_offered_remote(its_service,
+ its_instance)) {
+ break;
+ }
for (std::size_t i = 8; i+1 < its_size; i++) {
std::memcpy(&its_eventgroup,
&_data[VSOMEIP_COMMAND_PAYLOAD_POS + i],
@@ -404,6 +473,11 @@ void routing_manager_stub::on_message(const byte_t *_data, length_t _size,
std::memcpy(&is_provided,
&_data[VSOMEIP_COMMAND_PAYLOAD_POS + 6],
sizeof(is_provided));
+ if (is_provided
+ && !configuration_->is_offered_remote(its_service,
+ its_instance)) {
+ break;
+ }
host_->unregister_shadow_event(its_client, its_service, its_instance,
its_event, is_provided);
VSOMEIP_DEBUG << "UNREGISTER EVENT("
@@ -430,6 +504,13 @@ void routing_manager_stub::on_message(const byte_t *_data, length_t _size,
<< std::hex << std::setw(4) << std::setfill('0') << its_instance
<< ":is_reliable=" << its_reliable << "]";
break;
+
+ case VSOMEIP_REGISTERED_ACK:
+ VSOMEIP_DEBUG << "REGISTERED_ACK("
+ << std::hex << std::setw(4) << std::setfill('0') << its_client << ")";
+ std::lock_guard<std::mutex> its_guard(routing_info_mutex_);
+ broadcast_routing_info(false, its_client);
+ break;
}
}
}
@@ -486,23 +567,20 @@ void routing_manager_stub::client_registration_func(void) {
on_deregister_application(r.first);
}
{
- // Inform (de)registered client first then broadcast all others
+ // Inform (de)registered client. All others will be informed after
+ // the client acknowledged its registered state!
// Don't inform client if we deregister because of an client
// endpoint error to avoid writing in an already closed socket
std::lock_guard<std::mutex> its_guard(routing_info_mutex_);
if (b != registration_type_e::DEREGISTER_ERROR_CASE) {
send_routing_info(r.first);
}
- for (auto& info : routing_info_) {
- if (info.first != VSOMEIP_ROUTING_CLIENT &&
- info.first != host_->get_client() &&
- info.first != r.first) {
- send_routing_info(info.first);
- }
- }
}
- if (b == registration_type_e::DEREGISTER
- || b == registration_type_e::DEREGISTER_ERROR_CASE) {
+ if (b != registration_type_e::REGISTER) {
+ {
+ std::lock_guard<std::mutex> its_guard(routing_info_mutex_);
+ broadcast_routing_info(false, r.first);
+ }
host_->remove_local(r.first);
}
if (b == registration_type_e::DEREGISTER_ERROR_CASE) {
@@ -519,40 +597,73 @@ void routing_manager_stub::init_routing_endpoint() {
std::stringstream its_endpoint_path;
its_endpoint_path << VSOMEIP_BASE_PATH << VSOMEIP_ROUTING_CLIENT;
endpoint_path_ = its_endpoint_path.str();
-
-#if WIN32
- ::_unlink(endpoint_path_.c_str());
- int port = VSOMEIP_INTERNAL_BASE_PORT;
- VSOMEIP_DEBUG << "Routing endpoint at " << port;
-#else
- if (-1 == ::unlink(endpoint_path_.c_str()) && errno != ENOENT) {
- VSOMEIP_ERROR << "routing_manager_stub::init_endpoint unlink failed ("
- << endpoint_path_ << "): "<< std::strerror(errno);
+ client_t routing_host_id = configuration_->get_id(configuration_->get_routing_host());
+ if (configuration_->is_security_enabled() && get_client() != routing_host_id) {
+ VSOMEIP_ERROR << "routing_manager_stub::init_routing_endpoint: "
+ << std::hex << "Client " << get_client() << " isn't allow"
+ << " to create the routing endpoint due to its not configured as the routing master!";
+ return;
}
- VSOMEIP_DEBUG << "Routing endpoint at " << endpoint_path_;
-
- const mode_t previous_mask(::umask(static_cast<mode_t>(configuration_->get_umask())));
+ uint32_t native_socket_fd, num_fd = 0;
+#ifndef WITHOUT_SYSTEMD
+ num_fd = sd_listen_fds(0);
#endif
-
- try {
- endpoint_ =
- std::make_shared < local_server_endpoint_impl
- > (shared_from_this(),
- #ifdef WIN32
- boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), port),
- #else
- boost::asio::local::stream_protocol::endpoint(endpoint_path_),
- #endif
- io_, configuration_->get_max_message_size_local());
- } catch (const std::exception &e) {
- VSOMEIP_ERROR << ERROR_INFO[static_cast<int>(error_code_e::SERVER_ENDPOINT_CREATION_FAILED)]
- << " (" << static_cast<int>(error_code_e::SERVER_ENDPOINT_CREATION_FAILED) << ")";
- VSOMEIP_ERROR << "routing_manager_stub::init_endpoint Client ID: "
- << std::hex << VSOMEIP_ROUTING_CLIENT << ": " << e.what();
+ if (num_fd > 1) {
+ VSOMEIP_ERROR << "Too many file descriptors received by systemd socket activation! num_fd: " << num_fd;
+ } else if (num_fd == 1) {
+ native_socket_fd = SD_LISTEN_FDS_START + 0;
+ VSOMEIP_INFO << "Using native socket created by systemd socket activation! fd: " << native_socket_fd;
+ #ifndef WIN32
+ try {
+ endpoint_ =
+ std::make_shared < local_server_endpoint_impl
+ > (shared_from_this(),
+ boost::asio::local::stream_protocol::endpoint(endpoint_path_),
+ io_, configuration_->get_max_message_size_local(), native_socket_fd);
+ } catch (const std::exception &e) {
+ VSOMEIP_ERROR << ERROR_INFO[static_cast<int>(error_code_e::SERVER_ENDPOINT_CREATION_FAILED)]
+ << " (" << static_cast<int>(error_code_e::SERVER_ENDPOINT_CREATION_FAILED) << ")";
+ VSOMEIP_ERROR << "routing_manager_stub::init_endpoint Client ID: "
+ << std::hex << VSOMEIP_ROUTING_CLIENT << ": " << e.what();
+ }
+ #endif
+ is_socket_activated_ = true;
+ } else {
+ #if WIN32
+ ::_unlink(endpoint_path_.c_str());
+ int port = VSOMEIP_INTERNAL_BASE_PORT;
+ VSOMEIP_DEBUG << "Routing endpoint at " << port;
+ #else
+ if (-1 == ::unlink(endpoint_path_.c_str()) && errno != ENOENT) {
+ VSOMEIP_ERROR << "routing_manager_stub::init_endpoint unlink failed ("
+ << endpoint_path_ << "): "<< std::strerror(errno);
+ }
+ VSOMEIP_DEBUG << "init_routing_endpoint Routing endpoint at " << endpoint_path_;
+
+ const mode_t previous_mask(::umask(static_cast<mode_t>(configuration_->get_umask())));
+ #endif
+
+ try {
+ endpoint_ =
+ std::make_shared < local_server_endpoint_impl
+ > (shared_from_this(),
+ #ifdef WIN32
+ boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), port),
+ #else
+ boost::asio::local::stream_protocol::endpoint(endpoint_path_),
+ #endif
+ io_, configuration_->get_max_message_size_local());
+ } catch (const std::exception &e) {
+ VSOMEIP_ERROR << ERROR_INFO[static_cast<int>(error_code_e::SERVER_ENDPOINT_CREATION_FAILED)]
+ << " (" << static_cast<int>(error_code_e::SERVER_ENDPOINT_CREATION_FAILED) << ")";
+ VSOMEIP_ERROR << "routing_manager_stub::init_endpoint Client ID: "
+ << std::hex << VSOMEIP_ROUTING_CLIENT << ": " << e.what();
+ }
+ #ifndef WIN32
+ ::umask(previous_mask);
+ #endif
+ is_socket_activated_ = false;
}
-#ifndef WIN32
- ::umask(previous_mask);
-#endif
}
void routing_manager_stub::on_offer_service(client_t _client,
@@ -561,8 +672,17 @@ void routing_manager_stub::on_offer_service(client_t _client,
if (_client == host_->get_client()) {
create_local_receiver();
}
- routing_info_[_client].second[_service][_instance] = std::make_pair(_major, _minor);
- broadcast_routing_info();
+
+ if (_client == VSOMEIP_ROUTING_CLIENT ||
+ configuration_->is_offer_allowed(_client, _service, _instance)) {
+ routing_info_[_client].second[_service][_instance] = std::make_pair(_major, _minor);
+ broadcast_routing_info();
+ } else {
+ VSOMEIP_WARNING << std::hex << "Security: Client 0x" << _client
+ << " isn't allow to offer the following service/instance "
+ << _service << "/" << _instance
+ << " : Skip offer!";
+ }
}
void routing_manager_stub::on_stop_offer_service(client_t _client,
@@ -605,7 +725,7 @@ void routing_manager_stub::send_routing_info(client_t _client, bool _empty) {
its_command.push_back(VSOMEIP_ROUTING_INFO);
// Sender client
- client_t client = 0x0;
+ 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]);
@@ -705,9 +825,11 @@ void routing_manager_stub::send_routing_info(client_t _client, bool _empty) {
}
}
-void routing_manager_stub::broadcast_routing_info(bool _empty) {
+void routing_manager_stub::broadcast_routing_info(bool _empty, client_t _ignore) {
for (auto& info : routing_info_) {
- if (info.first != VSOMEIP_ROUTING_CLIENT && info.first != host_->get_client()) {
+ if (info.first != VSOMEIP_ROUTING_CLIENT &&
+ info.first != host_->get_client() &&
+ info.first != _ignore) {
send_routing_info(info.first, _empty);
}
}
@@ -788,8 +910,9 @@ void routing_manager_stub::send_subscribe_ack(client_t _client, service_t _servi
uint32_t its_size = VSOMEIP_SUBSCRIBE_ACK_COMMAND_SIZE
- VSOMEIP_COMMAND_HEADER_SIZE;
+ client_t this_client = get_client();
its_command[VSOMEIP_COMMAND_TYPE_POS] = VSOMEIP_SUBSCRIBE_ACK;
- std::memcpy(&its_command[VSOMEIP_COMMAND_CLIENT_POS], &_client,
+ std::memcpy(&its_command[VSOMEIP_COMMAND_CLIENT_POS], &this_client,
sizeof(_client));
std::memcpy(&its_command[VSOMEIP_COMMAND_SIZE_POS_MIN], &its_size,
sizeof(its_size));
@@ -813,8 +936,9 @@ void routing_manager_stub::send_subscribe_nack(client_t _client, service_t _serv
uint32_t its_size = VSOMEIP_SUBSCRIBE_NACK_COMMAND_SIZE
- VSOMEIP_COMMAND_HEADER_SIZE;
+ client_t this_client = get_client();
its_command[VSOMEIP_COMMAND_TYPE_POS] = VSOMEIP_SUBSCRIBE_NACK;
- std::memcpy(&its_command[VSOMEIP_COMMAND_CLIENT_POS], &_client,
+ std::memcpy(&its_command[VSOMEIP_COMMAND_CLIENT_POS], &this_client,
sizeof(_client));
std::memcpy(&its_command[VSOMEIP_COMMAND_SIZE_POS_MIN], &its_size,
sizeof(its_size));
@@ -929,6 +1053,12 @@ void routing_manager_stub::create_local_receiver() {
::_unlink(local_receiver_path_.c_str());
int port = VSOMEIP_INTERNAL_BASE_PORT;
#else
+ if (!check_credentials(get_client(), getuid(), getgid())) {
+ VSOMEIP_ERROR << "routing_manager_stub::create_local_receiver: "
+ << std::hex << "Client " << get_client() << " isn't allow"
+ << " to create a server endpoint due to credential check failed!";
+ return;
+ }
if (-1 == ::unlink(local_receiver_path_.c_str()) && errno != ENOENT) {
VSOMEIP_ERROR << "routing_manager_stub::create_local_receiver unlink (local receiver) failed ("
<< local_receiver_path_ << "): "<< std::strerror(errno);
@@ -936,7 +1066,6 @@ void routing_manager_stub::create_local_receiver() {
const mode_t previous_mask(::umask(static_cast<mode_t>(configuration_->get_umask())));
#endif
-
try {
local_receiver_ =
std::make_shared < local_server_endpoint_impl
@@ -1115,4 +1244,14 @@ void routing_manager_stub::deregister_erroneous_client(client_t _client) {
client_registration_condition_.notify_one();
}
+client_t routing_manager_stub::get_client() const {
+ return host_->get_client();
+}
+
+#ifndef WIN32
+bool routing_manager_stub::check_credentials(client_t _client, uid_t _uid, gid_t _gid) {
+ return configuration_->check_credentials(_client, _uid, _gid);
+}
+#endif
+
} // namespace vsomeip
diff --git a/implementation/routing/src/serviceinfo.cpp b/implementation/routing/src/serviceinfo.cpp
index fcf535e..f8db130 100644
--- a/implementation/routing/src/serviceinfo.cpp
+++ b/implementation/routing/src/serviceinfo.cpp
@@ -15,7 +15,8 @@ serviceinfo::serviceinfo(major_version_t _major, minor_version_t _minor,
ttl_(0),
reliable_(nullptr),
unreliable_(nullptr),
- is_local_(_is_local) {
+ is_local_(_is_local),
+ is_in_mainphase_(false) {
std::chrono::seconds ttl = static_cast<std::chrono::seconds> (_ttl);
ttl_ = std::chrono::duration_cast<std::chrono::milliseconds>(ttl);
@@ -87,5 +88,13 @@ bool serviceinfo::is_local() const {
return is_local_;
}
+bool serviceinfo::is_in_mainphase() const {
+ return is_in_mainphase_;
+}
+
+void serviceinfo::set_is_in_mainphase(bool _in_mainphase) {
+ is_in_mainphase_ = _in_mainphase;
+}
+
} // namespace vsomeip
diff --git a/implementation/runtime/include/application_impl.hpp b/implementation/runtime/include/application_impl.hpp
index 5b3fe26..88d00bc 100644
--- a/implementation/runtime/include/application_impl.hpp
+++ b/implementation/runtime/include/application_impl.hpp
@@ -26,6 +26,7 @@
namespace vsomeip {
+class runtime;
class configuration;
class logger;
class routing_manager;
@@ -95,12 +96,18 @@ public:
VSOMEIP_EXPORT void notify(service_t _service, instance_t _instance,
event_t _event, std::shared_ptr<payload> _payload,
bool _force) const;
+ VSOMEIP_EXPORT void notify(service_t _service, instance_t _instance,
+ event_t _event, std::shared_ptr<payload> _payload,
+ bool _force, bool _flush) const;
VSOMEIP_EXPORT void notify_one(service_t _service, instance_t _instance,
event_t _event, std::shared_ptr<payload> _payload, client_t _client) const;
VSOMEIP_EXPORT void notify_one(service_t _service, instance_t _instance,
event_t _event, std::shared_ptr<payload> _payload, client_t _client,
bool _force) const;
+ VSOMEIP_EXPORT void notify_one(service_t _service, instance_t _instance,
+ event_t _event, std::shared_ptr<payload> _payload, client_t _client,
+ bool _force, bool _flush) const;
VSOMEIP_EXPORT void register_state_handler(state_handler_t _handler);
VSOMEIP_EXPORT void unregister_state_handler();
@@ -152,6 +159,9 @@ public:
VSOMEIP_EXPORT bool are_available(available_t &_available,
service_t _service = ANY_SERVICE, instance_t _instance = ANY_INSTANCE,
major_version_t _major = ANY_MAJOR, minor_version_t _minor = ANY_MINOR) const;
+ VSOMEIP_EXPORT void set_routing_state(routing_state_e _routing_state);
+
+ VSOMEIP_EXPORT void clear_all_handler();
private:
//
@@ -181,7 +191,6 @@ private:
//
// Methods
//
- void service();
inline void update_session() {
session_++;
if (0 == session_) {
@@ -206,7 +215,6 @@ private:
bool is_active_dispatcher(std::thread::id &_id);
void remove_elapsed_dispatchers();
- void clear_all_handler();
void shutdown();
void send_back_cached_event(service_t _service, instance_t _instance, event_t _event);
@@ -215,6 +223,7 @@ private:
//
// Attributes
//
+ std::shared_ptr<runtime> runtime_;
client_t client_; // unique application identifier
session_t session_;
std::mutex session_mutex_;
@@ -224,10 +233,9 @@ private:
std::string name_;
std::shared_ptr<configuration> configuration_;
- std::string file_; // configuration file
- std::string folder_; // configuration folder
boost::asio::io_service io_;
+ std::set<std::shared_ptr<std::thread> > io_threads_;
std::shared_ptr<boost::asio::io_service::work> work_;
// Proxy to or the Routing Manager itself
@@ -308,10 +316,9 @@ private:
std::map<service_t, std::map<instance_t, std::map<event_t, bool>>> event_subscriptions_;
std::thread::id stop_caller_id_;
+ std::thread::id start_caller_id_;
bool stopped_called_;
-
- std::thread::id io_thread_id_;
};
} // namespace vsomeip
diff --git a/implementation/runtime/include/runtime_impl.hpp b/implementation/runtime/include/runtime_impl.hpp
index a81b00e..e761d8a 100644
--- a/implementation/runtime/include/runtime_impl.hpp
+++ b/implementation/runtime/include/runtime_impl.hpp
@@ -43,7 +43,7 @@ private:
static std::shared_ptr<runtime> the_runtime_;
static std::map<std::string, std::string> properties_;
- std::map<std::string, std::shared_ptr<application>> applications_;
+ std::map<std::string, std::weak_ptr<application>> applications_;
};
} // namespace vsomeip
diff --git a/implementation/runtime/src/application_impl.cpp b/implementation/runtime/src/application_impl.cpp
index d8f08d6..ccf4e05 100644
--- a/implementation/runtime/src/application_impl.cpp
+++ b/implementation/runtime/src/application_impl.cpp
@@ -22,7 +22,6 @@
#include "../../routing/include/routing_manager_impl.hpp"
#include "../../routing/include/routing_manager_proxy.hpp"
#include "../../utility/include/utility.hpp"
-#include "../../configuration/include/configuration_impl.hpp"
#include "../../tracing/include/trace_connector.hpp"
#include "../../tracing/include/enumeration_types.hpp"
@@ -32,11 +31,11 @@ uint32_t application_impl::app_counter__ = 0;
std::mutex application_impl::app_counter_mutex__;
application_impl::application_impl(const std::string &_name)
- : client_(ILLEGAL_CLIENT),
+ : runtime_(runtime::get()),
+ client_(ILLEGAL_CLIENT),
session_(1),
is_initialized_(false), name_(_name),
- file_(VSOMEIP_DEFAULT_CONFIGURATION_FILE),
- folder_(VSOMEIP_DEFAULT_CONFIGURATION_FOLDER),
+ work_(std::make_shared<boost::asio::io_service::work>(io_)),
routing_(0),
state_(state_type_e::ST_DEREGISTERED),
#ifdef VSOMEIP_ENABLE_SIGNAL_HANDLING
@@ -60,8 +59,8 @@ application_impl::~application_impl() {
void application_impl::set_configuration(
const std::shared_ptr<configuration> _configuration) {
- if(_configuration)
- configuration_ = std::make_shared<cfg::configuration_impl>(*(std::static_pointer_cast<cfg::configuration_impl, configuration>(_configuration)));
+ (void)_configuration;
+ // Dummy.
}
bool application_impl::init() {
@@ -80,74 +79,26 @@ bool application_impl::init() {
// load configuration from module
std::string config_module = "";
const char *its_config_module = getenv(VSOMEIP_ENV_CONFIGURATION_MODULE);
- if(nullptr != its_config_module) {
- config_module = its_config_module;
- if (config_module.rfind(".so") != config_module.length() - 3) {
- config_module += ".so";
- }
- VSOMEIP_INFO << "Loading configuration from module \"" << config_module << "\".";
-#ifdef WIN32
- HMODULE config = LoadLibrary(config_module.c_str());
- if (config != 0) {
- VSOMEIP_INFO << "\"" << config_module << "\" is loaded.";
- if (!configuration_) {
- VSOMEIP_ERROR << "Configuration not set.";
- return false;
- }
- } else {
- VSOMEIP_ERROR << "\"" << config_module << "\" could not be loaded (" << GetLastError() << ")";
- return false;
- }
- FreeModule(config);
-#else
- void *config = dlopen(config_module.c_str(), RTLD_LAZY | RTLD_GLOBAL);
- if(config != 0) {
- VSOMEIP_INFO << "\"" << config_module << "\" is loaded.";
- if(!configuration_) {
- VSOMEIP_ERROR << "Configuration not set.";
- return false;
- }
+ 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);
+ configuration_->load(name_);
+ VSOMEIP_INFO << "Default configuration module loaded.";
} else {
- VSOMEIP_ERROR << "\"" << config_module << "\" could not be loaded (" << dlerror() << ").";
- return false;
- }
- dlclose(config);
-#endif
- } else {
- // Override with local file /folder
- std::string its_local_file(VSOMEIP_LOCAL_CONFIGURATION_FILE);
- if (utility::is_file(its_local_file)) {
- file_ = its_local_file;
- }
-
- std::string its_local_folder(VSOMEIP_LOCAL_CONFIGURATION_FOLDER);
- if (utility::is_folder(its_local_folder)) {
- folder_ = its_local_folder;
- }
-
- // Finally, override with path from environment
- const char *its_env = getenv(VSOMEIP_ENV_CONFIGURATION);
- if (nullptr != its_env) {
- if (utility::is_file(its_env)) {
- file_ = its_env;
- folder_ = "";
- } else if (utility::is_folder(its_env)) {
- folder_ = its_env;
- file_ = "";
- }
+ exit(-1);
}
}
std::shared_ptr<configuration> its_configuration = get_configuration();
if (its_configuration) {
VSOMEIP_INFO << "Initializing vsomeip application \"" << name_ << "\".";
-
- if (utility::is_file(file_))
- VSOMEIP_INFO << "Using configuration file: \"" << file_ << "\".";
-
- if (utility::is_folder(folder_))
- VSOMEIP_INFO << "Using configuration folder: \"" << folder_ << "\".";
-
client_ = its_configuration->get_id(name_);
// Max dispatchers is the configured maximum number of dispatchers and
@@ -156,13 +107,13 @@ bool application_impl::init() {
max_dispatch_time_ = its_configuration->get_max_dispatch_time(name_);
std::string its_routing_host = its_configuration->get_routing_host();
- if (!utility::auto_configuration_init()) {
+ if (!utility::auto_configuration_init(its_configuration)) {
VSOMEIP_WARNING << "Could _not_ initialize auto-configuration:"
" Cannot guarantee unique application identifiers!";
} else {
// Client Identifier
client_t its_old_client = client_;
- client_ = utility::request_client_id(name_, client_);
+ client_ = utility::request_client_id(its_configuration, name_, client_);
if (client_ == ILLEGAL_CLIENT) {
VSOMEIP_ERROR << "Couldn't acquire client identifier";
return false;
@@ -178,11 +129,8 @@ bool application_impl::init() {
// Routing
if (its_routing_host == "") {
+ VSOMEIP_INFO << "No routing manager configured. Using auto-configuration.";
is_routing_manager_host_ = utility::is_routing_manager_host(client_);
- VSOMEIP_INFO << "No routing manager configured. "
- << "Using auto-configuration ("
- << (is_routing_manager_host_ ?
- "Host" : "Proxy") << ")";
}
}
@@ -191,8 +139,10 @@ bool application_impl::init() {
}
if (is_routing_manager_host_) {
+ VSOMEIP_INFO << "Instantiating routing manager [Host].";
routing_ = std::make_shared<routing_manager_impl>(this);
} else {
+ VSOMEIP_INFO << "Instantiating routing manager [Proxy].";
routing_ = std::make_shared<routing_manager_proxy>(this);
}
@@ -294,7 +244,7 @@ void application_impl::start() {
is_dispatching_ = true;
- io_thread_id_ = std::this_thread::get_id();
+ start_caller_id_ = std::this_thread::get_id();
auto its_main_dispatcher = std::make_shared<std::thread>(
std::bind(&application_impl::main_dispatch, this));
@@ -307,15 +257,20 @@ void application_impl::start() {
if (routing_)
routing_->start();
+
+ for (int i = 0; i < 3; i++) {
+ std::shared_ptr<std::thread> its_thread
+ = std::make_shared<std::thread>([this, i] {
+ io_.run();
+ });
+ io_threads_.insert(its_thread);
+ }
}
app_counter_mutex__.lock();
app_counter__++;
app_counter_mutex__.unlock();
- work_ = std::make_shared<boost::asio::io_service::work>(io_);
- io_.run();
-
if (stop_thread_.joinable()) {
stop_thread_.join();
}
@@ -360,7 +315,12 @@ void application_impl::stop() {
stop_caller_id_ = std::this_thread::get_id();
stopped_ = true;
stopped_called_ = true;
- if (io_thread_id_ == std::this_thread::get_id()) {
+ for (auto thread : io_threads_) {
+ if (thread->get_id() == std::this_thread::get_id()) {
+ block = false;
+ }
+ }
+ if (start_caller_id_ == stop_caller_id_) {
block = false;
}
}
@@ -640,19 +600,25 @@ void application_impl::send(std::shared_ptr<message> _message, bool _flush) {
void application_impl::notify(service_t _service, instance_t _instance,
event_t _event, std::shared_ptr<payload> _payload) const {
- return notify(_service, _instance, _event, _payload, false);
+ return notify(_service, _instance, _event, _payload, false, true);
}
void application_impl::notify(service_t _service, instance_t _instance,
event_t _event, std::shared_ptr<payload> _payload, bool _force) const {
if (routing_)
- routing_->notify(_service, _instance, _event, _payload, _force);
+ routing_->notify(_service, _instance, _event, _payload, _force, true);
+}
+
+void application_impl::notify(service_t _service, instance_t _instance,
+ event_t _event, std::shared_ptr<payload> _payload, bool _force, bool _flush) const {
+ if (routing_)
+ routing_->notify(_service, _instance, _event, _payload, _force, _flush);
}
void application_impl::notify_one(service_t _service, instance_t _instance,
event_t _event, std::shared_ptr<payload> _payload,
client_t _client) const {
- return notify_one(_service, _instance, _event, _payload, _client, false);
+ return notify_one(_service, _instance, _event, _payload, _client, false, true);
}
void application_impl::notify_one(service_t _service, instance_t _instance,
@@ -660,7 +626,16 @@ void application_impl::notify_one(service_t _service, instance_t _instance,
client_t _client, bool _force) const {
if (routing_) {
routing_->notify_one(_service, _instance, _event, _payload, _client,
- _force);
+ _force, true);
+ }
+}
+
+void application_impl::notify_one(service_t _service, instance_t _instance,
+ event_t _event, std::shared_ptr<payload> _payload,
+ client_t _client, bool _force, bool _flush) const {
+ if (routing_) {
+ routing_->notify_one(_service, _instance, _event, _payload, _client,
+ _force, _flush);
}
}
@@ -749,7 +724,7 @@ void application_impl::register_subscription_handler(service_t _service,
subscription_[_service][_instance][_eventgroup] = _handler;
message_handler_t handler([&](const std::shared_ptr<message>& request) {
- send(runtime::get()->create_response(request), true);
+ send(runtime_->create_response(request), true);
});
register_message_handler(_service, _instance, ANY_METHOD - 1, handler);
}
@@ -895,20 +870,7 @@ client_t application_impl::get_client() const {
}
std::shared_ptr<configuration> application_impl::get_configuration() const {
- if(configuration_) {
- return configuration_;
- } else {
- std::set<std::string> its_input;
- std::shared_ptr<configuration> its_configuration;
- if (file_ != "") {
- its_input.insert(file_);
- }
- if (folder_ != "") {
- its_input.insert(folder_);
- }
- its_configuration = configuration::get(its_input);
- return its_configuration;
- }
+ return configuration_;
}
boost::asio::io_service & application_impl::get_io() {
@@ -916,24 +878,25 @@ boost::asio::io_service & application_impl::get_io() {
}
void application_impl::on_state(state_type_e _state) {
- if (state_ != _state) {
- state_ = _state;
- if (state_ == state_type_e::ST_REGISTERED) {
- std::lock_guard<std::mutex> availability_lock(availability_mutex_);
- for (auto &its_service : availability_) {
- for (auto &its_instance : its_service.second) {
- if (!std::get<3>(its_instance.second)) {
- do_register_availability_handler(
- its_service.first, its_instance.first,
- std::get<2>(its_instance.second),
- std::get<0>(its_instance.second),
- std::get<1>(its_instance.second));
+ {
+ std::lock_guard<std::mutex> availability_lock(availability_mutex_);
+ if (state_ != _state) {
+ state_ = _state;
+ if (state_ == state_type_e::ST_REGISTERED) {
+ for (auto &its_service : availability_) {
+ for (auto &its_instance : its_service.second) {
+ if (!std::get<3>(its_instance.second)) {
+ do_register_availability_handler(
+ its_service.first, its_instance.first,
+ std::get<2>(its_instance.second),
+ std::get<0>(its_instance.second),
+ std::get<1>(its_instance.second));
+ }
}
}
}
}
}
-
if (handler_) {
{
std::lock_guard<std::mutex> its_lock(handlers_mutex_);
@@ -1161,15 +1124,9 @@ routing_manager * application_impl::get_routing_manager() const {
return routing_.get();
}
-// Internal
-void application_impl::service() {
- io_.run();
-}
-
void application_impl::main_dispatch() {
+ std::unique_lock<std::mutex> its_lock(handlers_mutex_);
while (is_dispatching_) {
- std::unique_lock<std::mutex> its_lock(handlers_mutex_);
-
if (handlers_.empty()) {
// Cancel other waiting dispatcher
dispatcher_condition_.notify_all();
@@ -1178,7 +1135,7 @@ void application_impl::main_dispatch() {
dispatcher_condition_.wait(its_lock);
}
} else {
- while (!handlers_.empty()) {
+ while (is_dispatching_ && !handlers_.empty()) {
std::shared_ptr<sync_handler> its_handler = handlers_.front();
handlers_.pop_front();
its_lock.unlock();
@@ -1301,6 +1258,10 @@ void application_impl::clear_all_handler() {
}
void application_impl::shutdown() {
+#ifndef WIN32
+ boost::asio::detail::posix_signal_blocker blocker;
+#endif
+
{
std::unique_lock<std::mutex> its_lock(start_stop_mutex_);
while(!stopped_) {
@@ -1308,7 +1269,7 @@ void application_impl::shutdown() {
}
}
{
- std::unique_lock<std::mutex> its_lock(handlers_mutex_);
+ std::lock_guard<std::mutex> its_lock(handlers_mutex_);
is_dispatching_ = false;
}
dispatcher_condition_.notify_all();
@@ -1338,6 +1299,14 @@ void application_impl::shutdown() {
work_.reset();
io_.stop();
+
+ {
+ std::lock_guard<std::mutex> its_lock_start_stop(start_stop_mutex_);
+ for (auto t : io_threads_) {
+ t->join();
+ }
+ io_threads_.clear();
+ }
}
bool application_impl::is_routing() const {
@@ -1350,7 +1319,7 @@ void application_impl::send_back_cached_event(service_t _service,
std::shared_ptr<event> its_event = routing_->get_event(_service,
_instance, _event);
if (its_event && its_event->is_field() && its_event->is_set()) {
- std::shared_ptr<message> its_message = runtime::get()->create_notification();
+ std::shared_ptr<message> its_message = runtime_->create_notification();
its_message->set_service(_service);
its_message->set_method(_event);
its_message->set_instance(_instance);
@@ -1367,7 +1336,7 @@ void application_impl::send_back_cached_eventgroup(service_t _service,
_eventgroup);
for(const auto &its_event : its_events) {
if (its_event && its_event->is_field() && its_event->is_set()) {
- std::shared_ptr<message> its_message = runtime::get()->create_notification();
+ std::shared_ptr<message> its_message = runtime_->create_notification();
its_message->set_service(_service);
its_message->set_method(its_event->get_event());
its_message->set_instance(_instance);
@@ -1378,4 +1347,9 @@ void application_impl::send_back_cached_eventgroup(service_t _service,
}
}
+void application_impl::set_routing_state(routing_state_e _routing_state) {
+ if (routing_)
+ routing_->set_routing_state(_routing_state);
+}
+
} // namespace vsomeip
diff --git a/implementation/runtime/src/runtime_impl.cpp b/implementation/runtime/src/runtime_impl.cpp
index 4943b6d..cf8c6e6 100644
--- a/implementation/runtime/src/runtime_impl.cpp
+++ b/implementation/runtime/src/runtime_impl.cpp
@@ -107,7 +107,7 @@ std::shared_ptr<application> runtime_impl::get_application(
const std::string &_name) const {
auto found_application = applications_.find(_name);
if(found_application != applications_.end())
- return found_application->second;
+ return found_application->second.lock();
return nullptr;
}
diff --git a/implementation/service_discovery/include/defines.hpp b/implementation/service_discovery/include/defines.hpp
index a0129b6..83a67bf 100644
--- a/implementation/service_discovery/include/defines.hpp
+++ b/implementation/service_discovery/include/defines.hpp
@@ -42,5 +42,6 @@
#define VSOMEIP_SD_DEFAULT_TTL DEFAULT_TTL
#define VSOMEIP_SD_DEFAULT_CYCLIC_OFFER_DELAY 1000
#define VSOMEIP_SD_DEFAULT_REQUEST_RESPONSE_DELAY 2000
+#define VSOMEIP_SD_DEFAULT_OFFER_DEBOUNCE_TIME 500
#endif // VSOMEIP_SD_DEFINES_HPP
diff --git a/implementation/service_discovery/include/fsm_base.hpp b/implementation/service_discovery/include/fsm_base.hpp
deleted file mode 100644
index b04f9a6..0000000
--- a/implementation/service_discovery/include/fsm_base.hpp
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright (C) 2014-2016 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_FSM_BASE_HPP
-#define VSOMEIP_FSM_BASE_HPP
-
-#include <memory>
-
-#include <boost/asio/io_service.hpp>
-#include <boost/asio/steady_timer.hpp>
-
-namespace vsomeip {
-namespace sd {
-
-class fsm_base: public std::enable_shared_from_this<fsm_base> {
-public:
- fsm_base(boost::asio::io_service &_io);
- virtual ~fsm_base();
-
- void start_timer(uint32_t _ms, bool _use_alt_timer = false);
- void stop_timer(bool _use_alt_timer = false);
-
- uint32_t expired_from_now(bool _use_alt_timer = false);
-
- virtual void timer_expired(const boost::system::error_code &_error,
- bool _use_alt_timer) = 0;
-
-private:
- boost::asio::steady_timer timer_;
- boost::asio::steady_timer alt_timer_;
-};
-
-} // namespace sd
-} // namespace vsomeip
-
-#endif // VSOMEIP_FSM_BASE_HPP
diff --git a/implementation/service_discovery/include/fsm_events.hpp b/implementation/service_discovery/include/fsm_events.hpp
deleted file mode 100644
index 75279e2..0000000
--- a/implementation/service_discovery/include/fsm_events.hpp
+++ /dev/null
@@ -1,60 +0,0 @@
-// Copyright (C) 2014-2016 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_FSM_EVENTS_HPP
-#define VSOMEIP_FSM_EVENTS_HPP
-
-#include <boost/statechart/event.hpp>
-
-#include <vsomeip/primitive_types.hpp>
-#include "../../routing/include/serviceinfo.hpp"
-
-namespace sc = boost::statechart;
-
-namespace vsomeip {
-namespace sd {
-
-struct ev_none: sc::event<ev_none> {
-};
-
-struct ev_timeout: sc::event<ev_timeout> {
-};
-
-struct ev_alt_timeout: sc::event<ev_alt_timeout> {
-};
-
-struct ev_status_change: sc::event<ev_status_change> {
- ev_status_change(bool _is_up)
- : is_up_(_is_up) {
- }
-
- bool is_up_;
-};
-
-struct ev_find_service: sc::event<ev_find_service> {
-
- ev_find_service(const std::shared_ptr<const serviceinfo> &_info, service_t _service, instance_t _instance,
- major_version_t _major, minor_version_t _minor, bool _unicast_flag)
- : info_(_info), service_(_service), instance_(_instance), major_(_major), minor_(
- _minor), unicast_flag_(_unicast_flag) {
- }
- const std::shared_ptr<const serviceinfo> &info_;
- service_t service_;
- instance_t instance_;
- major_version_t major_;
- minor_version_t minor_;
- bool unicast_flag_;
-};
-
-struct ev_offer_change: sc::event<ev_offer_change> {
-};
-
-struct ev_request_service: sc::event<ev_request_service> {
-};
-
-} // namespace sd
-} // namespace vsomeip
-
-#endif // VSOMEIP_FSM_EVENTS_HPP
diff --git a/implementation/service_discovery/include/service_discovery.hpp b/implementation/service_discovery/include/service_discovery.hpp
index ebc81fa..14c95bc 100644
--- a/implementation/service_discovery/include/service_discovery.hpp
+++ b/implementation/service_discovery/include/service_discovery.hpp
@@ -13,6 +13,7 @@
#include <vsomeip/enumeration_types.hpp>
#include "../../routing/include/serviceinfo.hpp"
#include "../../endpoints/include/endpoint.hpp"
+#include "../include/service_discovery_host.hpp"
namespace vsomeip {
@@ -49,22 +50,17 @@ public:
const boost::asio::ip::address &_sender,
const boost::asio::ip::address &_destination) = 0;
- virtual void on_offer_change() = 0;
-
virtual void send_subscriptions(service_t _service, instance_t _instance,
client_t _client, bool _reliable) = 0;
- virtual void send_unicast_offer_service(const std::shared_ptr<const serviceinfo> &_info,
- service_t _service, instance_t _instance,
- major_version_t _major,
- minor_version_t _minor) = 0;
- virtual void send_multicast_offer_service(const std::shared_ptr<const serviceinfo>& _info,
- service_t _service, instance_t _instance,
- major_version_t _major,
- minor_version_t _minor) = 0;
virtual void on_reliable_endpoint_connected(
service_t _service, instance_t _instance,
const std::shared_ptr<const vsomeip::endpoint> &_endpoint) = 0;
+
+ virtual void offer_service(service_t _service, instance_t _instance,
+ std::shared_ptr<serviceinfo> _info) = 0;
+ virtual void stop_offer_service(service_t _service, instance_t _instance,
+ std::shared_ptr<serviceinfo> _info) = 0;
};
} // namespace sd
diff --git a/implementation/service_discovery/include/service_discovery_fsm.hpp b/implementation/service_discovery/include/service_discovery_fsm.hpp
deleted file mode 100644
index 915b3e3..0000000
--- a/implementation/service_discovery/include/service_discovery_fsm.hpp
+++ /dev/null
@@ -1,203 +0,0 @@
-// Copyright (C) 2014-2016 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_SD_SERVICE_DISCOVERY_FSM_HPP
-#define VSOMEIP_SD_SERVICE_DISCOVERY_FSM_HPP
-
-#include <mutex>
-#include <string>
-
-#include <boost/mpl/list.hpp>
-#include <boost/statechart/custom_reaction.hpp>
-#include <boost/statechart/state.hpp>
-#include <boost/statechart/state_machine.hpp>
-#include <boost/statechart/transition.hpp>
-#include "../../routing/include/serviceinfo.hpp"
-
-
-#include "../include/fsm_base.hpp"
-#include "../include/fsm_events.hpp"
-
-namespace vsomeip {
-namespace sd {
-
-class service_discovery_fsm;
-class service_discovery;
-
-///////////////////////////////////////////////////////////////////////////////
-// Machine
-///////////////////////////////////////////////////////////////////////////////
-namespace mpl = boost::mpl;
-namespace sc = boost::statechart;
-
-namespace _sd {
-
-struct inactive;
-struct fsm: sc::state_machine<fsm, inactive>, public fsm_base {
-
- fsm(boost::asio::io_service &_io);
- virtual ~fsm();
-
- void set_fsm(std::shared_ptr<service_discovery_fsm> _fsm);
-
- void timer_expired(const boost::system::error_code &_error,
- bool _use_alt_timeout);
-
- uint32_t initial_delay_;
- uint32_t repetitions_base_delay_;
- uint8_t repetitions_max_;
- uint32_t cyclic_offer_delay_;
-
- bool is_up_;
- uint8_t run_;
-
- std::weak_ptr<service_discovery_fsm> fsm_;
-};
-
-struct inactive: sc::state<inactive, fsm> {
-
- inactive(my_context context);
-
- typedef mpl::list<sc::custom_reaction<ev_none>,
- sc::custom_reaction<ev_status_change> > reactions;
-
- sc::result react(const ev_none &_event);
- sc::result react(const ev_status_change &_event);
-};
-
-struct initial;
-struct active: sc::state<active, fsm, initial> {
-
- active(my_context _context);
- ~active();
-
- typedef sc::custom_reaction<ev_status_change> reactions;
-
- sc::result react(const ev_status_change &_event);
-};
-
-struct initial: sc::state<initial, active> {
-
- initial(my_context _context);
-
- typedef sc::custom_reaction<ev_timeout> reactions;
-
- sc::result react(const ev_timeout &_event);
-};
-
-struct repeat: sc::state<repeat, active> {
-
- repeat(my_context _context);
-
- typedef mpl::list<sc::custom_reaction<ev_timeout>,
- sc::custom_reaction<ev_find_service> > reactions;
-
- sc::result react(const ev_timeout &_event);
- sc::result react(const ev_find_service &_event);
-};
-
-struct offer;
-struct find;
-struct main: sc::state<main, active, mpl::list<offer, find>> {
- main(my_context _context);
-};
-
-struct offer: sc::state<offer, main::orthogonal<0> > {
-
- offer(my_context _context);
-
- typedef mpl::list<sc::custom_reaction<ev_timeout>,
- sc::custom_reaction<ev_find_service>,
- sc::custom_reaction<ev_offer_change> > reactions;
-
- sc::result react(const ev_timeout &_event);
- sc::result react(const ev_find_service &_event);
- sc::result react(const ev_offer_change &_event);
-
- uint8_t run_;
-};
-
-struct idle;
-struct find: sc::state<find, main::orthogonal<1>, idle> {
-
- find(my_context _context);
-
- uint8_t run_;
-};
-
-struct idle: sc::state<idle, find> {
- idle(my_context _context);
-
- typedef mpl::list<sc::custom_reaction<ev_request_service> >reactions;
-
- sc::result react(const ev_request_service &_event);
-};
-
-struct send: sc::state<send, find> {
- send(my_context _context);
-
- typedef mpl::list<
- sc::custom_reaction<ev_alt_timeout>,
- sc::custom_reaction<ev_none>
- > reactions;
-
- sc::result react(const ev_alt_timeout &_event);
- sc::result react(const ev_none &_event);
-};
-
-} // namespace _sd
-
-///////////////////////////////////////////////////////////////////////////////
-// Interface
-///////////////////////////////////////////////////////////////////////////////
-class service_discovery_fsm: public std::enable_shared_from_this<
- service_discovery_fsm> {
-public:
- service_discovery_fsm(std::shared_ptr<service_discovery> _discovery);
-
- void start();
- void stop();
-
- bool send(bool _is_announcing, bool _is_find = false);
-
- void send_unicast_offer_service(
- const std::shared_ptr<const serviceinfo> &_info,
- service_t _service, instance_t _instance,
- major_version_t _major,
- minor_version_t _minor);
-
- void send_multicast_offer_service(
- const std::shared_ptr<const serviceinfo> &_info,
- service_t _service, instance_t _instance,
- major_version_t _major,
- minor_version_t _minor);
-
- inline void process(const sc::event_base &_event) {
- std::lock_guard<std::mutex> its_lock(lock_);
- fsm_->process_event(_event);
- }
-
- inline uint8_t get_repetition_max() const {
- if (!fsm_)
- return 0;
-
- return fsm_->repetitions_max_;
- }
-
- std::chrono::milliseconds get_elapsed_offer_timer();
-
- bool check_is_multicast_offer();
-
-private:
- std::weak_ptr<service_discovery> discovery_;
- std::shared_ptr<_sd::fsm> fsm_;
-
- std::mutex lock_;
-};
-
-} // namespace sd
-} // namespace vsomeip
-
-#endif // VSOMEIP_SD_SERVICE_DISCOVERY_FSM_HPP
diff --git a/implementation/service_discovery/include/service_discovery_host.hpp b/implementation/service_discovery/include/service_discovery_host.hpp
index 3f7a594..66d81c8 100644
--- a/implementation/service_discovery/include/service_discovery_host.hpp
+++ b/implementation/service_discovery/include/service_discovery_host.hpp
@@ -8,6 +8,7 @@
#include <map>
#include <memory>
+#include <chrono>
#include <boost/asio/ip/address.hpp>
#include <boost/asio/io_service.hpp>
@@ -28,7 +29,7 @@ public:
}
virtual boost::asio::io_service & get_io() = 0;
- virtual std::shared_ptr<configuration> get_configuration() const = 0;
+ virtual const std::shared_ptr<configuration> get_configuration() const = 0;
virtual std::shared_ptr<endpoint> create_service_discovery_endpoint(
const std::string &_address, uint16_t _port, bool _reliable) = 0;
diff --git a/implementation/service_discovery/include/service_discovery_impl.hpp b/implementation/service_discovery/include/service_discovery_impl.hpp
index 910037d..f2a9e3c 100644
--- a/implementation/service_discovery/include/service_discovery_impl.hpp
+++ b/implementation/service_discovery/include/service_discovery_impl.hpp
@@ -10,6 +10,7 @@
#include <memory>
#include <mutex>
#include <set>
+#include <forward_list>
#include <boost/asio/steady_timer.hpp>
@@ -77,25 +78,16 @@ public:
const boost::asio::ip::address &_sender,
const boost::asio::ip::address &_destination);
- void on_offer_change();
-
- void send_unicast_offer_service(const std::shared_ptr<const serviceinfo> &_info,
- service_t _service, instance_t _instance,
- major_version_t _major,
- minor_version_t _minor);
-
- void send_multicast_offer_service(const std::shared_ptr<const serviceinfo>& _info,
- service_t _service, instance_t _instance,
- major_version_t _major,
- minor_version_t _minor);
-
void on_reliable_endpoint_connected(
service_t _service, instance_t _instance,
const std::shared_ptr<const vsomeip::endpoint> &_endpoint);
-private:
-
+ void offer_service(service_t _service, instance_t _instance,
+ std::shared_ptr<serviceinfo> _info);
+ void stop_offer_service(service_t _service, instance_t _instance,
+ std::shared_ptr<serviceinfo> _info);
+private:
std::pair<session_t, bool> get_session(const boost::asio::ip::address &_address);
void increment_session(const boost::asio::ip::address &_address);
@@ -110,7 +102,8 @@ private:
void insert_find_entries(std::shared_ptr<message_impl> &_message,
requests_t &_requests, uint32_t _start, uint32_t &_size, bool &_done);
void insert_offer_entries(std::shared_ptr<message_impl> &_message,
- services_t &_services, uint32_t &_start, uint32_t _size, bool &_done);
+ const services_t &_services, uint32_t &_start,
+ uint32_t _size, bool &_done, bool _ignore_phase);
bool insert_offer_service(std::shared_ptr<message_impl> _message,
service_t _service, instance_t _instance,
const std::shared_ptr<const serviceinfo> &_info,
@@ -221,6 +214,49 @@ private:
std::shared_ptr<request> find_request(service_t _service, instance_t _instance);
+ void start_offer_debounce_timer(bool _first_start);
+ void on_offer_debounce_timer_expired(const boost::system::error_code &_error);
+
+ void on_repetition_phase_timer_expired(
+ const boost::system::error_code &_error,
+ std::shared_ptr<boost::asio::steady_timer> _timer,
+ std::uint8_t _repetition, std::uint32_t _last_delay);
+ void move_offers_into_main_phase(
+ const std::shared_ptr<boost::asio::steady_timer> &_timer);
+
+ void fill_message_with_offer_entries(
+ std::shared_ptr<runtime> _runtime,
+ std::shared_ptr<message_impl> _message,
+ std::vector<std::shared_ptr<message_impl>> &_messages,
+ const services_t &_offers, bool _ignore_phase);
+
+ bool serialize_and_send_messages(
+ const std::vector<std::shared_ptr<message_impl>> &_messages);
+
+ bool send_stop_offer(service_t _service, instance_t _instance,
+ std::shared_ptr<serviceinfo> _info);
+
+ void start_main_phase_timer();
+ void on_main_phase_timer_expired(const boost::system::error_code &_error);
+
+
+ void send_uni_or_multicast_offerservice(
+ service_t _service, instance_t _instance, major_version_t _major,
+ minor_version_t _minor,
+ const std::shared_ptr<const serviceinfo> &_info,
+ bool _unicast_flag);
+ bool last_offer_shorter_half_offer_delay_ago();
+ void send_unicast_offer_service(
+ const std::shared_ptr<const serviceinfo> &_info, service_t _service,
+ instance_t _instance, major_version_t _major,
+ minor_version_t _minor);
+ void send_multicast_offer_service(
+ const std::shared_ptr<const serviceinfo>& _info, service_t _service,
+ instance_t _instance, major_version_t _major,
+ minor_version_t _minor);
+
+ bool check_source_address(const boost::asio::ip::address &its_source_address) const;
+
private:
boost::asio::io_service &io_;
service_discovery_host *host_;
@@ -233,9 +269,6 @@ private:
std::shared_ptr<serializer> serializer_;
std::shared_ptr<deserializer> deserializer_;
- std::shared_ptr<service_discovery_fsm> default_;
- std::map<std::string, std::shared_ptr<service_discovery_fsm> > additional_;
-
requests_t requested_;
std::mutex requested_mutex_;
std::map<service_t,
@@ -265,6 +298,25 @@ private:
std::chrono::steady_clock::time_point next_subscription_expiration_;
uint32_t max_message_size_;
+
+ std::chrono::milliseconds initial_delay_;
+ std::chrono::milliseconds offer_debounce_time_;
+ std::chrono::milliseconds repetitions_base_delay_;
+ std::uint8_t repetitions_max_;
+ std::chrono::milliseconds cyclic_offer_delay_;
+ boost::asio::steady_timer offer_debounce_timer_;
+ // this map is used to collect offers while for offer debouncing
+ std::mutex collected_offers_mutex_;
+ services_t collected_offers_;
+
+ // this map contains the offers and their timers currently in repetition phase
+ std::mutex repetition_phase_timers_mutex_;
+ std::map<std::shared_ptr<boost::asio::steady_timer>,
+ services_t> repetition_phase_timers_;
+
+ boost::asio::steady_timer main_phase_timer_;
+
+ bool is_suspended_;
};
} // namespace sd
diff --git a/implementation/service_discovery/src/fsm_base.cpp b/implementation/service_discovery/src/fsm_base.cpp
deleted file mode 100644
index e3c234b..0000000
--- a/implementation/service_discovery/src/fsm_base.cpp
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright (C) 2014-2016 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/fsm_base.hpp"
-
-namespace vsomeip {
-namespace sd {
-
-fsm_base::fsm_base(boost::asio::io_service &_io)
- : timer_(_io), alt_timer_(_io) {
-}
-
-fsm_base::~fsm_base() {
-}
-
-void fsm_base::start_timer(uint32_t _milliseconds, bool _use_alt_timer) {
- if (_use_alt_timer) {
- alt_timer_.expires_from_now(std::chrono::milliseconds(_milliseconds));
- alt_timer_.async_wait(
- std::bind(&fsm_base::timer_expired, shared_from_this(),
- std::placeholders::_1, true));
- } else {
- timer_.expires_from_now(std::chrono::milliseconds(_milliseconds));
- timer_.async_wait(
- std::bind(&fsm_base::timer_expired, shared_from_this(),
- std::placeholders::_1, false));
- }
-}
-
-void fsm_base::stop_timer(bool _use_alt_timer) {
- if (_use_alt_timer) {
- alt_timer_.cancel();
- } else {
- timer_.cancel();
- }
-}
-
-uint32_t fsm_base::expired_from_now(bool _use_alt_timer) {
- if (_use_alt_timer) {
- return (uint32_t) std::chrono::duration_cast < std::chrono::milliseconds
- > (alt_timer_.expires_from_now()).count();
- } else {
- return (uint32_t) std::chrono::duration_cast < std::chrono::milliseconds
- > (timer_.expires_from_now()).count();
- }
-}
-
-} // namespace sd
-} // namespace vsomeip
diff --git a/implementation/service_discovery/src/service_discovery_fsm.cpp b/implementation/service_discovery/src/service_discovery_fsm.cpp
deleted file mode 100644
index ba1bd18..0000000
--- a/implementation/service_discovery/src/service_discovery_fsm.cpp
+++ /dev/null
@@ -1,416 +0,0 @@
-// Copyright (C) 2014-2016 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 <boost/random/mersenne_twister.hpp>
-#include <boost/random/uniform_int_distribution.hpp>
-
-#include "../include/defines.hpp"
-#include "../include/service_discovery.hpp"
-#include "../include/service_discovery_fsm.hpp"
-#include "../../routing/include/serviceinfo.hpp"
-
-#include "../../configuration/include/configuration.hpp"
-#include "../../logging/include/logger.hpp"
-
-namespace vsomeip {
-namespace sd {
-
-///////////////////////////////////////////////////////////////////////////////
-// Machine
-///////////////////////////////////////////////////////////////////////////////
-namespace _sd {
-
-fsm::fsm(boost::asio::io_service &_io)
- : fsm_base(_io), is_up_(true) {
-}
-
-fsm::~fsm() {
-}
-
-void fsm::set_fsm(std::shared_ptr<service_discovery_fsm> _fsm) {
- fsm_ = _fsm;
-}
-
-void fsm::timer_expired(const boost::system::error_code &_error,
- bool _use_alt_timeout) {
- if (!_error) {
- std::shared_ptr<service_discovery_fsm> its_fsm = fsm_.lock();
- if (its_fsm) {
- if (_use_alt_timeout) {
- its_fsm->process(ev_alt_timeout());
- } else {
- its_fsm->process(ev_timeout());
- }
- }
- }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// State "Inactive"
-///////////////////////////////////////////////////////////////////////////////
-inactive::inactive(my_context context)
- : sc::state<inactive, fsm>(context) {
- std::shared_ptr < service_discovery_fsm > fsm =
- outermost_context().fsm_.lock();
- if (fsm) {
- VSOMEIP_TRACE << "sd::inactive";
- outermost_context().run_ = 0;
- }
-}
-
-sc::result inactive::react(const ev_none &_event) {
- (void)_event;
-
- if (outermost_context().is_up_) {
- return transit<active>();
- }
-
- return discard_event();
-}
-
-sc::result inactive::react(const ev_status_change &_event) {
- (void)_event;
-
- outermost_context().is_up_ = _event.is_up_;
- if (outermost_context().is_up_) {
- return transit<active>();
- }
-
- return discard_event();
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// State "Active"
-///////////////////////////////////////////////////////////////////////////////
-active::active(my_context _context)
- : sc::state<active, fsm, initial>(_context) {
- std::shared_ptr < service_discovery_fsm > fsm =
- outermost_context().fsm_.lock();
- if (fsm) {
- VSOMEIP_TRACE << "sd::active";
- }
-}
-
-active::~active() {
-}
-
-sc::result active::react(const ev_status_change &_event) {
- (void)_event;
-
- outermost_context().stop_timer();
- outermost_context().is_up_ = _event.is_up_;
- if (!outermost_context().is_up_)
- return transit<inactive>();
-
- return forward_event();
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// State "Active.Initial"
-///////////////////////////////////////////////////////////////////////////////
-initial::initial(my_context _context)
- : sc::state<initial, active>(_context) {
- std::shared_ptr < service_discovery_fsm > fsm =
- outermost_context().fsm_.lock();
- if (fsm) {
- VSOMEIP_TRACE << "sd::active.initial";
- outermost_context().start_timer(outermost_context().initial_delay_);
- }
-}
-
-sc::result initial::react(const ev_timeout &_event) {
- (void)_event;
- VSOMEIP_TRACE << "sd::active.initial.react";
- std::shared_ptr < service_discovery_fsm > fsm =
- outermost_context().fsm_.lock();
- if (fsm) {
- (void)fsm->send(false, false);
- }
- return transit<repeat>();
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// State "Active.Repeat"
-///////////////////////////////////////////////////////////////////////////////
-repeat::repeat(my_context _context)
- : sc::state<repeat, active>(_context) {
- std::shared_ptr < service_discovery_fsm > fsm =
- outermost_context().fsm_.lock();
- if (fsm) {
- VSOMEIP_TRACE << "sd::active.repeat";
- uint32_t its_timeout = (outermost_context().repetitions_base_delay_
- << outermost_context().run_);
- outermost_context().run_++;
- (void)fsm->send(false);
- outermost_context().start_timer(its_timeout);
- }
-}
-
-sc::result repeat::react(const ev_timeout &_event) {
- (void)_event;
- if (outermost_context().run_ < outermost_context().repetitions_max_) {
- return transit<repeat>();
- }
- return transit<main>();
-}
-
-sc::result repeat::react(const ev_find_service &_event) {
- std::shared_ptr < service_discovery_fsm > fsm =
- outermost_context().fsm_.lock();
- // Answer Find Service messages with unicast offer in repetition phase
- if (fsm) {
- VSOMEIP_TRACE << "sd::active.repeat.react.find";
- fsm->send_unicast_offer_service(_event.info_, _event.service_, _event.instance_,
- _event.major_, _event.minor_);
- }
- return forward_event();
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// State "Active.Main"
-///////////////////////////////////////////////////////////////////////////////
-main::main(my_context _context)
- : sc::state<main, active, mpl::list<offer, find> >(_context) {
- VSOMEIP_TRACE << "sd::active.main";
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// State "Active.Main.Offer"
-///////////////////////////////////////////////////////////////////////////////
-offer::offer(my_context _context)
- : sc::state<offer, main::orthogonal<0> >(_context) {
- std::shared_ptr < service_discovery_fsm > fsm =
- outermost_context().fsm_.lock();
- if (fsm) {
- VSOMEIP_TRACE << "sd::active.main.offer";
- outermost_context().start_timer(
- outermost_context().cyclic_offer_delay_);
- (void)fsm->send(true);
- }
-}
-
-sc::result offer::react(const ev_timeout &_event) {
- (void)_event;
- return transit<offer>();
-}
-
-sc::result offer::react(const ev_find_service &_event) {
- VSOMEIP_TRACE << "sd::active.main.react.find";
- std::shared_ptr < service_discovery_fsm > fsm =
- outermost_context().fsm_.lock();
- if (fsm) {
- if(_event.unicast_flag_) { //SIP_SD_826
- if( !fsm->check_is_multicast_offer()) { // SIP_SD_89
- fsm->send_unicast_offer_service(_event.info_, _event.service_, _event.instance_,
- _event.major_, _event.minor_);
- } else { // SIP_SD_90
- fsm->send_multicast_offer_service(_event.info_, _event.service_, _event.instance_,
- _event.major_, _event.minor_);
- }
- } else { // SIP_SD_824
- fsm->send_unicast_offer_service(_event.info_, _event.service_, _event.instance_,
- _event.major_, _event.minor_);
- }
- }
- return forward_event();
-}
-
-sc::result offer::react(const ev_offer_change &_event) {
- (void)_event;
- return transit<offer>();
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// State "Active.Announce.Main.Find"
-///////////////////////////////////////////////////////////////////////////////
-find::find(my_context _context)
- : sc::state<find, main::orthogonal<1>, idle>(_context) {
- VSOMEIP_TRACE << "sd::active.main.find";
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// State "Active.Announce.Idle"
-///////////////////////////////////////////////////////////////////////////////
-idle::idle(my_context _context)
- : sc::state<idle, find>(_context) {
- VSOMEIP_TRACE << "sd::active.main.find.idle";
- context<find>().run_ = 0;
-}
-
-sc::result idle::react(const ev_request_service &_event) {
- (void)_event;
- return transit<send>();
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// State "Active.Announce.Main.Find.Send"
-///////////////////////////////////////////////////////////////////////////////
-send::send(my_context _context)
- : sc::state<send, find>(_context) {
- std::shared_ptr < service_discovery_fsm > fsm =
- outermost_context().fsm_.lock();
- if (fsm) {
- VSOMEIP_TRACE << "sd::active.main.find.send";
- if( context<find>().run_ == 0)
- {
- outermost_context().start_timer(outermost_context().initial_delay_, true);
- } else if ( context<find>().run_ < fsm->get_repetition_max() + 1 ) {
- // Increment to the maximum run value (which is repetition_max-1)
- // As new request might be added in the meantime, this will be
- // used to calculate the maximum cycle time.
- uint32_t its_timeout = (outermost_context().repetitions_base_delay_
- << context<find>().run_);
- outermost_context().start_timer(its_timeout, true);
- }
- else {
- post_event(ev_none());
- }
- } else {
- post_event(ev_none());
- }
-}
-
-sc::result send::react(const ev_alt_timeout &_event) {
- (void)_event;
- std::shared_ptr < service_discovery_fsm > fsm =
- outermost_context().fsm_.lock();
- if (fsm) {
- VSOMEIP_TRACE << "sd::active.main.find.initial";
- context<find>().run_++;
- (void)fsm->send(true, true);
- }
- return transit<send>();
-}
-
-sc::result send::react(const ev_none &_event) {
- (void)_event;
- return transit<idle>();
-}
-
-} // namespace _sd
-
-///////////////////////////////////////////////////////////////////////////////
-// Interface
-///////////////////////////////////////////////////////////////////////////////
-service_discovery_fsm::service_discovery_fsm(
- std::shared_ptr<service_discovery> _discovery)
- : discovery_(_discovery), fsm_(
- std::make_shared < _sd::fsm > (_discovery->get_io())) {
- std::shared_ptr < service_discovery > discovery = discovery_.lock();
- if (discovery) {
- std::shared_ptr < configuration > its_configuration =
- discovery->get_configuration();
-
- int32_t its_initial_delay_min
- = its_configuration->get_sd_initial_delay_min();
- if (its_initial_delay_min < 0)
- its_initial_delay_min = VSOMEIP_SD_DEFAULT_INITIAL_DELAY_MIN;
-
- int32_t its_initial_delay_max
- = its_configuration->get_sd_initial_delay_max();
- if (its_initial_delay_max <= 0)
- its_initial_delay_max = VSOMEIP_SD_DEFAULT_INITIAL_DELAY_MAX;
-
- if (its_initial_delay_min > its_initial_delay_max) {
- int32_t tmp_initial_delay = its_initial_delay_min;
- its_initial_delay_min = its_initial_delay_max;
- its_initial_delay_max = tmp_initial_delay;
- }
-
- VSOMEIP_TRACE << "Inital delay [" << its_initial_delay_min << ", "
- << its_initial_delay_max << "]";
-
- boost::random::mt19937 its_generator;
- boost::random::uniform_int_distribution<> its_distribution(
- its_initial_delay_min, its_initial_delay_max);
- fsm_->initial_delay_ = its_distribution(its_generator);
-
- fsm_->repetitions_base_delay_
- = its_configuration->get_sd_repetitions_base_delay();
- if (fsm_->repetitions_base_delay_ <= 0)
- fsm_->repetitions_base_delay_
- = VSOMEIP_SD_DEFAULT_REPETITIONS_BASE_DELAY;
- fsm_->repetitions_max_
- = its_configuration->get_sd_repetitions_max();
- if (fsm_->repetitions_max_ <= 0)
- fsm_->repetitions_max_ = VSOMEIP_SD_DEFAULT_REPETITIONS_MAX;
-
- fsm_->cyclic_offer_delay_
- = its_configuration->get_sd_cyclic_offer_delay();
- if (fsm_->cyclic_offer_delay_ <= 0)
- fsm_->cyclic_offer_delay_ = VSOMEIP_SD_DEFAULT_CYCLIC_OFFER_DELAY;
-
- VSOMEIP_INFO << "SD configuration [" << std::dec << fsm_->initial_delay_ << ":"
- << std::dec << fsm_->repetitions_base_delay_ << ":"
- << std::dec << (int) fsm_->repetitions_max_ << ":"
- << std::dec << fsm_->cyclic_offer_delay_ << "]";
- } else {
- VSOMEIP_ERROR << "SD initialization failed";
- }
-}
-
-void service_discovery_fsm::start() {
- fsm_->set_fsm(shared_from_this());
- fsm_->initiate();
-}
-
-void service_discovery_fsm::stop() {
-}
-
-bool service_discovery_fsm::send(bool _is_announcing, bool _is_find) {
- std::shared_ptr < service_discovery > discovery = discovery_.lock();
- if (discovery) {
- return discovery->send(_is_announcing, _is_find);
- }
- return false;
-}
-
-void service_discovery_fsm::send_unicast_offer_service(
- const std::shared_ptr<const serviceinfo> &_info,
- service_t _service, instance_t _instance,
- major_version_t _major,
- minor_version_t _minor) {
- std::shared_ptr < service_discovery > discovery = discovery_.lock();
- if (discovery) {
- discovery->send_unicast_offer_service(_info, _service,
- _instance, _major, _minor );
- }
-}
-
-void service_discovery_fsm::send_multicast_offer_service(
- const std::shared_ptr<const serviceinfo> &_info, service_t _service,
- instance_t _instance, major_version_t _major, minor_version_t _minor) {
- std::shared_ptr < service_discovery > discovery = discovery_.lock();
- if (discovery) {
- discovery->send_multicast_offer_service(_info, _service,
- _instance, _major, _minor );
- }
-}
-
-std::chrono::milliseconds service_discovery_fsm::get_elapsed_offer_timer() {
- //get remaining time to next offer since last offer
- std::chrono::milliseconds remaining =
- std::chrono::milliseconds(fsm_->expired_from_now(false));
-
- if( std::chrono::milliseconds(0) > remaining) {
- remaining = std::chrono::milliseconds(fsm_->cyclic_offer_delay_);
- }
- return std::chrono::milliseconds(fsm_->cyclic_offer_delay_) - remaining;
-}
-
-bool service_discovery_fsm::check_is_multicast_offer() {
- bool is_multicast(false);
- std::chrono::milliseconds elapsed_ = get_elapsed_offer_timer();
- uint32_t half_cyclic_offer_delay_ = fsm_->cyclic_offer_delay_ / 2;
-
- if( elapsed_ >= std::chrono::milliseconds(half_cyclic_offer_delay_)) {
- // Response must be a multicast offer (SIP_SD_90)
- is_multicast = true;
- }
- return is_multicast;
-}
-
-} // namespace sd
-} // namespace vsomeip
diff --git a/implementation/service_discovery/src/service_discovery_impl.cpp b/implementation/service_discovery/src/service_discovery_impl.cpp
index 78af86b..94a03b4 100644
--- a/implementation/service_discovery/src/service_discovery_impl.cpp
+++ b/implementation/service_discovery/src/service_discovery_impl.cpp
@@ -5,6 +5,7 @@
#include <vsomeip/constants.hpp>
+#include <random>
#include <forward_list>
#include "../include/constants.hpp"
@@ -17,7 +18,6 @@
#include "../include/message_impl.hpp"
#include "../include/request.hpp"
#include "../include/runtime.hpp"
-#include "../include/service_discovery_fsm.hpp"
#include "../include/service_discovery_host.hpp"
#include "../include/service_discovery_impl.hpp"
#include "../include/serviceentry_impl.hpp"
@@ -39,11 +39,23 @@ namespace sd {
service_discovery_impl::service_discovery_impl(service_discovery_host *_host)
: io_(_host->get_io()),
host_(_host),
+ port_(VSOMEIP_SD_DEFAULT_PORT),
+ reliable_(false),
serializer_(std::make_shared<serializer>()),
deserializer_(std::make_shared<deserializer>()),
ttl_timer_(_host->get_io()),
smallest_ttl_(DEFAULT_TTL),
- subscription_expiration_timer_(_host->get_io()) {
+ ttl_(VSOMEIP_SD_DEFAULT_TTL),
+ subscription_expiration_timer_(_host->get_io()),
+ max_message_size_(VSOMEIP_MAX_UDP_SD_PAYLOAD),
+ initial_delay_(0),
+ offer_debounce_time_(VSOMEIP_SD_DEFAULT_OFFER_DEBOUNCE_TIME),
+ repetitions_base_delay_(VSOMEIP_SD_DEFAULT_REPETITIONS_BASE_DELAY),
+ repetitions_max_(VSOMEIP_SD_DEFAULT_REPETITIONS_MAX),
+ cyclic_offer_delay_(VSOMEIP_SD_DEFAULT_CYCLIC_OFFER_DELAY),
+ offer_debounce_timer_(_host->get_io()),
+ main_phase_timer_(_host->get_io()),
+ is_suspended_(false) {
std::chrono::seconds smallest_ttl(DEFAULT_TTL);
smallest_ttl_ = std::chrono::duration_cast<std::chrono::milliseconds>(smallest_ttl);
@@ -64,7 +76,6 @@ boost::asio::io_service & service_discovery_impl::get_io() {
void service_discovery_impl::init() {
runtime_ = runtime::get();
- default_ = std::make_shared<service_discovery_fsm>(shared_from_this());
std::shared_ptr < configuration > its_configuration =
host_->get_configuration();
@@ -86,24 +97,60 @@ void service_discovery_impl::init() {
its_configuration->get_sd_multicast(), port_, reliable_);
ttl_ = its_configuration->get_sd_ttl();
+
+ // generate random initial delay based on initial delay min and max
+ std::int32_t initial_delay_min =
+ its_configuration->get_sd_initial_delay_min();
+ if (initial_delay_min < 0) {
+ initial_delay_min = VSOMEIP_SD_DEFAULT_INITIAL_DELAY_MIN;
+ }
+ std::int32_t initial_delay_max =
+ its_configuration->get_sd_initial_delay_max();
+ if (initial_delay_max < 0) {
+ initial_delay_max = VSOMEIP_SD_DEFAULT_INITIAL_DELAY_MAX;
+ }
+ if (initial_delay_min > initial_delay_max) {
+ const std::uint32_t tmp(initial_delay_min);
+ initial_delay_min = initial_delay_max;
+ initial_delay_max = tmp;
+ }
+
+ std::random_device r;
+ std::mt19937 e(r());
+ std::uniform_int_distribution<std::uint32_t> distribution(
+ initial_delay_min, initial_delay_max);
+ initial_delay_ = std::chrono::milliseconds(distribution(e));
+
+
+ repetitions_base_delay_ = std::chrono::milliseconds(
+ its_configuration->get_sd_repetitions_base_delay());
+ repetitions_max_ = its_configuration->get_sd_repetitions_max();
+ cyclic_offer_delay_ = std::chrono::milliseconds(
+ its_configuration->get_sd_cyclic_offer_delay());
+ offer_debounce_time_ = std::chrono::milliseconds(
+ its_configuration->get_sd_offer_debounce_time());
} else {
VSOMEIP_ERROR << "SD: no configuration found!";
}
}
void service_discovery_impl::start() {
- default_->start();
- for (auto &its_group : additional_) {
- its_group.second->start();
- }
-
- default_->process(ev_none());
- for (auto &its_group : additional_) {
- its_group.second->process(ev_none());
- }
+ is_suspended_ = false;
+ start_main_phase_timer();
+ start_offer_debounce_timer(true);
}
void service_discovery_impl::stop() {
+ boost::system::error_code ec;
+ is_suspended_ = true;
+ main_phase_timer_.cancel(ec);
+ offer_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);
+ }
+ }
}
void service_discovery_impl::request_service(service_t _service,
@@ -128,7 +175,7 @@ void service_discovery_impl::request_service(service_t _service,
}
}
if (is_new_request) {
- default_->process(ev_request_service());
+ send(false, true);
}
}
@@ -592,7 +639,7 @@ void service_discovery_impl::insert_find_entries(
for (auto its_instance : its_service.second) {
auto its_request = its_instance.second;
uint8_t its_sent_counter = its_request->get_sent_counter();
- if (its_sent_counter != default_->get_repetition_max() + 1) {
+ if (its_sent_counter != repetitions_max_ + 1) {
if (i >= _start) {
if (its_size + VSOMEIP_SOMEIP_SD_ENTRY_SIZE <= max_message_size_) {
std::shared_ptr < serviceentry_impl > its_entry =
@@ -625,15 +672,16 @@ void service_discovery_impl::insert_find_entries(
}
void service_discovery_impl::insert_offer_entries(
- std::shared_ptr<message_impl> &_message, services_t &_services,
- uint32_t &_start, uint32_t _size, bool &_done) {
+ std::shared_ptr<message_impl> &_message, const services_t &_services,
+ uint32_t &_start, uint32_t _size, bool &_done, bool _ignore_phase) {
uint32_t i = 0;
uint32_t its_size(_size);
- for (auto its_service : _services) {
- for (auto its_instance : its_service.second) {
+ for (const auto its_service : _services) {
+ for (const auto its_instance : its_service.second) {
// Only insert services with configured endpoint(s)
- if (its_instance.second->get_endpoint(false)
- || its_instance.second->get_endpoint(true)) {
+ 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)) {
@@ -673,14 +721,14 @@ void service_discovery_impl::insert_subscription(
std::shared_ptr < endpoint > its_endpoint;
if (_insert_reliable) {
its_endpoint = _subscription->get_endpoint(true);
- if (its_endpoint) {
+ if (its_endpoint && its_endpoint->get_local_port()) {
insert_option(_message, its_entry, unicast_,
its_endpoint->get_local_port(), true);
}
}
if (_insert_unreliable) {
its_endpoint = _subscription->get_endpoint(false);
- if (its_endpoint) {
+ if (its_endpoint && its_endpoint->get_local_port()) {
insert_option(_message, its_entry, unicast_,
its_endpoint->get_local_port(), false);
}
@@ -801,38 +849,12 @@ bool service_discovery_impl::send(bool _is_announcing, bool _is_find) {
if (!_is_find) {
services_t its_offers = host_->get_offered_services();
-
- uint32_t its_start(0);
- bool is_done(false);
- while (!is_done) {
- insert_offer_entries(its_message, its_offers, its_start, its_remaining, is_done);
- if (!is_done) {
- its_remaining = max_message_size_;
- its_message = its_runtime->create_message();
- its_messages.push_back(its_message);
- }
- }
+ fill_message_with_offer_entries(its_runtime, its_message,
+ its_messages, its_offers, false);
}
// Serialize and send
- bool has_sent(false);
- {
- // lock serialize mutex here as well even if we don't use the
- // serializer as it's used to guard access to the sessions_sent_ map
- std::lock_guard<std::mutex> its_lock(serialize_mutex_);
- for (auto m : its_messages) {
- if (m->get_entries().size() > 0) {
- std::pair<session_t, bool> its_session = get_session(unicast_);
- m->set_session(its_session.first);
- m->set_reboot_flag(its_session.second);
- if (host_->send(VSOMEIP_SD_CLIENT, m, true)) {
- increment_session(unicast_);
- }
- has_sent = true;
- }
- }
- }
- return has_sent;
+ return serialize_and_send_messages(its_messages);
}
return false;
}
@@ -848,10 +870,17 @@ void service_discovery_impl::on_message(const byte_t *_data, length_t _length,
msg << std::hex << std::setw(2) << std::setfill('0') << (int)_data[i] << " ";
VSOMEIP_DEBUG << msg.str();
#endif
+ if(is_suspended_) {
+ return;
+ }
deserializer_->set_data(_data, _length);
std::shared_ptr < message_impl
> its_message(deserializer_->deserialize_sd_message());
if (its_message) {
+ // ignore all SD messages with source address equal to node's unicast address
+ if (!check_source_address(_sender)) {
+ return;
+ }
// ignore all messages which are sent with invalid header fields
if(!check_static_header_fields(its_message)) {
return;
@@ -909,10 +938,6 @@ void service_discovery_impl::on_message(const byte_t *_data, length_t _length,
}
}
-void service_discovery_impl::on_offer_change() {
- default_->process(ev_offer_change());
-}
-
// Entry processing
void service_discovery_impl::process_serviceentry(
std::shared_ptr<serviceentry_impl> &_entry,
@@ -1011,9 +1036,9 @@ void service_discovery_impl::process_serviceentry(
} else {
std::shared_ptr<request> its_request = find_request(its_service, its_instance);
- if (its_request)
- its_request->set_sent_counter((uint8_t) (default_->get_repetition_max() + 1));
-
+ if (its_request) {
+ 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),
@@ -1034,7 +1059,7 @@ void service_discovery_impl::process_offerservice_serviceentry(
std::shared_ptr<request> its_request = find_request(_service, _instance);
if (its_request)
- its_request->set_sent_counter((uint8_t) (default_->get_repetition_max() + 1));
+ its_request->set_sent_counter(std::uint8_t(repetitions_max_ + 1));
smallest_ttl_ = host_->add_routing_info(_service, _instance,
_major, _minor, _ttl,
@@ -1142,18 +1167,14 @@ void service_discovery_impl::process_findservice_serviceentry(
auto found_instance = found_service->second.find(_instance);
if (found_instance != found_service->second.end()) {
std::shared_ptr<serviceinfo> its_info = found_instance->second;
-
- ev_find_service find_event(its_info, _service,
- _instance, _major, _minor, _unicast_flag );
- default_->process(find_event);
+ send_uni_or_multicast_offerservice(_service, _instance, _major, _minor, its_info,
+ _unicast_flag);
}
} else {
// send back all available instances
for (const auto &found_instance : found_service->second) {
-
- ev_find_service find_event(found_instance.second, _service,
- _instance, _major, _minor, _unicast_flag );
- default_->process(find_event);
+ send_uni_or_multicast_offerservice(_service, _instance, _major, _minor,
+ found_instance.second, _unicast_flag);
}
}
}
@@ -1174,8 +1195,14 @@ void service_discovery_impl::send_unicast_offer_service(
uint32_t its_size(max_message_size_);
insert_offer_service(its_message, _service, _instance, _info,
its_size);
-
- serialize_and_send(its_message, get_current_remote_address());
+ const boost::asio::ip::address its_address(get_current_remote_address());
+ if (its_address.is_unspecified()) {
+ VSOMEIP_ERROR << "service_discovery_impl::"
+ "send_unicast_offer_service current remote address "
+ "is unspecified, won't send offer.";
+ } else {
+ serialize_and_send(its_message, its_address);
+ }
}
}
}
@@ -1921,11 +1948,21 @@ void service_discovery_impl::check_ttl(const boost::system::error_code &_error)
}
boost::asio::ip::address service_discovery_impl::get_current_remote_address() const {
+ boost::asio::ip::address its_address;
if (reliable_) {
- return std::static_pointer_cast<tcp_server_endpoint_impl>(endpoint_)->get_remote().address();
+ auto endpoint = std::dynamic_pointer_cast<tcp_server_endpoint_impl>(endpoint_);
+ if (endpoint && !endpoint->get_remote_address(its_address)) {
+ VSOMEIP_ERROR << "service_discovery_impl::get_current_remote_address: "
+ "couldn't determine remote address (reliable)";
+ }
} else {
- return std::static_pointer_cast<udp_server_endpoint_impl>(endpoint_)->get_remote().address();
+ auto endpoint = std::dynamic_pointer_cast<udp_server_endpoint_impl>(endpoint_);
+ if (endpoint && !endpoint->get_remote_address(its_address)) {
+ VSOMEIP_ERROR << "service_discovery_impl::get_current_remote_address: "
+ "couldn't determine remote address (unreliable)";
+ }
}
+ return its_address;
}
bool service_discovery_impl::check_static_header_fields(
@@ -2089,5 +2126,381 @@ bool service_discovery_impl::check_ipv4_address(
return is_valid;
}
+void service_discovery_impl::offer_service(service_t _service,
+ instance_t _instance,
+ std::shared_ptr<serviceinfo> _info) {
+ std::lock_guard<std::mutex> its_lock(collected_offers_mutex_);
+ // check if offer is in map
+ bool found(false);
+ const auto its_service = collected_offers_.find(_service);
+ if (its_service != collected_offers_.end()) {
+ const auto its_instance = its_service->second.find(_instance);
+ if (its_instance != its_service->second.end()) {
+ found = true;
+ }
+ }
+ if (!found) {
+ collected_offers_[_service][_instance] = _info;
+ }
+}
+
+void service_discovery_impl::start_offer_debounce_timer(bool _first_start) {
+ boost::system::error_code ec;
+ if (_first_start) {
+ offer_debounce_timer_.expires_from_now(initial_delay_, ec);
+ } else {
+ offer_debounce_timer_.expires_from_now(offer_debounce_time_, ec);
+ }
+ if (ec) {
+ VSOMEIP_ERROR<< "service_discovery_impl::start_offer_debounce_timer "
+ "setting expiry time of timer failed: " << ec.message();
+ }
+ offer_debounce_timer_.async_wait(
+ std::bind(
+ &service_discovery_impl::on_offer_debounce_timer_expired,
+ this, std::placeholders::_1));
+}
+
+void service_discovery_impl::on_offer_debounce_timer_expired(
+ const boost::system::error_code &_error) {
+ if(_error) { // timer was canceled
+ return;
+ }
+
+ // copy the accumulated offers of the initial wait phase
+ services_t repetition_phase_offers;
+ bool new_offers(false);
+ {
+ std::lock_guard<std::mutex> its_lock(collected_offers_mutex_);
+ if (collected_offers_.size()) {
+ repetition_phase_offers = collected_offers_;
+ collected_offers_.clear();
+ new_offers = true;
+ }
+ }
+
+ if (!new_offers) {
+ start_offer_debounce_timer(false);
+ return;
+ }
+
+ // Sent out offers for the first time as initial wait phase ended
+ std::shared_ptr<runtime> its_runtime = runtime_.lock();
+ if (its_runtime) {
+ std::vector<std::shared_ptr<message_impl>> its_messages;
+ std::shared_ptr<message_impl> its_message =
+ its_runtime->create_message();
+ its_messages.push_back(its_message);
+ fill_message_with_offer_entries(its_runtime, its_message, its_messages,
+ repetition_phase_offers, true);
+
+ // Serialize and send
+ serialize_and_send_messages(its_messages);
+ }
+
+ std::chrono::milliseconds its_delay(0);
+ std::uint8_t its_repetitions(0);
+ if (repetitions_max_) {
+ // start timer for repetition phase the first time
+ // with 2^0 * repetitions_base_delay
+ its_delay = repetitions_base_delay_;
+ its_repetitions = 1;
+ } else {
+ // if repetitions_max is set to zero repetition phase is skipped,
+ // therefore wait one cyclic offer delay before entering main phase
+ its_delay = cyclic_offer_delay_;
+ its_repetitions = 0;
+ }
+
+ std::shared_ptr<boost::asio::steady_timer> its_timer = std::make_shared<
+ boost::asio::steady_timer>(host_->get_io());
+
+ {
+ std::lock_guard<std::mutex> its_lock(repetition_phase_timers_mutex_);
+ repetition_phase_timers_[its_timer] = repetition_phase_offers;
+ }
+
+ boost::system::error_code ec;
+ its_timer->expires_from_now(its_delay, ec);
+ if (ec) {
+ VSOMEIP_ERROR<< "service_discovery_impl::on_offer_debounce_timer_expired "
+ "setting expiry time of timer failed: " << ec.message();
+ }
+ its_timer->async_wait(
+ std::bind(
+ &service_discovery_impl::on_repetition_phase_timer_expired,
+ this, std::placeholders::_1, its_timer, its_repetitions,
+ its_delay.count()));
+ start_offer_debounce_timer(false);
+}
+
+void service_discovery_impl::on_repetition_phase_timer_expired(
+ const boost::system::error_code &_error,
+ std::shared_ptr<boost::asio::steady_timer> _timer,
+ std::uint8_t _repetition, std::uint32_t _last_delay) {
+ if (_error) {
+ return;
+ }
+ if (_repetition == 0) {
+ std::lock_guard<std::mutex> its_lock(repetition_phase_timers_mutex_);
+ // we waited one cyclic offer delay, the offers can now be sent in the
+ // main phase and the timer can be deleted
+ move_offers_into_main_phase(_timer);
+ } else {
+ std::lock_guard<std::mutex> its_lock(repetition_phase_timers_mutex_);
+ auto its_timer_pair = repetition_phase_timers_.find(_timer);
+ if (its_timer_pair != repetition_phase_timers_.end()) {
+ std::chrono::milliseconds new_delay(0);
+ std::uint8_t repetition(0);
+ if (_repetition <= repetitions_max_) {
+ // sent offers, double time to wait and start timer again.
+ std::shared_ptr<runtime> its_runtime = runtime_.lock();
+ if (its_runtime) {
+ std::vector<std::shared_ptr<message_impl>> its_messages;
+ std::shared_ptr<message_impl> its_message =
+ its_runtime->create_message();
+ its_messages.push_back(its_message);
+ fill_message_with_offer_entries(its_runtime, its_message,
+ its_messages, its_timer_pair->second, true);
+
+ // Serialize and send
+ serialize_and_send_messages(its_messages);
+ }
+ new_delay = std::chrono::milliseconds(_last_delay * 2);
+ repetition = ++_repetition;
+ } else {
+ // repetition phase is now over we have to sleep one cyclic
+ // offer delay before it's allowed to sent the offer again.
+ // If the last offer was sent shorter than half the
+ // configured cyclic_offer_delay_ago the offers are directly
+ // moved into the mainphase to avoid potentially sleeping twice
+ // the cyclic offer delay before moving the offers in to main
+ // phase
+ if (last_offer_shorter_half_offer_delay_ago()) {
+ move_offers_into_main_phase(_timer);
+ return;
+ } else {
+ new_delay = cyclic_offer_delay_;
+ repetition = 0;
+ }
+ }
+ boost::system::error_code ec;
+ its_timer_pair->first->expires_from_now(new_delay, ec);
+ if (ec) {
+ VSOMEIP_ERROR <<
+ "service_discovery_impl::on_repetition_phase_timer_expired "
+ "setting expiry time of timer failed: " << ec.message();
+ }
+ its_timer_pair->first->async_wait(
+ std::bind(
+ &service_discovery_impl::on_repetition_phase_timer_expired,
+ this, std::placeholders::_1, its_timer_pair->first,
+ repetition, new_delay.count()));
+ }
+ }
+}
+
+void service_discovery_impl::move_offers_into_main_phase(
+ const std::shared_ptr<boost::asio::steady_timer> &_timer) {
+ // HINT: make sure to lock the repetition_phase_timers_mutex_ before calling
+ // this function
+ // set flag on all serviceinfos bound to this timer
+ // that they will be included in the cyclic offers from now on
+ const auto its_timer = repetition_phase_timers_.find(_timer);
+ if (its_timer != repetition_phase_timers_.end()) {
+ for (const auto its_service : its_timer->second) {
+ for (const auto instance : its_service.second) {
+ instance.second->set_is_in_mainphase(true);
+ }
+ }
+ repetition_phase_timers_.erase(_timer);
+ }
+}
+
+void service_discovery_impl::fill_message_with_offer_entries(
+ std::shared_ptr<runtime> _runtime,
+ std::shared_ptr<message_impl> _message,
+ std::vector<std::shared_ptr<message_impl>> &_messages,
+ const services_t &_offers, bool _ignore_phase) {
+ uint32_t its_remaining(max_message_size_);
+ uint32_t its_start(0);
+ bool is_done(false);
+ while (!is_done) {
+ insert_offer_entries(_message, _offers, its_start, its_remaining,
+ is_done, _ignore_phase);
+ if (!is_done) {
+ its_remaining = max_message_size_;
+ _message = _runtime->create_message();
+ _messages.push_back(_message);
+ }
+ }
+}
+
+bool service_discovery_impl::serialize_and_send_messages(
+ const std::vector<std::shared_ptr<message_impl>> &_messages) {
+ bool has_sent(false);
+ // lock serialize mutex here as well even if we don't use the
+ // serializer as it's used to guard access to the sessions_sent_ map
+ std::lock_guard<std::mutex> its_lock(serialize_mutex_);
+ for (const auto m : _messages) {
+ if (m->get_entries().size() > 0) {
+ std::pair<session_t, bool> its_session = get_session(unicast_);
+ m->set_session(its_session.first);
+ m->set_reboot_flag(its_session.second);
+ if (host_->send(VSOMEIP_SD_CLIENT, m, true)) {
+ increment_session(unicast_);
+ }
+ has_sent = true;
+ }
+ }
+ return has_sent;
+}
+
+void service_discovery_impl::stop_offer_service(
+ service_t _service, instance_t _instance,
+ std::shared_ptr<serviceinfo> _info) {
+ bool stop_offer_required(false);
+ // delete from initial phase offers
+ {
+ std::lock_guard<std::mutex> its_lock(collected_offers_mutex_);
+ if (collected_offers_.size()) {
+ auto its_service = collected_offers_.find(_service);
+ if (its_service != collected_offers_.end()) {
+ auto its_instance = its_service->second.find(_instance);
+ if (its_instance != its_service->second.end()) {
+ if (its_instance->second == _info) {
+ its_service->second.erase(its_instance);
+
+ if (!collected_offers_[its_service->first].size()) {
+ collected_offers_.erase(its_service);
+ }
+ }
+ }
+ }
+ }
+ // no need to sent out a stop offer message here as all services
+ // instances contained in the collected offers weren't broadcasted yet
+ }
+
+ // delete from repetition phase offers
+ {
+ std::lock_guard<std::mutex> its_lock(repetition_phase_timers_mutex_);
+ for (auto rpt = repetition_phase_timers_.begin();
+ rpt != repetition_phase_timers_.end();) {
+ auto its_service = rpt->second.find(_service);
+ if (its_service != rpt->second.end()) {
+ auto its_instance = its_service->second.find(_instance);
+ if (its_instance != its_service->second.end()) {
+ if (its_instance->second == _info) {
+ its_service->second.erase(its_instance);
+ stop_offer_required = true;
+ if (!rpt->second[its_service->first].size()) {
+ rpt->second.erase(_service);
+ }
+ }
+ }
+ }
+ if (!rpt->second.size()) {
+ rpt = repetition_phase_timers_.erase(rpt);
+ } else {
+ ++rpt;
+ }
+ }
+ }
+ // sent stop offer
+ if(_info->is_in_mainphase() || stop_offer_required) {
+ send_stop_offer(_service, _instance, _info);
+ }
+}
+
+bool service_discovery_impl::send_stop_offer(
+ service_t _service, instance_t _instance,
+ std::shared_ptr<serviceinfo> _info) {
+ std::shared_ptr < runtime > its_runtime = runtime_.lock();
+ if (its_runtime) {
+ std::vector<std::shared_ptr<message_impl>> its_messages;
+ std::shared_ptr<message_impl> its_message;
+ its_message = its_runtime->create_message();
+ its_messages.push_back(its_message);
+
+ uint32_t its_size(max_message_size_);
+ insert_offer_service(its_message, _service, _instance, _info, its_size);
+
+ // Serialize and send
+ return serialize_and_send_messages(its_messages);
+ }
+ return false;
+}
+
+void service_discovery_impl::start_main_phase_timer() {
+ boost::system::error_code ec;
+ main_phase_timer_.expires_from_now(cyclic_offer_delay_);
+ if (ec) {
+ VSOMEIP_ERROR<< "service_discovery_impl::start_main_phase_timer "
+ "setting expiry time of timer failed: " << ec.message();
+ }
+ main_phase_timer_.async_wait(
+ std::bind(&service_discovery_impl::on_main_phase_timer_expired,
+ this, std::placeholders::_1));
+}
+
+void service_discovery_impl::on_main_phase_timer_expired(
+ const boost::system::error_code &_error) {
+ if (_error) {
+ return;
+ }
+ send(true, false);
+ start_main_phase_timer();
+}
+
+void service_discovery_impl::send_uni_or_multicast_offerservice(
+ service_t _service, instance_t _instance, major_version_t _major,
+ minor_version_t _minor, const std::shared_ptr<const serviceinfo> &_info,
+ bool _unicast_flag) {
+ if (_unicast_flag) { // SID_SD_826
+ if (last_offer_shorter_half_offer_delay_ago()) { // SIP_SD_89
+ send_unicast_offer_service(_info, _service, _instance, _major, _minor);
+ } else { // SIP_SD_90
+ send_multicast_offer_service(_info, _service, _instance, _major, _minor);
+ }
+ } else { // SID_SD_826
+ send_unicast_offer_service(_info, _service, _instance, _major, _minor);
+ }
+}
+
+bool service_discovery_impl::last_offer_shorter_half_offer_delay_ago() {
+ //get remaining time to next offer since last offer
+ std::chrono::milliseconds remaining = std::chrono::duration_cast<
+ std::chrono::milliseconds>(main_phase_timer_.expires_from_now());
+
+ if (std::chrono::milliseconds(0) > remaining) {
+ remaining = cyclic_offer_delay_;
+ }
+ const std::chrono::milliseconds half_cyclic_offer_delay =
+ cyclic_offer_delay_ / 2;
+
+ return remaining > half_cyclic_offer_delay;
+}
+
+bool service_discovery_impl::check_source_address(
+ const boost::asio::ip::address &its_source_address) const {
+ bool is_valid = true;
+ std::shared_ptr<configuration> its_configuration =
+ host_->get_configuration();
+
+ if(its_configuration) {
+ boost::asio::ip::address its_unicast_address =
+ its_configuration.get()->get_unicast_address();
+ // check if source address is same as nodes unicast address
+ if(its_unicast_address
+ == its_source_address) {
+ VSOMEIP_ERROR << "Source address of message is same as DUT's unicast address! : "
+ << its_source_address.to_string();
+ is_valid = false;
+ }
+ }
+ return is_valid;
+}
+
} // namespace sd
} // namespace vsomeip
diff --git a/implementation/utility/include/utility.hpp b/implementation/utility/include/utility.hpp
index 0831bdb..7e69401 100644
--- a/implementation/utility/include/utility.hpp
+++ b/implementation/utility/include/utility.hpp
@@ -15,6 +15,8 @@
namespace vsomeip {
+class configuration;
+
class utility {
public:
static void * load_library(const std::string &_path,
@@ -70,21 +72,21 @@ public:
static uint32_t get_payload_size(const byte_t *_data, uint32_t _size);
static bool exists(const std::string &_path);
- static bool is_file(const std::string &_path);
- static bool is_folder(const std::string &_path);
+ static bool VSOMEIP_IMPORT_EXPORT is_file(const std::string &_path);
+ static bool VSOMEIP_IMPORT_EXPORT is_folder(const std::string &_path);
static CriticalSection its_local_configuration_mutex__;
static struct configuration_data_t *the_configuration_data__;
- static bool auto_configuration_init();
+ static bool auto_configuration_init(const std::shared_ptr<configuration> &_config);
static void auto_configuration_exit(client_t _client);
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 client_t request_client_id(const std::string &_name,
- client_t _client);
+ 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);
static inline bool is_valid_message_type(message_type_e _type) {
diff --git a/implementation/utility/src/utility.cpp b/implementation/utility/src/utility.cpp
index 62dcf59..d91dd56 100644
--- a/implementation/utility/src/utility.cpp
+++ b/implementation/utility/src/utility.cpp
@@ -9,6 +9,7 @@
#include <dlfcn.h>
#include <sys/mman.h>
#include <thread>
+ #include <sstream>
#endif
#include <sys/stat.h>
@@ -129,9 +130,8 @@ static HANDLE configuration_data_mutex(INVALID_HANDLE_VALUE);
static HANDLE its_descriptor(INVALID_HANDLE_VALUE);
#endif
-bool utility::auto_configuration_init() {
+bool utility::auto_configuration_init(const std::shared_ptr<configuration> &_config) {
std::unique_lock<CriticalSection> its_lock(its_local_configuration_mutex__);
- std::shared_ptr<configuration> its_config(configuration::get());
#ifdef WIN32
if (its_configuration_refs__ > 0) {
@@ -212,7 +212,7 @@ bool utility::auto_configuration_init() {
= reinterpret_cast<configuration_data_t *>(its_segment);
the_configuration_data__->client_base_
- = static_cast<unsigned short>(its_config->get_diagnosis_address() << 8);
+ = static_cast<unsigned short>(_config->get_diagnosis_address() << 8);
the_configuration_data__->used_client_ids_[0]
= the_configuration_data__->client_base_;
the_configuration_data__->client_base_++;
@@ -220,7 +220,7 @@ bool utility::auto_configuration_init() {
the_configuration_data__->max_assigned_client_id_low_byte_ = 0x00;
the_configuration_data__->routing_manager_host_ = 0x0000;
- std::string its_name = its_config->get_routing_host();
+ std::string its_name = _config->get_routing_host();
if (its_name == "")
the_configuration_data__->routing_manager_host_ = the_configuration_data__->client_base_;
@@ -252,9 +252,9 @@ bool utility::auto_configuration_init() {
}
}
#else
- const mode_t previous_mask(::umask(static_cast<mode_t>(its_config->get_umask())));
+ 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,
- static_cast<mode_t>(its_config->get_permissions_shm()));
+ static_cast<mode_t>(_config->get_permissions_shm()));
::umask(previous_mask);
if (its_descriptor > -1) {
if (-1 == ftruncate(its_descriptor, sizeof(configuration_data_t))) {
@@ -292,7 +292,7 @@ bool utility::auto_configuration_init() {
}
the_configuration_data__->client_base_
- = static_cast<unsigned short>(its_config->get_diagnosis_address() << 8);
+ = static_cast<unsigned short>(_config->get_diagnosis_address() << 8);
the_configuration_data__->used_client_ids_[0]
= the_configuration_data__->client_base_;
the_configuration_data__->client_base_++;
@@ -300,7 +300,7 @@ bool utility::auto_configuration_init() {
the_configuration_data__->max_assigned_client_id_low_byte_ = 0x00;
the_configuration_data__->routing_manager_host_ = 0x0000;
- std::string its_name = its_config->get_routing_host();
+ std::string its_name = _config->get_routing_host();
if (its_name == "")
the_configuration_data__->routing_manager_host_ = the_configuration_data__->client_base_;
@@ -321,9 +321,9 @@ bool utility::auto_configuration_init() {
}
}
} else if (errno == EEXIST) {
- const mode_t previous_mask(::umask(static_cast<mode_t>(its_config->get_umask())));
+ const mode_t previous_mask(::umask(static_cast<mode_t>(_config->get_umask())));
its_descriptor = shm_open(VSOMEIP_SHM_NAME, O_RDWR,
- static_cast<mode_t>(its_config->get_permissions_shm()));
+ static_cast<mode_t>(_config->get_permissions_shm()));
::umask(previous_mask);
if (-1 == its_descriptor) {
VSOMEIP_ERROR << "utility::auto_configuration_init: "
@@ -437,10 +437,22 @@ bool utility::is_used_client_id(client_t _client) {
return true;
}
}
+#ifndef WIN32
+ std::stringstream its_client;
+ its_client << VSOMEIP_BASE_PATH << 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"
+ << std::hex << _client << " can't be reused!";
+ return true;
+ }
+
+ }
+#endif
return false;
}
-client_t utility::request_client_id(const std::string &_name, client_t _client) {
+client_t utility::request_client_id(const std::shared_ptr<configuration> &_config, const std::string &_name, client_t _client) {
std::unique_lock<CriticalSection> its_lock(its_local_configuration_mutex__);
if (the_configuration_data__ != nullptr) {
@@ -451,8 +463,7 @@ client_t utility::request_client_id(const std::string &_name, client_t _client)
#else
pthread_mutex_lock(&the_configuration_data__->mutex_);
#endif
- std::shared_ptr<configuration> its_config(configuration::get());
- const std::string its_name = its_config->get_routing_host();
+ 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) {
diff --git a/interface/vsomeip/application.hpp b/interface/vsomeip/application.hpp
index 64f60ce..2b53666 100644
--- a/interface/vsomeip/application.hpp
+++ b/interface/vsomeip/application.hpp
@@ -147,6 +147,16 @@ public:
virtual bool are_available(available_t &_available,
service_t _service = ANY_SERVICE, instance_t _instance = ANY_INSTANCE,
major_version_t _major = ANY_MAJOR, minor_version_t _minor = ANY_MINOR) const = 0;
+
+ virtual void notify(service_t _service, instance_t _instance,
+ event_t _event, std::shared_ptr<payload> _payload,
+ bool _force, bool _flush) const = 0;
+
+ virtual void notify_one(service_t _service, instance_t _instance,
+ event_t _event, std::shared_ptr<payload> _payload,
+ client_t _client, bool _force, bool _flush) const = 0;
+
+ virtual void set_routing_state(routing_state_e _routing_state) = 0;
};
} // namespace vsomeip
diff --git a/interface/vsomeip/enumeration_types.hpp b/interface/vsomeip/enumeration_types.hpp
index b9b0a50..1b5ef51 100644
--- a/interface/vsomeip/enumeration_types.hpp
+++ b/interface/vsomeip/enumeration_types.hpp
@@ -54,6 +54,14 @@ enum class subscription_type_e : uint8_t {
SU_RELIABLE = 0x04,
};
+enum class routing_state_e : uint8_t {
+ RS_RUNNING = 0x00,
+ RS_SUSPENDED = 0x01,
+ RS_RESUMED = 0x02,
+ RS_SHUTDOWN = 0x03,
+ RS_UNKNOWN = 0xFF
+};
+
} // namespace vsomeip
#endif // VSOMEIP_ENUMERATION_TYPES_HPP
diff --git a/interface/vsomeip/export.hpp b/interface/vsomeip/export.hpp
index 16b4d23..8fc3895 100644
--- a/interface/vsomeip/export.hpp
+++ b/interface/vsomeip/export.hpp
@@ -15,9 +15,16 @@
#else
#define VSOMEIP_IMPORT_EXPORT __declspec(dllimport)
#endif
+
+ #if VSOMEIP_DLL_COMPILATION_CONFIG
+ #define VSOMEIP_IMPORT_EXPORT_CONFIG __declspec(dllexport)
+ #else
+ #define VSOMEIP_IMPORT_EXPORT_CONFIG __declspec(dllimport)
+ #endif
#else
#define VSOMEIP_EXPORT
#define VSOMEIP_IMPORT_EXPORT
+ #define VSOMEIP_IMPORT_EXPORT_CONFIG
#endif
#endif
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 358154c..e84e1a4 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -73,6 +73,7 @@ if(NOT ${TESTS_BAT})
add_executable(${TEST_CONFIGURATION} configuration_tests/configuration-test.cpp)
target_link_libraries(${TEST_CONFIGURATION}
vsomeip
+ vsomeip-cfg
${Boost_LIBRARIES}
${DL_LIBRARY}
)
@@ -105,25 +106,56 @@ if(NOT ${TESTS_BAT})
${TEST_LINK_LIBRARIES}
)
+ set(TEST_APPLICATION_SINGLE_PROCESS_NAME ${TEST_APPLICATION}_single_process)
+ add_executable(${TEST_APPLICATION_SINGLE_PROCESS_NAME} application_tests/${TEST_APPLICATION_SINGLE_PROCESS_NAME}.cpp)
+ target_link_libraries(${TEST_APPLICATION_SINGLE_PROCESS_NAME}
+ vsomeip
+ ${Boost_LIBRARIES}
+ ${DL_LIBRARY}
+ ${TEST_LINK_LIBRARIES}
+ )
+
+ set(TEST_APPLICATION_SINGLE_PROCESS_CONFIGURATION_FILE ${TEST_APPLICATION}_single_process.json)
+ copy_to_builddir(${PROJECT_SOURCE_DIR}/test/application_tests/${TEST_APPLICATION_SINGLE_PROCESS_CONFIGURATION_FILE}
+ ${PROJECT_BINARY_DIR}/test/${TEST_APPLICATION_SINGLE_PROCESS_CONFIGURATION_FILE}
+ ${TEST_APPLICATION}_single_process
+ )
+
set(TEST_APPLICATION_CONFIGURATION_FILE ${TEST_APPLICATION}.json)
+ configure_file(
+ ${PROJECT_SOURCE_DIR}/test/application_tests/conf/${TEST_APPLICATION_CONFIGURATION_FILE}.in
+ ${PROJECT_SOURCE_DIR}/test/application_tests/${TEST_APPLICATION_CONFIGURATION_FILE}
+ @ONLY)
copy_to_builddir(${PROJECT_SOURCE_DIR}/test/application_tests/${TEST_APPLICATION_CONFIGURATION_FILE}
${PROJECT_BINARY_DIR}/test/${TEST_APPLICATION_CONFIGURATION_FILE}
${TEST_APPLICATION}
)
set(TEST_APPLICATION_CONFIGURATION_FILE_DAEMON ${TEST_APPLICATION}_daemon.json)
+ configure_file(
+ ${PROJECT_SOURCE_DIR}/test/application_tests/conf/${TEST_APPLICATION_CONFIGURATION_FILE_DAEMON}.in
+ ${PROJECT_SOURCE_DIR}/test/application_tests/${TEST_APPLICATION_CONFIGURATION_FILE_DAEMON}
+ @ONLY)
copy_to_builddir(${PROJECT_SOURCE_DIR}/test/application_tests/${TEST_APPLICATION_CONFIGURATION_FILE_DAEMON}
${PROJECT_BINARY_DIR}/test/${TEST_APPLICATION_CONFIGURATION_FILE_DAEMON}
${TEST_APPLICATION}
)
set(TEST_APPLICATION_NO_DISPATCH_CONFIGURATION_FILE ${TEST_APPLICATION}_no_dispatch_threads.json)
+ configure_file(
+ ${PROJECT_SOURCE_DIR}/test/application_tests/conf/${TEST_APPLICATION_NO_DISPATCH_CONFIGURATION_FILE}.in
+ ${PROJECT_SOURCE_DIR}/test/application_tests/${TEST_APPLICATION_NO_DISPATCH_CONFIGURATION_FILE}
+ @ONLY)
copy_to_builddir(${PROJECT_SOURCE_DIR}/test/application_tests/${TEST_APPLICATION_NO_DISPATCH_CONFIGURATION_FILE}
${PROJECT_BINARY_DIR}/test/${TEST_APPLICATION_NO_DISPATCH_CONFIGURATION_FILE}
${TEST_APPLICATION}
)
set(TEST_APPLICATION_NO_DISPATCH_CONFIGURATION_FILE_DAEMON ${TEST_APPLICATION}_no_dispatch_threads_daemon.json)
+ configure_file(
+ ${PROJECT_SOURCE_DIR}/test/application_tests/conf/${TEST_APPLICATION_NO_DISPATCH_CONFIGURATION_FILE_DAEMON}.in
+ ${PROJECT_SOURCE_DIR}/test/application_tests/${TEST_APPLICATION_NO_DISPATCH_CONFIGURATION_FILE_DAEMON}
+ @ONLY)
copy_to_builddir(${PROJECT_SOURCE_DIR}/test/application_tests/${TEST_APPLICATION_NO_DISPATCH_CONFIGURATION_FILE_DAEMON}
${PROJECT_BINARY_DIR}/test/${TEST_APPLICATION_NO_DISPATCH_CONFIGURATION_FILE_DAEMON}
${TEST_APPLICATION}
@@ -134,6 +166,12 @@ if(NOT ${TESTS_BAT})
${PROJECT_BINARY_DIR}/test/${TEST_APPLICATION_STARTER}
${TEST_APPLICATION}
)
+
+ set(TEST_APPLICATION_SINGLE_PROCESS_STARTER ${TEST_APPLICATION}_single_process_starter.sh)
+ copy_to_builddir(${PROJECT_SOURCE_DIR}/test/application_tests/${TEST_APPLICATION_SINGLE_PROCESS_STARTER}
+ ${PROJECT_BINARY_DIR}/test/${TEST_APPLICATION_SINGLE_PROCESS_STARTER}
+ ${TEST_APPLICATION}_single_process
+ )
endif()
##############################################################################
# magic-cookies-test-client
@@ -332,6 +370,10 @@ if(NOT ${TESTS_BAT})
# Copy bashscript to start client and server $BUILDDIR/test
set(TEST_LOCAL_ROUTING_STARTER local_routing_test_starter.sh)
+ configure_file(
+ ${PROJECT_SOURCE_DIR}/test/routing_tests/conf/${TEST_LOCAL_ROUTING_STARTER}.in
+ ${PROJECT_SOURCE_DIR}/test/routing_tests/${TEST_LOCAL_ROUTING_STARTER}
+ @ONLY)
copy_to_builddir(${PROJECT_SOURCE_DIR}/test/routing_tests/${TEST_LOCAL_ROUTING_STARTER}
${PROJECT_BINARY_DIR}/test/${TEST_LOCAL_ROUTING_STARTER}
${TEST_LOCAL_ROUTING_CLIENT}
@@ -445,6 +487,10 @@ else()
# Copy bashscript to start client and server $BUILDDIR/test
set(TEST_LOCAL_ROUTING_STARTER local_routing_test_starter.sh)
+ configure_file(
+ ${PROJECT_SOURCE_DIR}/test/routing_tests/conf/${TEST_LOCAL_ROUTING_STARTER}.bat.in
+ ${PROJECT_SOURCE_DIR}/test/routing_tests/${TEST_LOCAL_ROUTING_STARTER}
+ @ONLY)
copy_to_builddir(${PROJECT_SOURCE_DIR}/test/routing_tests/${TEST_LOCAL_ROUTING_STARTER}
${PROJECT_BINARY_DIR}/test/${TEST_LOCAL_ROUTING_STARTER}
${TEST_LOCAL_ROUTING_CLIENT}
@@ -1509,6 +1555,7 @@ endif()
if(NOT ${TESTS_BAT})
add_dependencies(${TEST_CONFIGURATION} gtest)
add_dependencies(${TEST_APPLICATION} gtest)
+ add_dependencies(${TEST_APPLICATION_SINGLE_PROCESS_NAME} gtest)
add_dependencies(${TEST_MAGIC_COOKIES_CLIENT} gtest)
add_dependencies(${TEST_MAGIC_COOKIES_SERVICE} gtest)
add_dependencies(${TEST_HEADER_FACTORY} gtest)
@@ -1546,6 +1593,7 @@ endif()
if(NOT ${TESTS_BAT})
add_dependencies(build_tests ${TEST_CONFIGURATION})
add_dependencies(build_tests ${TEST_APPLICATION})
+ add_dependencies(build_tests ${TEST_APPLICATION_SINGLE_PROCESS_NAME})
add_dependencies(build_tests ${TEST_MAGIC_COOKIES_CLIENT})
add_dependencies(build_tests ${TEST_MAGIC_COOKIES_SERVICE})
add_dependencies(build_tests ${TEST_HEADER_FACTORY})
@@ -1595,6 +1643,10 @@ if(NOT ${TESTS_BAT})
COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_APPLICATION_STARTER}
)
set_tests_properties(${TEST_APPLICATION} PROPERTIES TIMEOUT 40)
+ add_test(NAME ${TEST_APPLICATION_SINGLE_PROCESS_NAME}
+ COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_APPLICATION_SINGLE_PROCESS_STARTER}
+ )
+ set_tests_properties(${TEST_APPLICATION_SINGLE_PROCESS_NAME} PROPERTIES TIMEOUT 60)
# magic cookies test
add_test(NAME ${TEST_MAGIC_COOKIES_NAME}
@@ -1745,10 +1797,10 @@ if(NOT ${TESTS_BAT})
add_test(NAME ${TEST_INITIAL_EVENT_NAME}_diff_client_ids_diff_ports_tcp
COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_INITIAL_EVENT_MASTER_STARTER} TCP ${TEST_INITIAL_EVENT_DIFF_IDS_DIFF_PORTS_MASTER_CONFIG_FILE})
set_tests_properties(${TEST_INITIAL_EVENT_NAME}_diff_client_ids_diff_ports_tcp PROPERTIES TIMEOUT 60)
-# TODO
-# add_test(NAME ${TEST_INITIAL_EVENT_NAME}_diff_client_ids_diff_ports_both_tcp_and_udp
-# COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_INITIAL_EVENT_MASTER_STARTER} TCP_AND_UDP ${TEST_INITIAL_EVENT_DIFF_IDS_DIFF_PORTS_MASTER_CONFIG_FILE})
-# set_tests_properties(${TEST_INITIAL_EVENT_NAME}_diff_client_ids_diff_ports_both_tcp_and_udp PROPERTIES TIMEOUT 60)
+
+ add_test(NAME ${TEST_INITIAL_EVENT_NAME}_diff_client_ids_diff_ports_both_tcp_and_udp
+ COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_INITIAL_EVENT_MASTER_STARTER} TCP_AND_UDP ${TEST_INITIAL_EVENT_DIFF_IDS_DIFF_PORTS_MASTER_CONFIG_FILE})
+ set_tests_properties(${TEST_INITIAL_EVENT_NAME}_diff_client_ids_diff_ports_both_tcp_and_udp PROPERTIES TIMEOUT 60)
add_test(NAME ${TEST_INITIAL_EVENT_NAME}_diff_client_ids_diff_ports_prefer_udp
COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_INITIAL_EVENT_MASTER_STARTER} PREFER_UDP ${TEST_INITIAL_EVENT_DIFF_IDS_DIFF_PORTS_MASTER_CONFIG_FILE})
@@ -1765,10 +1817,10 @@ if(NOT ${TESTS_BAT})
add_test(NAME ${TEST_INITIAL_EVENT_NAME}_diff_client_ids_same_ports_tcp
COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_INITIAL_EVENT_MASTER_STARTER} TCP ${TEST_INITIAL_EVENT_DIFF_IDS_SAME_PORTS_MASTER_CONFIG_FILE})
set_tests_properties(${TEST_INITIAL_EVENT_NAME}_diff_client_ids_same_ports_tcp PROPERTIES TIMEOUT 60)
-# TODO
-# add_test(NAME ${TEST_INITIAL_EVENT_NAME}_diff_client_ids_same_ports_both_tcp_and_udp
-# COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_INITIAL_EVENT_MASTER_STARTER} TCP_AND_UDP ${TEST_INITIAL_EVENT_DIFF_IDS_SAME_PORTS_MASTER_CONFIG_FILE})
-# set_tests_properties(${TEST_INITIAL_EVENT_NAME}_diff_client_ids_same_ports_both_tcp_and_udp PROPERTIES TIMEOUT 60)
+
+ add_test(NAME ${TEST_INITIAL_EVENT_NAME}_diff_client_ids_same_ports_both_tcp_and_udp
+ COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_INITIAL_EVENT_MASTER_STARTER} TCP_AND_UDP ${TEST_INITIAL_EVENT_DIFF_IDS_SAME_PORTS_MASTER_CONFIG_FILE})
+ set_tests_properties(${TEST_INITIAL_EVENT_NAME}_diff_client_ids_same_ports_both_tcp_and_udp PROPERTIES TIMEOUT 60)
add_test(NAME ${TEST_INITIAL_EVENT_NAME}_diff_client_ids_same_ports_prefer_udp
COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_INITIAL_EVENT_MASTER_STARTER} PREFER_UDP ${TEST_INITIAL_EVENT_DIFF_IDS_SAME_PORTS_MASTER_CONFIG_FILE})
@@ -1777,10 +1829,10 @@ if(NOT ${TESTS_BAT})
add_test(NAME ${TEST_INITIAL_EVENT_NAME}_diff_client_ids_same_ports_prefer_tcp
COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_INITIAL_EVENT_MASTER_STARTER} PREFER_TCP ${TEST_INITIAL_EVENT_DIFF_IDS_SAME_PORTS_MASTER_CONFIG_FILE})
set_tests_properties(${TEST_INITIAL_EVENT_NAME}_diff_client_ids_same_ports_prefer_tcp PROPERTIES TIMEOUT 60)
-# TODO
-# add_test(NAME ${TEST_INITIAL_EVENT_NAME}_diff_client_ids_partial_same_ports_both_tcp_and_udp
-# COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_INITIAL_EVENT_MASTER_STARTER} TCP_AND_UDP ${TEST_INITIAL_EVENT_DIFF_IDS_PARTIAL_SAME_PORTS_MASTER_CONFIG_FILE})
-# set_tests_properties(${TEST_INITIAL_EVENT_NAME}_diff_client_ids_partial_same_ports_both_tcp_and_udp PROPERTIES TIMEOUT 60)
+
+ add_test(NAME ${TEST_INITIAL_EVENT_NAME}_diff_client_ids_partial_same_ports_both_tcp_and_udp
+ COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_INITIAL_EVENT_MASTER_STARTER} TCP_AND_UDP ${TEST_INITIAL_EVENT_DIFF_IDS_PARTIAL_SAME_PORTS_MASTER_CONFIG_FILE})
+ set_tests_properties(${TEST_INITIAL_EVENT_NAME}_diff_client_ids_partial_same_ports_both_tcp_and_udp PROPERTIES TIMEOUT 60)
add_test(NAME ${TEST_INITIAL_EVENT_NAME}_diff_client_ids_diff_ports_same_service_id_udp
COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_INITIAL_EVENT_MASTER_STARTER} UDP ${TEST_INITIAL_EVENT_DIFF_IDS_DIFF_PORTS_SAME_SERVICEID_MASTER_CONFIG_FILE} SAME_SERVICE_ID)
diff --git a/test/application_tests/application_test.cpp b/test/application_tests/application_test.cpp
index c73a90f..6832c1f 100644
--- a/test/application_tests/application_test.cpp
+++ b/test/application_tests/application_test.cpp
@@ -24,7 +24,10 @@ public:
protected:
void SetUp() {
app_ = runtime::get()->create_application("application_test");
- app_->init();
+ if (!app_->init()) {
+ VSOMEIP_ERROR << "Couldn't initialize application";
+ EXPECT_TRUE(false);
+ }
app_->register_state_handler(
std::bind(&someip_application_test::on_state, this,
@@ -127,7 +130,10 @@ protected:
is_available_ = false;
app_ = runtime::get()->create_application("application_test");
- app_->init();
+ if (!app_->init()) {
+ VSOMEIP_ERROR << "Couldn't initialize application";
+ EXPECT_TRUE(false);
+ }
app_->register_message_handler(vsomeip_test::TEST_SERVICE_SERVICE_ID,
vsomeip_test::TEST_SERVICE_INSTANCE_ID,
@@ -179,10 +185,7 @@ protected:
{
(void)_request;
VSOMEIP_INFO << "Shutdown method was called, going down now.";
- app_->unregister_message_handler(vsomeip_test::TEST_SERVICE_SERVICE_ID,
- vsomeip_test::TEST_SERVICE_INSTANCE_ID,
- vsomeip_test::TEST_SERVICE_METHOD_ID_SHUTDOWN);
- app_->unregister_state_handler();
+ app_->clear_all_handler();
app_->stop();
}
diff --git a/test/application_tests/application_test_client.cpp b/test/application_tests/application_test_client.cpp
new file mode 100644
index 0000000..a227799
--- /dev/null
+++ b/test/application_tests/application_test_client.cpp
@@ -0,0 +1,193 @@
+// Copyright (C) 2014-2016 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 <chrono>
+#include <condition_variable>
+#include <iomanip>
+#include <iostream>
+#include <sstream>
+#include <thread>
+#include <map>
+#include <algorithm>
+
+#include <gtest/gtest.h>
+
+#include <vsomeip/vsomeip.hpp>
+#include "../../implementation/logging/include/logger.hpp"
+
+#include "application_test_globals.hpp"
+
+class application_test_client {
+public:
+ application_test_client(struct application_test::service_info _service_info) :
+ service_info_(_service_info),
+ app_(vsomeip::runtime::get()->create_application("client")),
+ service_available_(false),
+ wait_until_registered_(true),
+ wait_until_service_available_(true),
+ send_thread_(std::bind(&application_test_client::send, this)),
+ wait_for_stop_(true),
+ stop_thread_(std::bind(&application_test_client::wait_for_stop, this)),
+ received_responses_(0),
+ sent_requests_(0),
+ stop_called_(false) {
+ app_->init();
+ app_->register_state_handler(
+ std::bind(&application_test_client::on_state, this,
+ std::placeholders::_1));
+
+ app_->register_message_handler(vsomeip::ANY_SERVICE,
+ vsomeip::ANY_INSTANCE, vsomeip::ANY_METHOD,
+ std::bind(&application_test_client::on_message, this,
+ std::placeholders::_1));
+
+ // register availability for all other services and request their event.
+ app_->register_availability_handler(service_info_.service_id,
+ service_info_.instance_id,
+ std::bind(&application_test_client::on_availability, this,
+ std::placeholders::_1, std::placeholders::_2,
+ std::placeholders::_3));
+ app_->request_service(service_info_.service_id,
+ service_info_.instance_id);
+ application_thread_ = std::thread([&](){
+ app_->start();
+ });
+ }
+
+ ~application_test_client() {
+ send_thread_.join();
+ stop_thread_.join();
+ application_thread_.join();
+ }
+
+ void on_state(vsomeip::state_type_e _state) {
+ VSOMEIP_INFO << "Application " << app_->get_name() << " is "
+ << (_state == vsomeip::state_type_e::ST_REGISTERED ?
+ "registered." : "deregistered.");
+
+ if (_state == vsomeip::state_type_e::ST_REGISTERED) {
+ std::lock_guard<std::mutex> its_lock(mutex_);
+ wait_until_registered_ = false;
+ condition_.notify_one();
+ }
+ }
+
+ void on_availability(vsomeip::service_t _service,
+ vsomeip::instance_t _instance, bool _is_available) {
+ VSOMEIP_INFO << "Service [" << std::setw(4)
+ << std::setfill('0') << std::hex << _service << "." << _instance
+ << "] is " << (_is_available ? "available":"not available") << ".";
+ std::lock_guard<std::mutex> its_lock(mutex_);
+ if(_is_available) {
+ wait_until_service_available_ = false;
+ condition_.notify_one();
+ } else {
+ wait_until_service_available_ = true;
+ condition_.notify_one();
+ }
+ }
+
+ void on_message(const std::shared_ptr<vsomeip::message> &_message) {
+ ++received_responses_;
+ EXPECT_EQ(service_info_.service_id, _message->get_service());
+ EXPECT_EQ(service_info_.method_id, _message->get_method());
+ EXPECT_EQ(service_info_.instance_id, _message->get_instance());
+ VSOMEIP_INFO << "Received a response with Client/Session [" << std::setw(4)
+ << std::setfill('0') << std::hex << _message->get_client() << "/"
+ << std::setw(4) << std::setfill('0') << std::hex
+ << _message->get_session() << "]";
+ }
+
+ void send() {
+ std::unique_lock<std::mutex> its_lock(mutex_);
+ while (wait_until_registered_ && !stop_called_) {
+ condition_.wait_for(its_lock, std::chrono::milliseconds(100));
+ }
+
+ while (wait_until_service_available_ && !stop_called_) {
+ condition_.wait_for(its_lock, std::chrono::milliseconds(100));
+ }
+ its_lock.unlock();
+ its_lock.release();
+
+ for (;;) {
+ bool send(false);
+ {
+ std::lock_guard<std::mutex> its_lock(mutex_);
+ send = !wait_until_service_available_;
+ }
+ if (send && !stop_called_) {
+ std::shared_ptr<vsomeip::message> its_req = vsomeip::runtime::get()->create_request();
+ its_req->set_service(service_info_.service_id);
+ its_req->set_instance(service_info_.instance_id);
+ its_req->set_method(service_info_.method_id);
+ app_->send(its_req);
+ ++sent_requests_;
+ VSOMEIP_INFO << "Sent a request to the service!";
+ std::this_thread::sleep_for(std::chrono::milliseconds(100));
+ } else {
+ std::this_thread::sleep_for(std::chrono::milliseconds(50));
+ }
+ if(stop_called_) {
+ break;
+ }
+ }
+ }
+
+ void wait_for_stop() {
+ std::unique_lock<std::mutex> its_lock(stop_mutex_);
+ while (wait_for_stop_) {
+ stop_condition_.wait(its_lock);
+ }
+ VSOMEIP_INFO << "going down";
+ app_->clear_all_handler();
+ app_->stop();
+ }
+
+ void stop(bool check) {
+ stop_called_ = true;
+ std::lock_guard<std::mutex> its_lock(stop_mutex_);
+ wait_for_stop_ = false;
+ VSOMEIP_INFO << "going down. Sent " << sent_requests_
+ << " requests and received " << received_responses_
+ << " responses. Delta: " << sent_requests_ - received_responses_;
+ std::uint32_t counter(0);
+ if (check) {
+ if (sent_requests_ == 0 || received_responses_ == 0) {
+ EXPECT_EQ(0, 1);
+ }
+ while(sent_requests_ < received_responses_) {
+ std::this_thread::sleep_for(std::chrono::milliseconds(100));
+ if(++counter > 50) {
+ break;
+ }
+ }
+ EXPECT_EQ(sent_requests_, received_responses_);
+ }
+ stop_condition_.notify_one();
+ }
+
+private:
+ struct application_test::service_info service_info_;
+ std::shared_ptr<vsomeip::application> app_;
+ bool service_available_;
+
+ bool wait_until_registered_;
+ bool wait_until_service_available_;
+ std::mutex mutex_;
+ std::condition_variable condition_;
+ std::thread send_thread_;
+
+ bool wait_for_stop_;
+ std::mutex stop_mutex_;
+ std::condition_variable stop_condition_;
+ std::thread stop_thread_;
+
+ std::uint32_t received_responses_;
+ std::uint32_t sent_requests_;
+
+ std::thread application_thread_;
+ bool stop_called_;
+};
diff --git a/test/application_tests/application_test_daemon.cpp b/test/application_tests/application_test_daemon.cpp
new file mode 100644
index 0000000..6e2c7cb
--- /dev/null
+++ b/test/application_tests/application_test_daemon.cpp
@@ -0,0 +1,34 @@
+// Copyright (C) 2014-2016 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 <gtest/gtest.h>
+
+#include <vsomeip/vsomeip.hpp>
+#include "../../implementation/logging/include/logger.hpp"
+
+class application_test_daemon {
+public:
+ application_test_daemon() :
+ app_(vsomeip::runtime::get()->create_application("daemon")) {
+ app_->init();
+ application_thread_ = std::thread([&](){
+ app_->start();
+ });
+ VSOMEIP_INFO << "Daemon starting";
+ }
+
+ ~application_test_daemon() {
+ application_thread_.join();
+ }
+
+ void stop() {
+ VSOMEIP_INFO << "Daemon stopping";
+ app_->stop();
+ }
+
+private:
+ std::shared_ptr<vsomeip::application> app_;
+ std::thread application_thread_;
+};
diff --git a/test/application_tests/application_test_globals.hpp b/test/application_tests/application_test_globals.hpp
new file mode 100644
index 0000000..ea82255
--- /dev/null
+++ b/test/application_tests/application_test_globals.hpp
@@ -0,0 +1,25 @@
+// Copyright (C) 2014-2016 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 APPLICATION_TEST_GLOBALS_HPP_
+#define APPLICATION_TEST_GLOBALS_HPP_
+
+namespace application_test {
+
+struct service_info {
+ vsomeip::service_t service_id;
+ vsomeip::instance_t instance_id;
+ vsomeip::method_t method_id;
+ vsomeip::event_t event_id;
+ vsomeip::eventgroup_t eventgroup_id;
+ vsomeip::method_t shutdown_method_id;
+};
+
+struct service_info service = { 0x1111, 0x1, 0x1111, 0x1111, 0x1000, 0x1404 };
+
+static constexpr int number_of_messages_to_send = 150;
+}
+
+#endif /* APPLICATION_TEST_GLOBALS_HPP_ */
diff --git a/test/application_tests/application_test_service.cpp b/test/application_tests/application_test_service.cpp
new file mode 100644
index 0000000..a1c654e
--- /dev/null
+++ b/test/application_tests/application_test_service.cpp
@@ -0,0 +1,115 @@
+// Copyright (C) 2014-2016 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 <chrono>
+#include <condition_variable>
+#include <iomanip>
+#include <iostream>
+#include <sstream>
+#include <thread>
+#include <map>
+#include <algorithm>
+
+#include <gtest/gtest.h>
+
+#include <vsomeip/vsomeip.hpp>
+#include "../../implementation/logging/include/logger.hpp"
+
+#include "application_test_globals.hpp"
+
+class application_test_service {
+public:
+ application_test_service(struct application_test::service_info _service_info) :
+ service_info_(_service_info),
+ // service with number 1 uses "vsomeipd" as application name
+ // this way the same json file can be reused for all local tests
+ // including the ones with vsomeipd
+ app_(vsomeip::runtime::get()->create_application("service")),
+ counter_(0),
+ wait_until_registered_(true),
+ offer_thread_(std::bind(&application_test_service::run, this)),
+ stop_called_(false) {
+ app_->init();
+ app_->register_state_handler(
+ std::bind(&application_test_service::on_state, this,
+ std::placeholders::_1));
+
+ app_->register_message_handler(service_info_.service_id,
+ service_info_.instance_id, service_info_.method_id,
+ std::bind(&application_test_service::on_request, this,
+ std::placeholders::_1));
+
+ app_->register_message_handler(service_info_.service_id,
+ service_info_.instance_id, service_info_.shutdown_method_id,
+ std::bind(&application_test_service::on_shutdown_method_called, this,
+ std::placeholders::_1));
+ application_thread_ = std::thread([&](){
+ app_->start();
+ });
+ }
+
+ ~application_test_service() {
+ offer_thread_.join();
+ application_thread_.join();
+ }
+
+
+ void offer() {
+ app_->offer_service(service_info_.service_id, service_info_.instance_id);
+ }
+
+ void on_state(vsomeip::state_type_e _state) {
+ VSOMEIP_INFO << "Application " << app_->get_name() << " is "
+ << (_state == vsomeip::state_type_e::ST_REGISTERED ?
+ "registered." : "deregistered.");
+
+ if (_state == vsomeip::state_type_e::ST_REGISTERED) {
+ std::lock_guard<std::mutex> its_lock(mutex_);
+ wait_until_registered_ = false;
+ condition_.notify_one();
+ }
+ }
+
+ void on_request(const std::shared_ptr<vsomeip::message> &_message) {
+ app_->send(vsomeip::runtime::get()->create_response(_message));
+ VSOMEIP_INFO << "Received a request with Client/Session [" << std::setw(4)
+ << std::setfill('0') << std::hex << _message->get_client() << "/"
+ << std::setw(4) << std::setfill('0') << std::hex
+ << _message->get_session() << "]";
+ }
+
+ void on_shutdown_method_called(const std::shared_ptr<vsomeip::message> &_message) {
+ (void)_message;
+ stop_called_ = true;
+ app_->stop_offer_service(service_info_.service_id, service_info_.instance_id);
+ app_->clear_all_handler();
+ app_->stop();
+ }
+
+ void run() {
+ VSOMEIP_DEBUG << "[" << std::setw(4) << std::setfill('0') << std::hex
+ << service_info_.service_id << "] Running";
+ std::unique_lock<std::mutex> its_lock(mutex_);
+ while (wait_until_registered_ && !stop_called_) {
+ condition_.wait_for(its_lock, std::chrono::milliseconds(100));
+ }
+
+ VSOMEIP_DEBUG << "[" << std::setw(4) << std::setfill('0') << std::hex
+ << service_info_.service_id << "] Offering";
+ offer();
+ }
+
+private:
+ struct application_test::service_info service_info_;
+ std::shared_ptr<vsomeip::application> app_;
+ std::uint32_t counter_;
+
+ bool wait_until_registered_;
+ std::mutex mutex_;
+ std::condition_variable condition_;
+ std::thread offer_thread_;
+ std::thread application_thread_;
+ bool stop_called_;
+};
diff --git a/test/application_tests/application_test_single_process.cpp b/test/application_tests/application_test_single_process.cpp
new file mode 100644
index 0000000..eee636c
--- /dev/null
+++ b/test/application_tests/application_test_single_process.cpp
@@ -0,0 +1,47 @@
+// Copyright (C) 2014-2016 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 <gtest/gtest.h>
+#include "application_test_service.cpp"
+#include "application_test_client.cpp"
+#include "application_test_daemon.cpp"
+
+TEST(someip_application_test_single_process, notify_increasing_counter)
+{
+ // start application acting as daemon (rm_stub)
+ application_test_daemon its_daemon;
+
+ // start receiver service (rm_proxy)
+ application_test_service its_receiver(application_test::service);
+
+ // stop the daemon (rm_stub goes away)
+ its_daemon.stop();
+
+ // restart client which tries to communicate with service multiple times
+ // thus it will always be the new routing manager
+ for (int var = 0; var < 10; ++var) {
+ // every time the client is restarted it becomes the rm_stub again
+ application_test_client its_client(application_test::service);
+ if(var != 9) {
+ its_client.stop(false);
+ } else {
+ // for the last iteration we sleep to make sure the communication
+ // between the client and the service can be established
+ std::this_thread::sleep_for(std::chrono::milliseconds(2000));
+ its_client.stop(true);
+ }
+ }
+ std::this_thread::sleep_for(std::chrono::milliseconds(100));
+ its_receiver.on_shutdown_method_called(vsomeip::runtime::get()->create_message());
+}
+
+
+#ifndef WIN32
+int main(int argc, char** argv)
+{
+ ::testing::InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
+}
+#endif
diff --git a/test/application_tests/application_test_single_process.json b/test/application_tests/application_test_single_process.json
new file mode 100644
index 0000000..b604d9a
--- /dev/null
+++ b/test/application_tests/application_test_single_process.json
@@ -0,0 +1,14 @@
+{
+ "unicast":"127.0.0.1",
+ "logging":
+ {
+ "level":"warning",
+ "console":"true",
+ "file":
+ {
+ "enable":"false",
+ "path":"/tmp/someip.log"
+ },
+ "dlt":"false"
+ }
+}
diff --git a/test/application_tests/application_test_single_process_starter.sh b/test/application_tests/application_test_single_process_starter.sh
new file mode 100755
index 0000000..0ac3330
--- /dev/null
+++ b/test/application_tests/application_test_single_process_starter.sh
@@ -0,0 +1,23 @@
+#!/bin/bash
+# Copyright (C) 2015-2016 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/.
+
+FAIL=0
+
+export VSOMEIP_CONFIGURATION=application_test_single_process.json
+./application_test_single_process
+
+if [ $? -ne 0 ]
+then
+ ((FAIL+=1))
+fi
+
+# Check if both exited successfully
+if [ $FAIL -eq 0 ]
+then
+ exit 0
+else
+ exit 1
+fi
diff --git a/test/application_tests/application_test.json b/test/application_tests/conf/application_test.json.in
index 66abf3a..ed5a7fc 100644
--- a/test/application_tests/application_test.json
+++ b/test/application_tests/conf/application_test.json.in
@@ -1,5 +1,5 @@
{
- "unicast":"127.0.0.1",
+ "unicast":"@TEST_IP_MASTER@",
"logging":
{
"level":"warning",
diff --git a/test/application_tests/application_test_daemon.json b/test/application_tests/conf/application_test_daemon.json.in
index 6b4a946..c84adf5 100644
--- a/test/application_tests/application_test_daemon.json
+++ b/test/application_tests/conf/application_test_daemon.json.in
@@ -1,5 +1,5 @@
{
- "unicast":"127.0.0.1",
+ "unicast":"@TEST_IP_MASTER@",
"logging":
{
"level":"warning",
diff --git a/test/application_tests/application_test_no_dispatch_threads.json b/test/application_tests/conf/application_test_no_dispatch_threads.json.in
index d2f9569..20d0ebd 100644
--- a/test/application_tests/application_test_no_dispatch_threads.json
+++ b/test/application_tests/conf/application_test_no_dispatch_threads.json.in
@@ -1,5 +1,5 @@
{
- "unicast":"127.0.0.1",
+ "unicast":"@TEST_IP_MASTER@",
"logging":
{
"level":"warning",
diff --git a/test/application_tests/application_test_no_dispatch_threads_daemon.json b/test/application_tests/conf/application_test_no_dispatch_threads_daemon.json.in
index e33190b..8dec80e 100644
--- a/test/application_tests/application_test_no_dispatch_threads_daemon.json
+++ b/test/application_tests/conf/application_test_no_dispatch_threads_daemon.json.in
@@ -1,5 +1,5 @@
{
- "unicast":"127.0.0.1",
+ "unicast":"@TEST_IP_MASTER@",
"logging":
{
"level":"warning",
diff --git a/test/big_payload_tests/big_payload_test_client.cpp b/test/big_payload_tests/big_payload_test_client.cpp
index 15e0a14..a18dd0c 100644
--- a/test/big_payload_tests/big_payload_test_client.cpp
+++ b/test/big_payload_tests/big_payload_test_client.cpp
@@ -21,7 +21,10 @@ big_payload_test_client::big_payload_test_client(bool _use_tcp) :
void big_payload_test_client::init()
{
- app_->init();
+ if (!app_->init()) {
+ VSOMEIP_ERROR << "Couldn't initialize application";
+ EXPECT_TRUE(false);
+ }
app_->register_state_handler(
std::bind(&big_payload_test_client::on_state, this,
@@ -53,7 +56,7 @@ void big_payload_test_client::stop()
app_->unregister_state_handler();
app_->unregister_message_handler(vsomeip::ANY_SERVICE,
vsomeip_test::TEST_SERVICE_INSTANCE_ID, vsomeip::ANY_METHOD);
-
+ app_->clear_all_handler();
app_->stop();
}
diff --git a/test/big_payload_tests/big_payload_test_service.cpp b/test/big_payload_tests/big_payload_test_service.cpp
index fc8690e..37f3d7f 100644
--- a/test/big_payload_tests/big_payload_test_service.cpp
+++ b/test/big_payload_tests/big_payload_test_service.cpp
@@ -20,7 +20,10 @@ void big_payload_test_service::init()
{
std::lock_guard<std::mutex> its_lock(mutex_);
- app_->init();
+ if (!app_->init()) {
+ VSOMEIP_ERROR << "Couldn't initialize application";
+ EXPECT_TRUE(false);
+ }
app_->register_message_handler(vsomeip_test::TEST_SERVICE_SERVICE_ID,
vsomeip_test::TEST_SERVICE_INSTANCE_ID, vsomeip_test::TEST_SERVICE_METHOD_ID,
std::bind(&big_payload_test_service::on_message, this,
@@ -40,9 +43,7 @@ void big_payload_test_service::start()
void big_payload_test_service::stop()
{
VSOMEIP_INFO << "Stopping...";
- app_->unregister_message_handler(vsomeip_test::TEST_SERVICE_SERVICE_ID,
- vsomeip_test::TEST_SERVICE_INSTANCE_ID, vsomeip_test::TEST_SERVICE_METHOD_ID);
- app_->unregister_state_handler();
+ app_->clear_all_handler();
app_->stop();
}
diff --git a/test/client_id_tests/client_id_test_service.cpp b/test/client_id_tests/client_id_test_service.cpp
index 36bfeb8..6572d74 100644
--- a/test/client_id_tests/client_id_test_service.cpp
+++ b/test/client_id_tests/client_id_test_service.cpp
@@ -29,7 +29,10 @@ public:
offer_thread_(std::bind(&client_id_test_service::run, this)),
stopped_(false),
stop_thread_(std::bind(&client_id_test_service::wait_for_stop, this)) {
- app_->init();
+ if (!app_->init()) {
+ VSOMEIP_ERROR << "Couldn't initialize application";
+ EXPECT_TRUE(false);
+ }
app_->register_state_handler(
std::bind(&client_id_test_service::on_state, this,
std::placeholders::_1));
@@ -88,7 +91,9 @@ public:
void on_availability(vsomeip::service_t _service,
vsomeip::instance_t _instance, bool _is_available) {
if(_is_available) {
- VSOMEIP_INFO << "Service ["
+ VSOMEIP_INFO
+ << "[" << std::setw(4) << std::setfill('0') << std::hex
+ << service_info_.service_id << "] Service ["
<< std::setw(4) << std::setfill('0') << std::hex << _service << "." << _instance
<< "] is "
<< (_is_available ? "available." : "NOT available.");
@@ -112,7 +117,10 @@ public:
void on_request(const std::shared_ptr<vsomeip::message> &_message) {
if(_message->get_message_type() == vsomeip::message_type_e::MT_REQUEST) {
- VSOMEIP_DEBUG << "Received a request with Client/Session [" << std::setw(4)
+ VSOMEIP_DEBUG
+ << "[" << std::setw(4) << std::setfill('0') << std::hex
+ << service_info_.service_id
+ << "] Received a request with Client/Session [" << std::setw(4)
<< std::setfill('0') << std::hex << _message->get_client() << "/"
<< std::setw(4) << std::setfill('0') << std::hex
<< _message->get_session() << "]";
@@ -124,7 +132,10 @@ public:
void on_response(const std::shared_ptr<vsomeip::message> &_message) {
if(_message->get_message_type() == vsomeip::message_type_e::MT_RESPONSE) {
- VSOMEIP_DEBUG << "Received a response with Client/Session [" << std::setw(4)
+ VSOMEIP_DEBUG
+ << "[" << std::setw(4) << std::setfill('0') << std::hex
+ << service_info_.service_id
+ << "] Received a response with Client/Session [" << std::setw(4)
<< std::setfill('0') << std::hex << _message->get_client() << "/"
<< std::setw(4) << std::setfill('0') << std::hex
<< _message->get_session() << "] from Service/Method ["
@@ -147,14 +158,14 @@ public:
}
void run() {
- VSOMEIP_DEBUG << "Running";
std::unique_lock<std::mutex> its_lock(mutex_);
while (!blocked_) {
condition_.wait(its_lock);
}
blocked_ = false;
- VSOMEIP_DEBUG << "Offering";
+ VSOMEIP_DEBUG << "[" << std::setw(4) << std::setfill('0') << std::hex
+ << service_info_.service_id << "] Offering";
offer();
@@ -163,7 +174,8 @@ public:
}
blocked_ = false;
- VSOMEIP_DEBUG << "Sending";
+ VSOMEIP_DEBUG << "[" << std::setw(4) << std::setfill('0') << std::hex
+ << service_info_.service_id << "] Sending";
// send a message to all other services
for (int var = 0; var < client_id_test::messages_to_send; ++var) {
for(const client_id_test::service_info& i: client_id_test::service_infos) {
@@ -177,10 +189,12 @@ public:
msg->set_instance(i.instance_id);
msg->set_method(i.method_id);
app_->send(msg);
- VSOMEIP_DEBUG << "Sending a request to Service/Method ["
- << std::setw(4) << std::setfill('0') << std::hex
- << i.service_id << "/" << std::setw(4) << std::setfill('0')
- << std::hex << i.instance_id <<"]";
+ VSOMEIP_DEBUG << "[" << std::setw(4) << std::setfill('0')
+ << std::hex << service_info_.service_id
+ << "] Sending a request to Service/Method ["
+ << std::setw(4) << std::setfill('0') << std::hex
+ << i.service_id << "/" << std::setw(4) << std::setfill('0')
+ << std::hex << i.instance_id <<"]";
}
}
@@ -195,7 +209,9 @@ public:
while (!stopped_) {
stop_condition_.wait(its_lock);
}
- VSOMEIP_INFO << "Received responses from all other services, going down";
+ VSOMEIP_INFO << "[" << std::setw(4) << std::setfill('0') << std::hex
+ << service_info_.service_id
+ << "] Received responses from all other services, going down";
// let offer thread exit
{
@@ -205,6 +221,7 @@ public:
}
std::this_thread::sleep_for(std::chrono::seconds(3));
+ app_->clear_all_handler();
app_->stop();
}
diff --git a/test/configuration_tests/configuration-test-deprecated.json b/test/configuration_tests/configuration-test-deprecated.json
index 8d6a8d2..09a2e7e 100644
--- a/test/configuration_tests/configuration-test-deprecated.json
+++ b/test/configuration_tests/configuration-test-deprecated.json
@@ -29,7 +29,8 @@
"repetition-base" : "200",
"repetition-max" : "7",
"cyclic-offer" : "2132",
- "cyclic-request" : "2001"
+ "cyclic-request" : "2001",
+ "ttl" : "5"
},
"services" :
[
@@ -84,11 +85,12 @@
"unicast" : "local",
"delays" :
{
- "initial" : { "minimum" : "100", "maximum" : "200" },
- "repetition-base" : "300",
- "repetition-max" : "5",
- "cyclic-offer" : "2500",
- "cyclic-request" : "2221"
+ "initial" : { "minimum" : "10", "maximum" : "100" },
+ "repetition-base" : "200",
+ "repetition-max" : "7",
+ "cyclic-offer" : "2132",
+ "cyclic-request" : "2001",
+ "ttl" : "5"
},
"services" :
[
@@ -128,4 +130,4 @@
"multicast" : "224.212.244.223",
"port" : "30666"
}
-} \ No newline at end of file
+}
diff --git a/test/configuration_tests/configuration-test.cpp b/test/configuration_tests/configuration-test.cpp
index 01a0e3e..37ebfeb 100644
--- a/test/configuration_tests/configuration-test.cpp
+++ b/test/configuration_tests/configuration-test.cpp
@@ -3,6 +3,7 @@
// 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 <cstdlib>
#include <iostream>
#include <vsomeip/constants.hpp>
@@ -109,155 +110,158 @@ void check_file(const std::string &_config_file,
vsomeip::ttl_t _expected_cyclic_offer_delay,
vsomeip::ttl_t _expected_request_response_delay) {
- // Reset configuration
- vsomeip::configuration::reset();
-
- // Load test configuration
- std::set<std::string> its_configuration_files;
- its_configuration_files.insert(_config_file);
- std::shared_ptr<vsomeip::configuration> its_configuration
- = vsomeip::configuration::get(its_configuration_files);
-
- // 1. Did we get a configuration object?
- if (0 == its_configuration) {
- VSOMEIP_ERROR << "No configuration object. "
- "Either memory overflow or loading error detected!";
- return;
- }
-
- // 2. 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");
-
- // 3. Check logging
- bool has_console = its_configuration->has_console_log();
- bool has_file = its_configuration->has_file_log();
- bool has_dlt = its_configuration->has_dlt_log();
- std::string logfile = its_configuration->get_logfile();
- boost::log::trivial::severity_level loglevel
- = its_configuration->get_loglevel();
-
- 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");
-
- // 4. Services
- std::string its_unicast_address
- = its_configuration->get_unicast_address(0x1234, 0x0022);
- uint16_t its_reliable_port
- = its_configuration->get_reliable_port(0x1234, 0x0022);
- uint16_t its_unreliable_port
- = its_configuration->get_unreliable_port(0x1234, 0x0022);
-
- check<std::string>(its_unicast_address,
- _expected_unicast_address_1234_0022,
- "UNICAST_ADDRESS_1234_0022");
- check<uint16_t>(its_reliable_port,
- _expected_reliable_port_1234_0022,
- "RELIABLE_PORT_1234_0022");
- check<uint16_t>(its_unreliable_port,
- _expected_unreliable_port_1234_0022,
- "UNRELIABLE_PORT_1234_0022");
-
- its_unicast_address
- = its_configuration->get_unicast_address(0x1234, 0x0023);
- its_reliable_port
- = its_configuration->get_reliable_port(0x1234, 0x0023);
- its_unreliable_port
- = its_configuration->get_unreliable_port(0x1234, 0x0023);
-
- check<std::string>(its_unicast_address,
- _expected_unicast_address_1234_0023,
- "UNICAST_ADDRESS_1234_0023");
- check<uint16_t>(its_reliable_port,
- _expected_reliable_port_1234_0023,
- "RELIABLE_PORT_1234_0023");
- check<uint16_t>(its_unreliable_port,
- _expected_unreliable_port_1234_0023,
- "UNRELIABLE_PORT_1234_0023");
-
- its_unicast_address
- = its_configuration->get_unicast_address(0x2277, 0x0022);
- its_reliable_port
- = its_configuration->get_reliable_port(0x2277, 0x0022);
- its_unreliable_port
- = its_configuration->get_unreliable_port(0x2277, 0x0022);
-
- check<std::string>(its_unicast_address,
- _expected_unicast_address_2277_0022,
- "UNICAST_ADDRESS_2277_0022");
- check<uint16_t>(its_reliable_port,
- _expected_reliable_port_2277_0022,
- "RELIABLE_PORT_2277_0022");
- check<uint16_t>(its_unreliable_port,
- _expected_unreliable_port_2277_0022,
- "UNRELIABLE_PORT_2277_0022");
-
- its_unicast_address
- = its_configuration->get_unicast_address(0x2266, 0x0022);
- its_reliable_port
- = its_configuration->get_reliable_port(0x2266, 0x0022);
- its_unreliable_port
- = its_configuration->get_unreliable_port(0x2266, 0x0022);
-
- check<std::string>(its_unicast_address,
- _expected_unicast_address_2266_0022,
- "UNICAST_ADDRESS_2266_0022");
- check<uint16_t>(its_reliable_port,
- _expected_reliable_port_2266_0022,
- "RELIABLE_PORT_2266_0022");
- check<uint16_t>(its_unreliable_port,
- _expected_unreliable_port_2266_0022,
- "UNRELIABLE_PORT_2266_0022");
-
- its_unicast_address
- = its_configuration->get_unicast_address(0x4466, 0x0321);
- its_reliable_port
- = its_configuration->get_reliable_port(0x4466, 0x0321);
- its_unreliable_port
- = its_configuration->get_unreliable_port(0x4466, 0x0321);
-
- check<std::string>(its_unicast_address,
- _expected_unicast_address_4466_0321,
- "UNICAST_ADDRESS_4466_0321");
- check<uint16_t>(its_reliable_port,
- _expected_reliable_port_4466_0321,
- "RELIABLE_PORT_4466_0321");
- check<uint16_t>(its_unreliable_port,
- _expected_unreliable_port_4466_0321,
- "UNRELIABLE_PORT_4466_0321");
-
- // 5. Service discovery
- bool enabled = its_configuration->is_sd_enabled();
- std::string protocol = its_configuration->get_sd_protocol();
- uint16_t port = its_configuration->get_sd_port();
- std::string multicast = its_configuration->get_sd_multicast();
-
- int32_t initial_delay_min = its_configuration->get_sd_initial_delay_min();
- int32_t initial_delay_max = its_configuration->get_sd_initial_delay_max();
- int32_t repetitions_base_delay = its_configuration->get_sd_repetitions_base_delay();
- uint8_t repetitions_max = its_configuration->get_sd_repetitions_max();
- vsomeip::ttl_t ttl = its_configuration->get_sd_ttl();
- 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");
+ // 0. Create configuration object
+ std::shared_ptr<vsomeip::configuration> its_configuration
+ = vsomeip::configuration::get();
+
+ // 1. Did we get a configuration object?
+ if (0 == its_configuration) {
+ VSOMEIP_ERROR << "No configuration object. "
+ "Either memory overflow or loading error detected!";
+ return;
+ }
+
+ // 2. Set environment variable to config file and load it
+#ifndef WIN32
+ setenv("VSOMEIP_CONFIGURATION", _config_file.c_str(), 1);
+#else
+ _putenv_s("VSOMEIP_CONFIGURATION", _config_file.c_str()
+#endif
+ its_configuration->load(EXPECTED_ROUTING_MANAGER_HOST);
+
+ // 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");
+
+ // 4. Check logging
+ bool has_console = its_configuration->has_console_log();
+ bool has_file = its_configuration->has_file_log();
+ bool has_dlt = its_configuration->has_dlt_log();
+ std::string logfile = its_configuration->get_logfile();
+ boost::log::trivial::severity_level loglevel
+ = its_configuration->get_loglevel();
+
+ 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
+ = its_configuration->get_unicast_address(0x1234, 0x0022);
+ uint16_t its_reliable_port
+ = its_configuration->get_reliable_port(0x1234, 0x0022);
+ uint16_t its_unreliable_port
+ = its_configuration->get_unreliable_port(0x1234, 0x0022);
+
+ check<std::string>(its_unicast_address,
+ _expected_unicast_address_1234_0022,
+ "UNICAST_ADDRESS_1234_0022");
+ check<uint16_t>(its_reliable_port,
+ _expected_reliable_port_1234_0022,
+ "RELIABLE_PORT_1234_0022");
+ check<uint16_t>(its_unreliable_port,
+ _expected_unreliable_port_1234_0022,
+ "UNRELIABLE_PORT_1234_0022");
+
+ its_unicast_address
+ = its_configuration->get_unicast_address(0x1234, 0x0023);
+ its_reliable_port
+ = its_configuration->get_reliable_port(0x1234, 0x0023);
+ its_unreliable_port
+ = its_configuration->get_unreliable_port(0x1234, 0x0023);
+
+ check<std::string>(its_unicast_address,
+ _expected_unicast_address_1234_0023,
+ "UNICAST_ADDRESS_1234_0023");
+ check<uint16_t>(its_reliable_port,
+ _expected_reliable_port_1234_0023,
+ "RELIABLE_PORT_1234_0023");
+ check<uint16_t>(its_unreliable_port,
+ _expected_unreliable_port_1234_0023,
+ "UNRELIABLE_PORT_1234_0023");
+
+ its_unicast_address
+ = its_configuration->get_unicast_address(0x2277, 0x0022);
+ its_reliable_port
+ = its_configuration->get_reliable_port(0x2277, 0x0022);
+ its_unreliable_port
+ = its_configuration->get_unreliable_port(0x2277, 0x0022);
+
+ check<std::string>(its_unicast_address,
+ _expected_unicast_address_2277_0022,
+ "UNICAST_ADDRESS_2277_0022");
+ check<uint16_t>(its_reliable_port,
+ _expected_reliable_port_2277_0022,
+ "RELIABLE_PORT_2277_0022");
+ check<uint16_t>(its_unreliable_port,
+ _expected_unreliable_port_2277_0022,
+ "UNRELIABLE_PORT_2277_0022");
+
+ its_unicast_address
+ = its_configuration->get_unicast_address(0x2266, 0x0022);
+ its_reliable_port
+ = its_configuration->get_reliable_port(0x2266, 0x0022);
+ its_unreliable_port
+ = its_configuration->get_unreliable_port(0x2266, 0x0022);
+
+ check<std::string>(its_unicast_address,
+ _expected_unicast_address_2266_0022,
+ "UNICAST_ADDRESS_2266_0022");
+ check<uint16_t>(its_reliable_port,
+ _expected_reliable_port_2266_0022,
+ "RELIABLE_PORT_2266_0022");
+ check<uint16_t>(its_unreliable_port,
+ _expected_unreliable_port_2266_0022,
+ "UNRELIABLE_PORT_2266_0022");
+
+ its_unicast_address
+ = its_configuration->get_unicast_address(0x4466, 0x0321);
+ its_reliable_port
+ = its_configuration->get_reliable_port(0x4466, 0x0321);
+ its_unreliable_port
+ = its_configuration->get_unreliable_port(0x4466, 0x0321);
+
+ check<std::string>(its_unicast_address,
+ _expected_unicast_address_4466_0321,
+ "UNICAST_ADDRESS_4466_0321");
+ check<uint16_t>(its_reliable_port,
+ _expected_reliable_port_4466_0321,
+ "RELIABLE_PORT_4466_0321");
+ check<uint16_t>(its_unreliable_port,
+ _expected_unreliable_port_4466_0321,
+ "UNRELIABLE_PORT_4466_0321");
+
+ // 6. Service discovery
+ bool enabled = its_configuration->is_sd_enabled();
+ std::string protocol = its_configuration->get_sd_protocol();
+ uint16_t port = its_configuration->get_sd_port();
+ std::string multicast = its_configuration->get_sd_multicast();
+
+ int32_t initial_delay_min = its_configuration->get_sd_initial_delay_min();
+ int32_t initial_delay_max = its_configuration->get_sd_initial_delay_max();
+ int32_t repetitions_base_delay = its_configuration->get_sd_repetitions_base_delay();
+ uint8_t repetitions_max = its_configuration->get_sd_repetitions_max();
+ vsomeip::ttl_t ttl = its_configuration->get_sd_ttl();
+ 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");
}
diff --git a/test/cpu_load_tests/cpu_load_test_client.cpp b/test/cpu_load_tests/cpu_load_test_client.cpp
index 6546013..dd732e3 100644
--- a/test/cpu_load_tests/cpu_load_test_client.cpp
+++ b/test/cpu_load_tests/cpu_load_test_client.cpp
@@ -52,7 +52,10 @@ public:
payload_size_(_payload_size),
wait_for_all_msg_acknowledged_(true),
sender_(std::bind(&cpu_load_test_client::run, this)) {
- app_->init();
+ if (!app_->init()) {
+ VSOMEIP_ERROR << "Couldn't initialize application";
+ EXPECT_TRUE(false);
+ }
app_->register_state_handler(
std::bind(&cpu_load_test_client::on_state, this,
@@ -84,11 +87,7 @@ private:
{
shutdown_service();
}
- app_->unregister_availability_handler(cpu_load_test::service_id,
- cpu_load_test::instance_id);
- app_->unregister_state_handler();
- app_->unregister_message_handler(vsomeip::ANY_SERVICE,
- vsomeip::ANY_INSTANCE, vsomeip::ANY_METHOD);
+ app_->clear_all_handler();
}
void on_state(vsomeip::state_type_e _state) {
diff --git a/test/cpu_load_tests/cpu_load_test_service.cpp b/test/cpu_load_tests/cpu_load_test_service.cpp
index 6eb0c81..67b4ef9 100644
--- a/test/cpu_load_tests/cpu_load_test_service.cpp
+++ b/test/cpu_load_tests/cpu_load_test_service.cpp
@@ -40,7 +40,10 @@ public:
{
std::lock_guard<std::mutex> its_lock(mutex_);
- app_->init();
+ if (!app_->init()) {
+ VSOMEIP_ERROR << "Couldn't initialize application";
+ EXPECT_TRUE(false);
+ }
app_->register_message_handler(cpu_load_test::service_id,
cpu_load_test::instance_id, cpu_load_test::method_id,
std::bind(&cpu_load_test_service::on_message, this,
@@ -73,11 +76,7 @@ public:
{
VSOMEIP_INFO << "Stopping...";
app_->stop_offer_service(cpu_load_test::service_id, cpu_load_test::instance_id);
- app_->unregister_message_handler(cpu_load_test::service_id,
- cpu_load_test::instance_id, cpu_load_test::method_id);
- app_->unregister_message_handler(cpu_load_test::service_id,
- cpu_load_test::instance_id, cpu_load_test::method_id_shutdown);
- app_->unregister_state_handler();
+ app_->clear_all_handler();
app_->stop();
}
diff --git a/test/header_factory_tests/header_factory_test_client.cpp b/test/header_factory_tests/header_factory_test_client.cpp
index b6f3858..2e08cbc 100644
--- a/test/header_factory_tests/header_factory_test_client.cpp
+++ b/test/header_factory_tests/header_factory_test_client.cpp
@@ -20,7 +20,10 @@ header_factory_test_client::header_factory_test_client(bool _use_tcp) :
void header_factory_test_client::init()
{
- app_->init();
+ if (!app_->init()) {
+ VSOMEIP_ERROR << "Couldn't initialize application";
+ EXPECT_TRUE(false);
+ }
app_->register_state_handler(
std::bind(&header_factory_test_client::on_state, this,
@@ -47,12 +50,7 @@ void header_factory_test_client::start()
void header_factory_test_client::stop()
{
VSOMEIP_INFO << "Stopping...";
- app_->unregister_availability_handler(vsomeip_test::TEST_SERVICE_SERVICE_ID,
- vsomeip_test::TEST_SERVICE_INSTANCE_ID);
- app_->unregister_state_handler();
- app_->unregister_message_handler(vsomeip::ANY_SERVICE,
- vsomeip_test::TEST_SERVICE_INSTANCE_ID, vsomeip::ANY_METHOD);
-
+ app_->clear_all_handler();
app_->stop();
}
diff --git a/test/header_factory_tests/header_factory_test_service.cpp b/test/header_factory_tests/header_factory_test_service.cpp
index 0367d40..0ff516f 100644
--- a/test/header_factory_tests/header_factory_test_service.cpp
+++ b/test/header_factory_tests/header_factory_test_service.cpp
@@ -21,7 +21,10 @@ void header_factory_test_service::init()
{
std::lock_guard<std::mutex> its_lock(mutex_);
- app_->init();
+ if (!app_->init()) {
+ VSOMEIP_ERROR << "Couldn't initialize application";
+ EXPECT_TRUE(false);
+ }
app_->register_message_handler(vsomeip_test::TEST_SERVICE_SERVICE_ID,
vsomeip_test::TEST_SERVICE_INSTANCE_ID, vsomeip_test::TEST_SERVICE_METHOD_ID,
std::bind(&header_factory_test_service::on_message, this,
@@ -43,9 +46,7 @@ void header_factory_test_service::start()
void header_factory_test_service::stop()
{
VSOMEIP_INFO << "Stopping...";
- app_->unregister_message_handler(vsomeip_test::TEST_SERVICE_SERVICE_ID,
- vsomeip_test::TEST_SERVICE_INSTANCE_ID, vsomeip_test::TEST_SERVICE_METHOD_ID);
- app_->unregister_state_handler();
+ app_->clear_all_handler();
app_->stop();
std::thread t([](){ std::this_thread::sleep_for(std::chrono::microseconds(1000000 * 5));});
t.join();
diff --git a/test/initial_event_tests/conf/initial_event_test_diff_client_ids_diff_ports_master.json.in b/test/initial_event_tests/conf/initial_event_test_diff_client_ids_diff_ports_master.json.in
index 845cfe4..d7b5c7b 100644
--- a/test/initial_event_tests/conf/initial_event_test_diff_client_ids_diff_ports_master.json.in
+++ b/test/initial_event_tests/conf/initial_event_test_diff_client_ids_diff_ports_master.json.in
@@ -2,7 +2,7 @@
"unicast":"@TEST_IP_MASTER@",
"logging":
{
- "level":"info",
+ "level":"warning",
"console":"true",
"file":
{
@@ -70,6 +70,12 @@
"enable":"true",
"multicast":"224.0.0.1",
"port":"30490",
- "protocol":"udp"
+ "protocol":"udp",
+ "initial_delay_min" : "10",
+ "initial_delay_max" : "10",
+ "repetitions_base_delay" : "30",
+ "repetitions_max" : "3",
+ "cyclic_offer_delay" : "1000",
+ "ttl" : "3"
}
} \ No newline at end of file
diff --git a/test/initial_event_tests/conf/initial_event_test_diff_client_ids_diff_ports_same_service_id_master.json.in b/test/initial_event_tests/conf/initial_event_test_diff_client_ids_diff_ports_same_service_id_master.json.in
index 4348be8..6445025 100644
--- a/test/initial_event_tests/conf/initial_event_test_diff_client_ids_diff_ports_same_service_id_master.json.in
+++ b/test/initial_event_tests/conf/initial_event_test_diff_client_ids_diff_ports_same_service_id_master.json.in
@@ -2,7 +2,7 @@
"unicast":"@TEST_IP_MASTER@",
"logging":
{
- "level":"info",
+ "level":"warning",
"console":"true",
"file":
{
@@ -70,6 +70,12 @@
"enable":"true",
"multicast":"224.0.0.1",
"port":"30490",
- "protocol":"udp"
+ "protocol":"udp",
+ "initial_delay_min" : "10",
+ "initial_delay_max" : "10",
+ "repetitions_base_delay" : "30",
+ "repetitions_max" : "3",
+ "cyclic_offer_delay" : "1000",
+ "ttl" : "3"
}
} \ No newline at end of file
diff --git a/test/initial_event_tests/conf/initial_event_test_diff_client_ids_diff_ports_same_service_id_slave.json.in b/test/initial_event_tests/conf/initial_event_test_diff_client_ids_diff_ports_same_service_id_slave.json.in
index 5760288..c5dddc3 100644
--- a/test/initial_event_tests/conf/initial_event_test_diff_client_ids_diff_ports_same_service_id_slave.json.in
+++ b/test/initial_event_tests/conf/initial_event_test_diff_client_ids_diff_ports_same_service_id_slave.json.in
@@ -3,7 +3,7 @@
"diagnosis" : "0x63",
"logging":
{
- "level":"info",
+ "level":"warning",
"console":"true",
"file":
{
@@ -71,6 +71,12 @@
"enable":"true",
"multicast":"224.0.0.1",
"port":"30490",
- "protocol":"udp"
+ "protocol":"udp",
+ "initial_delay_min" : "10",
+ "initial_delay_max" : "10",
+ "repetitions_base_delay" : "30",
+ "repetitions_max" : "3",
+ "cyclic_offer_delay" : "1000",
+ "ttl" : "3"
}
} \ No newline at end of file
diff --git a/test/initial_event_tests/conf/initial_event_test_diff_client_ids_diff_ports_slave.json.in b/test/initial_event_tests/conf/initial_event_test_diff_client_ids_diff_ports_slave.json.in
index e60c7b8..3e7e286 100644
--- a/test/initial_event_tests/conf/initial_event_test_diff_client_ids_diff_ports_slave.json.in
+++ b/test/initial_event_tests/conf/initial_event_test_diff_client_ids_diff_ports_slave.json.in
@@ -3,7 +3,7 @@
"diagnosis" : "0x63",
"logging":
{
- "level":"info",
+ "level":"warning",
"console":"true",
"file":
{
@@ -71,6 +71,12 @@
"enable":"true",
"multicast":"224.0.0.1",
"port":"30490",
- "protocol":"udp"
+ "protocol":"udp",
+ "initial_delay_min" : "10",
+ "initial_delay_max" : "10",
+ "repetitions_base_delay" : "30",
+ "repetitions_max" : "3",
+ "cyclic_offer_delay" : "1000",
+ "ttl" : "3"
}
} \ No newline at end of file
diff --git a/test/initial_event_tests/conf/initial_event_test_diff_client_ids_partial_same_ports_master.json.in b/test/initial_event_tests/conf/initial_event_test_diff_client_ids_partial_same_ports_master.json.in
index 3a7c837..f168fae 100644
--- a/test/initial_event_tests/conf/initial_event_test_diff_client_ids_partial_same_ports_master.json.in
+++ b/test/initial_event_tests/conf/initial_event_test_diff_client_ids_partial_same_ports_master.json.in
@@ -2,7 +2,7 @@
"unicast":"@TEST_IP_MASTER@",
"logging":
{
- "level":"info",
+ "level":"warning",
"console":"true",
"file":
{
@@ -70,6 +70,12 @@
"enable":"true",
"multicast":"224.0.0.1",
"port":"30490",
- "protocol":"udp"
+ "protocol":"udp",
+ "initial_delay_min" : "10",
+ "initial_delay_max" : "10",
+ "repetitions_base_delay" : "30",
+ "repetitions_max" : "3",
+ "cyclic_offer_delay" : "1000",
+ "ttl" : "3"
}
} \ No newline at end of file
diff --git a/test/initial_event_tests/conf/initial_event_test_diff_client_ids_partial_same_ports_slave.json.in b/test/initial_event_tests/conf/initial_event_test_diff_client_ids_partial_same_ports_slave.json.in
index e296a42..30206a2 100644
--- a/test/initial_event_tests/conf/initial_event_test_diff_client_ids_partial_same_ports_slave.json.in
+++ b/test/initial_event_tests/conf/initial_event_test_diff_client_ids_partial_same_ports_slave.json.in
@@ -3,7 +3,7 @@
"diagnosis" : "0x63",
"logging":
{
- "level":"info",
+ "level":"warning",
"console":"true",
"file":
{
@@ -71,6 +71,12 @@
"enable":"true",
"multicast":"224.0.0.1",
"port":"30490",
- "protocol":"udp"
+ "protocol":"udp",
+ "initial_delay_min" : "10",
+ "initial_delay_max" : "10",
+ "repetitions_base_delay" : "30",
+ "repetitions_max" : "3",
+ "cyclic_offer_delay" : "1000",
+ "ttl" : "3"
}
} \ No newline at end of file
diff --git a/test/initial_event_tests/conf/initial_event_test_diff_client_ids_same_ports_master.json.in b/test/initial_event_tests/conf/initial_event_test_diff_client_ids_same_ports_master.json.in
index 17476ab..785e651 100644
--- a/test/initial_event_tests/conf/initial_event_test_diff_client_ids_same_ports_master.json.in
+++ b/test/initial_event_tests/conf/initial_event_test_diff_client_ids_same_ports_master.json.in
@@ -2,7 +2,7 @@
"unicast":"@TEST_IP_MASTER@",
"logging":
{
- "level":"info",
+ "level":"warning",
"console":"true",
"file":
{
@@ -70,6 +70,12 @@
"enable":"true",
"multicast":"224.0.0.1",
"port":"30490",
- "protocol":"udp"
+ "protocol":"udp",
+ "initial_delay_min" : "10",
+ "initial_delay_max" : "10",
+ "repetitions_base_delay" : "30",
+ "repetitions_max" : "3",
+ "cyclic_offer_delay" : "1000",
+ "ttl" : "3"
}
} \ No newline at end of file
diff --git a/test/initial_event_tests/conf/initial_event_test_diff_client_ids_same_ports_slave.json.in b/test/initial_event_tests/conf/initial_event_test_diff_client_ids_same_ports_slave.json.in
index 2f8d7d9..cfbdac4 100644
--- a/test/initial_event_tests/conf/initial_event_test_diff_client_ids_same_ports_slave.json.in
+++ b/test/initial_event_tests/conf/initial_event_test_diff_client_ids_same_ports_slave.json.in
@@ -3,7 +3,7 @@
"diagnosis" : "0x63",
"logging":
{
- "level":"info",
+ "level":"warning",
"console":"true",
"file":
{
@@ -71,6 +71,12 @@
"enable":"true",
"multicast":"224.0.0.1",
"port":"30490",
- "protocol":"udp"
+ "protocol":"udp",
+ "initial_delay_min" : "10",
+ "initial_delay_max" : "10",
+ "repetitions_base_delay" : "30",
+ "repetitions_max" : "3",
+ "cyclic_offer_delay" : "1000",
+ "ttl" : "3"
}
} \ No newline at end of file
diff --git a/test/initial_event_tests/conf/initial_event_test_same_client_ids_diff_ports_master.json.in b/test/initial_event_tests/conf/initial_event_test_same_client_ids_diff_ports_master.json.in
index 845cfe4..d7b5c7b 100644
--- a/test/initial_event_tests/conf/initial_event_test_same_client_ids_diff_ports_master.json.in
+++ b/test/initial_event_tests/conf/initial_event_test_same_client_ids_diff_ports_master.json.in
@@ -2,7 +2,7 @@
"unicast":"@TEST_IP_MASTER@",
"logging":
{
- "level":"info",
+ "level":"warning",
"console":"true",
"file":
{
@@ -70,6 +70,12 @@
"enable":"true",
"multicast":"224.0.0.1",
"port":"30490",
- "protocol":"udp"
+ "protocol":"udp",
+ "initial_delay_min" : "10",
+ "initial_delay_max" : "10",
+ "repetitions_base_delay" : "30",
+ "repetitions_max" : "3",
+ "cyclic_offer_delay" : "1000",
+ "ttl" : "3"
}
} \ No newline at end of file
diff --git a/test/initial_event_tests/conf/initial_event_test_same_client_ids_diff_ports_slave.json.in b/test/initial_event_tests/conf/initial_event_test_same_client_ids_diff_ports_slave.json.in
index df799e2..facc51a 100644
--- a/test/initial_event_tests/conf/initial_event_test_same_client_ids_diff_ports_slave.json.in
+++ b/test/initial_event_tests/conf/initial_event_test_same_client_ids_diff_ports_slave.json.in
@@ -3,7 +3,7 @@
"diagnosis" : "0x63",
"logging":
{
- "level":"info",
+ "level":"warning",
"console":"true",
"file":
{
@@ -71,6 +71,12 @@
"enable":"true",
"multicast":"224.0.0.1",
"port":"30490",
- "protocol":"udp"
+ "protocol":"udp",
+ "initial_delay_min" : "10",
+ "initial_delay_max" : "10",
+ "repetitions_base_delay" : "30",
+ "repetitions_max" : "3",
+ "cyclic_offer_delay" : "1000",
+ "ttl" : "3"
}
} \ No newline at end of file
diff --git a/test/initial_event_tests/conf/initial_event_test_same_client_ids_same_ports_master.json.in b/test/initial_event_tests/conf/initial_event_test_same_client_ids_same_ports_master.json.in
index 17476ab..785e651 100644
--- a/test/initial_event_tests/conf/initial_event_test_same_client_ids_same_ports_master.json.in
+++ b/test/initial_event_tests/conf/initial_event_test_same_client_ids_same_ports_master.json.in
@@ -2,7 +2,7 @@
"unicast":"@TEST_IP_MASTER@",
"logging":
{
- "level":"info",
+ "level":"warning",
"console":"true",
"file":
{
@@ -70,6 +70,12 @@
"enable":"true",
"multicast":"224.0.0.1",
"port":"30490",
- "protocol":"udp"
+ "protocol":"udp",
+ "initial_delay_min" : "10",
+ "initial_delay_max" : "10",
+ "repetitions_base_delay" : "30",
+ "repetitions_max" : "3",
+ "cyclic_offer_delay" : "1000",
+ "ttl" : "3"
}
} \ No newline at end of file
diff --git a/test/initial_event_tests/conf/initial_event_test_same_client_ids_same_ports_slave.json.in b/test/initial_event_tests/conf/initial_event_test_same_client_ids_same_ports_slave.json.in
index c8113c3..97b5d9f 100644
--- a/test/initial_event_tests/conf/initial_event_test_same_client_ids_same_ports_slave.json.in
+++ b/test/initial_event_tests/conf/initial_event_test_same_client_ids_same_ports_slave.json.in
@@ -3,7 +3,7 @@
"diagnosis" : "0x63",
"logging":
{
- "level":"info",
+ "level":"warning",
"console":"true",
"file":
{
@@ -71,6 +71,12 @@
"enable":"true",
"multicast":"224.0.0.1",
"port":"30490",
- "protocol":"udp"
+ "protocol":"udp",
+ "initial_delay_min" : "10",
+ "initial_delay_max" : "10",
+ "repetitions_base_delay" : "30",
+ "repetitions_max" : "3",
+ "cyclic_offer_delay" : "1000",
+ "ttl" : "3"
}
} \ No newline at end of file
diff --git a/test/initial_event_tests/initial_event_test_availability_checker.cpp b/test/initial_event_tests/initial_event_test_availability_checker.cpp
index 772df22..34c20c1 100644
--- a/test/initial_event_tests/initial_event_test_availability_checker.cpp
+++ b/test/initial_event_tests/initial_event_test_availability_checker.cpp
@@ -31,7 +31,10 @@ public:
wait_until_other_services_available_(true),
wait_for_stop_(true),
stop_thread_(std::bind(&initial_event_test_availability_checker::wait_for_stop, this)) {
- app_->init();
+ if (!app_->init()) {
+ VSOMEIP_ERROR << "Couldn't initialize application";
+ EXPECT_TRUE(false);
+ }
app_->register_state_handler(
std::bind(&initial_event_test_availability_checker::on_state, this,
std::placeholders::_1));
@@ -103,6 +106,7 @@ public:
}
VSOMEIP_INFO << "[" << std::setw(4) << std::setfill('0') << std::hex
<< client_number_ << "] all services are available. Going down";
+ app_->clear_all_handler();
app_->stop();
}
diff --git a/test/initial_event_tests/initial_event_test_client.cpp b/test/initial_event_tests/initial_event_test_client.cpp
index 5ee194e..d525632 100644
--- a/test/initial_event_tests/initial_event_test_client.cpp
+++ b/test/initial_event_tests/initial_event_test_client.cpp
@@ -33,7 +33,10 @@ public:
wait_until_other_services_available_(true),
wait_for_stop_(true),
stop_thread_(std::bind(&initial_event_test_client::wait_for_stop, this)) {
- app_->init();
+ if (!app_->init()) {
+ VSOMEIP_ERROR << "Couldn't initialize application";
+ EXPECT_TRUE(false);
+ }
app_->register_state_handler(
std::bind(&initial_event_test_client::on_state, this,
std::placeholders::_1));
@@ -164,7 +167,20 @@ public:
[&](const std::map<std::pair<vsomeip::service_t,
vsomeip::method_t>, std::uint32_t>::value_type& v)
{
- return v.second == initial_event_test::notifications_to_send;
+ if (v.second == initial_event_test::notifications_to_send) {
+ return true;
+ } else if (v.second >= initial_event_test::notifications_to_send){
+ VSOMEIP_WARNING
+ << " 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.";
+ return true;
+ } else {
+ return false;
+ }
}
);
}
@@ -173,7 +189,16 @@ public:
std::uint32_t received_twice(0);
std::uint32_t received_normal(0);
for(const auto &v : other_services_received_notification_) {
- if (v.second == initial_event_test::notifications_to_send * 2) {
+ if (v.second > initial_event_test::notifications_to_send * 2) {
+ VSOMEIP_WARNING
+ << " 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.";
+ received_twice++;
+ } else if (v.second == initial_event_test::notifications_to_send * 2) {
received_twice++;
} else if(v.second == initial_event_test::notifications_to_send) {
received_normal++;
@@ -181,7 +206,7 @@ public:
}
if( received_twice == (service_infos_.size() - 1) / 2
- && received_normal == (service_infos_.size() - 1) / 2 - 1) {
+ && received_normal == (service_infos_.size() - 1) / 2) {
// routing manager stub receives the notification
// - twice from external nodes
// - and normal from all internal nodes
@@ -196,14 +221,22 @@ public:
}
void wait_for_stop() {
- std::unique_lock<std::mutex> its_lock(stop_mutex_);
- while (wait_for_stop_) {
- stop_condition_.wait(its_lock);
+ {
+ std::unique_lock<std::mutex> its_lock(stop_mutex_);
+ while (wait_for_stop_) {
+ stop_condition_.wait(its_lock);
+ }
+ VSOMEIP_INFO << "[" << std::setw(4) << std::setfill('0') << std::hex
+ << client_number_
+ << "] Received notifications from all services, going down";
}
- VSOMEIP_INFO << "[" << std::setw(4) << std::setfill('0') << std::hex
- << client_number_
- << "] Received notifications from all services, going down";
-
+ for (const auto& i : service_infos_) {
+ if (i.service_id == 0xFFFF && i.instance_id == 0xFFFF) {
+ continue;
+ }
+ app_->unsubscribe(i.service_id, i.instance_id, i.eventgroup_id);
+ }
+ app_->clear_all_handler();
app_->stop();
}
diff --git a/test/initial_event_tests/initial_event_test_master_starter.sh b/test/initial_event_tests/initial_event_test_master_starter.sh
index 903104a..3273817 100755
--- a/test/initial_event_tests/initial_event_test_master_starter.sh
+++ b/test/initial_event_tests/initial_event_test_master_starter.sh
@@ -45,6 +45,22 @@ then
exit 1
fi
+print_starter_message () {
+cat <<End-of-message
+*******************************************************************************
+*******************************************************************************
+** Please now run:
+** initial_event_test_slave_starter.sh $PASSED_SUBSCRIPTION_TYPE $CLIENT_JSON_FILE $PASSED_SAME_SERVICE_ID_FLAG
+** from an external host to successfully complete this test.
+**
+** You probably will need to adapt the 'unicast' settings in
+** initial_event_test_diff_client_ids_diff_ports_master.json and
+** initial_event_test_diff_client_ids_diff_ports_slave.json to your personal setup.
+*******************************************************************************
+*******************************************************************************
+End-of-message
+}
+
# replace master with slave to be able display the correct json file to be used
# with the slave script
MASTER_JSON_FILE=$PASSED_JSON_FILE
@@ -73,11 +89,21 @@ unset VSOMEIP_APPLICATION_NAME
CLIENT_PIDS=()
# Start some clients
-for client_number in $(seq 9000 9009)
-do
- ./initial_event_test_client $client_number $PASSED_SUBSCRIPTION_TYPE $PASSED_SAME_SERVICE_ID_FLAG &
- CLIENT_PIDS+=($!)
-done
+if [[ $PASSED_SUBSCRIPTION_TYPE == "TCP_AND_UDP" ]]
+then
+ ./initial_event_test_client 9000 $PASSED_SUBSCRIPTION_TYPE $PASSED_SAME_SERVICE_ID_FLAG &
+ FIRST_PID=$!
+ sleep 1
+ print_starter_message
+ wait $FIRST_PID || FAIL=$(($FAIL+1))
+else
+ for client_number in $(seq 9000 9009)
+ do
+ ./initial_event_test_client $client_number $PASSED_SUBSCRIPTION_TYPE $PASSED_SAME_SERVICE_ID_FLAG &
+ CLIENT_PIDS+=($!)
+ done
+fi
+
# Start availability checker in order to wait until the services on the remote
# were started as well
@@ -86,19 +112,10 @@ PID_AVAILABILITY_CHECKER=$!
sleep 1
-cat <<End-of-message
-*******************************************************************************
-*******************************************************************************
-** Please now run:
-** initial_event_test_slave_starter.sh $PASSED_SUBSCRIPTION_TYPE $CLIENT_JSON_FILE $PASSED_SAME_SERVICE_ID_FLAG
-** from an external host to successfully complete this test.
-**
-** You probably will need to adapt the 'unicast' settings in
-** initial_event_test_diff_client_ids_diff_ports_master.json and
-** initial_event_test_diff_client_ids_diff_ports_slave.json to your personal setup.
-*******************************************************************************
-*******************************************************************************
-End-of-message
+if [ $PASSED_SUBSCRIPTION_TYPE != "TCP_AND_UDP" ]
+then
+ print_starter_message
+fi
# wait unti the services on the remote node were started as well
wait $PID_AVAILABILITY_CHECKER
@@ -107,11 +124,18 @@ wait $PID_AVAILABILITY_CHECKER
# the cached event from the routing manager daemon
sleep 2
-for client_number in $(seq 9010 9020)
-do
- ./initial_event_test_client $client_number $PASSED_SUBSCRIPTION_TYPE $PASSED_SAME_SERVICE_ID_FLAG &
- CLIENT_PIDS+=($!)
-done
+if [[ $PASSED_SUBSCRIPTION_TYPE == "TCP_AND_UDP" ]]
+then
+ ./initial_event_test_client 9010 $PASSED_SUBSCRIPTION_TYPE $PASSED_SAME_SERVICE_ID_FLAG &
+ FIRST_PID=$!
+ wait $FIRST_PID || FAIL=$(($FAIL+1))
+else
+ for client_number in $(seq 9010 9020)
+ do
+ ./initial_event_test_client $client_number $PASSED_SUBSCRIPTION_TYPE $PASSED_SAME_SERVICE_ID_FLAG &
+ CLIENT_PIDS+=($!)
+ done
+fi
# Wait until all clients are finished
diff --git a/test/initial_event_tests/initial_event_test_service.cpp b/test/initial_event_tests/initial_event_test_service.cpp
index 26a8e06..f02a493 100644
--- a/test/initial_event_tests/initial_event_test_service.cpp
+++ b/test/initial_event_tests/initial_event_test_service.cpp
@@ -27,7 +27,10 @@ public:
app_(vsomeip::runtime::get()->create_application()),
wait_until_registered_(true),
offer_thread_(std::bind(&initial_event_test_service::run, this)) {
- app_->init();
+ if (!app_->init()) {
+ VSOMEIP_ERROR << "Couldn't initialize application";
+ EXPECT_TRUE(false);
+ }
app_->register_state_handler(
std::bind(&initial_event_test_service::on_state, this,
std::placeholders::_1));
diff --git a/test/initial_event_tests/initial_event_test_slave_starter.sh b/test/initial_event_tests/initial_event_test_slave_starter.sh
index 9bd2d78..2b9eec8 100755
--- a/test/initial_event_tests/initial_event_test_slave_starter.sh
+++ b/test/initial_event_tests/initial_event_test_slave_starter.sh
@@ -69,11 +69,18 @@ unset VSOMEIP_APPLICATION_NAME
CLIENT_PIDS=()
# Start some clients
-for client_number in $(seq 9000 9009)
-do
- ./initial_event_test_client $client_number $PASSED_SUBSCRIPTION_TYPE $PASSED_SAME_SERVICE_ID_FLAG &
- CLIENT_PIDS+=($!)
-done
+if [[ $PASSED_SUBSCRIPTION_TYPE == "TCP_AND_UDP" ]]
+then
+ ./initial_event_test_client 9000 $PASSED_SUBSCRIPTION_TYPE $PASSED_SAME_SERVICE_ID_FLAG &
+ FIRST_PID=$!
+ wait $FIRST_PID || FAIL=$(($FAIL+1))
+else
+ for client_number in $(seq 9000 9009)
+ do
+ ./initial_event_test_client $client_number $PASSED_SUBSCRIPTION_TYPE $PASSED_SAME_SERVICE_ID_FLAG &
+ CLIENT_PIDS+=($!)
+ done
+fi
# Start availability checker in order to wait until the services on the remote
# were started as well
@@ -87,12 +94,18 @@ wait $PID_AVAILABILITY_CHECKER
# the cached event from the routing manager daemon
sleep 2
-for client_number in $(seq 9010 9020)
-do
- ./initial_event_test_client $client_number $PASSED_SUBSCRIPTION_TYPE $PASSED_SAME_SERVICE_ID_FLAG &
- CLIENT_PIDS+=($!)
-done
-
+if [[ $PASSED_SUBSCRIPTION_TYPE == "TCP_AND_UDP" ]]
+then
+ ./initial_event_test_client 9000 $PASSED_SUBSCRIPTION_TYPE $PASSED_SAME_SERVICE_ID_FLAG &
+ FIRST_PID=$!
+ wait $FIRST_PID || FAIL=$(($FAIL+1))
+else
+ for client_number in $(seq 9010 9020)
+ do
+ ./initial_event_test_client $client_number $PASSED_SUBSCRIPTION_TYPE $PASSED_SAME_SERVICE_ID_FLAG &
+ CLIENT_PIDS+=($!)
+ done
+fi
# Wait until all clients are finished
for job in ${CLIENT_PIDS[*]}
diff --git a/test/initial_event_tests/initial_event_test_stop_service.cpp b/test/initial_event_tests/initial_event_test_stop_service.cpp
index c8e519e..cd8a34a 100644
--- a/test/initial_event_tests/initial_event_test_stop_service.cpp
+++ b/test/initial_event_tests/initial_event_test_stop_service.cpp
@@ -33,7 +33,10 @@ public:
wait_for_stop_(true),
stop_thread_(std::bind(&initial_event_test_stop_service::wait_for_stop, this)),
called_other_node_(false) {
- app_->init();
+ if (!app_->init()) {
+ VSOMEIP_ERROR << "Couldn't initialize application";
+ EXPECT_TRUE(false);
+ }
app_->register_state_handler(
std::bind(&initial_event_test_stop_service::on_state, this,
std::placeholders::_1));
@@ -204,7 +207,7 @@ public:
wait_until_shutdown_method_called_ = false;
condition_.notify_one();
}
-
+ app_->clear_all_handler();
app_->stop();
}
diff --git a/test/magic_cookies_tests/magic_cookies_test_client.cpp b/test/magic_cookies_tests/magic_cookies_test_client.cpp
index fb335f9..35eba2e 100644
--- a/test/magic_cookies_tests/magic_cookies_test_client.cpp
+++ b/test/magic_cookies_tests/magic_cookies_test_client.cpp
@@ -26,7 +26,10 @@ public:
void init() {
VSOMEIP_INFO << "Initializing...";
- app_->init();
+ if (!app_->init()) {
+ VSOMEIP_ERROR << "Couldn't initialize application";
+ exit(EXIT_FAILURE);
+ }
app_->register_state_handler(
std::bind(
@@ -53,6 +56,7 @@ public:
void stop() {
VSOMEIP_INFO << "Stopping...";
+ app_->clear_all_handler();
app_->stop();
}
diff --git a/test/magic_cookies_tests/magic_cookies_test_service.cpp b/test/magic_cookies_tests/magic_cookies_test_service.cpp
index daa0fce..1a186b0 100644
--- a/test/magic_cookies_tests/magic_cookies_test_service.cpp
+++ b/test/magic_cookies_tests/magic_cookies_test_service.cpp
@@ -30,7 +30,10 @@ public:
void init() {
std::lock_guard<std::mutex> its_lock(mutex_);
- app_->init();
+ if (!app_->init()) {
+ VSOMEIP_ERROR << "Couldn't initialize application";
+ exit(EXIT_FAILURE);
+ }
app_->register_message_handler(
vsomeip_test::TEST_SERVICE_SERVICE_ID,
vsomeip_test::TEST_SERVICE_INSTANCE_ID,
@@ -112,6 +115,7 @@ public:
condition_.wait(its_lock);
}
std::this_thread::sleep_for(std::chrono::milliseconds(5));
+ app_->clear_all_handler();
app_->stop();
} else {
while (true) {
diff --git a/test/offer_tests/offer_test_client.cpp b/test/offer_tests/offer_test_client.cpp
index bb1cb84..d338f13 100644
--- a/test/offer_tests/offer_test_client.cpp
+++ b/test/offer_tests/offer_test_client.cpp
@@ -40,7 +40,10 @@ public:
last_received_counter_(0),
last_received_response_(std::chrono::steady_clock::now()),
number_received_responses_(0) {
- app_->init();
+ if (!app_->init()) {
+ VSOMEIP_ERROR << "Couldn't initialize application";
+ EXPECT_TRUE(false);
+ }
app_->register_state_handler(
std::bind(&offer_test_client::on_state, this,
std::placeholders::_1));
@@ -215,7 +218,7 @@ public:
stop_condition_.wait(its_lock);
}
VSOMEIP_INFO << "going down";
-
+ app_->clear_all_handler();
app_->stop();
}
diff --git a/test/offer_tests/offer_test_globals.hpp b/test/offer_tests/offer_test_globals.hpp
index 7163741..cc15c15 100644
--- a/test/offer_tests/offer_test_globals.hpp
+++ b/test/offer_tests/offer_test_globals.hpp
@@ -3,8 +3,8 @@
// 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 SUBSCRIBE_NOTIFY_TEST_GLOBALS_HPP_
-#define SUBSCRIBE_NOTIFY_TEST_GLOBALS_HPP_
+#ifndef OFFER_TEST_GLOBALS_HPP_
+#define OFFER_TEST_GLOBALS_HPP_
namespace offer_test {
@@ -22,4 +22,4 @@ struct service_info service = { 0x1111, 0x1, 0x1111, 0x1111, 0x1000, 0x1404 };
static constexpr int number_of_messages_to_send = 150;
}
-#endif /* SUBSCRIBE_NOTIFY_TEST_GLOBALS_HPP_ */
+#endif /* OFFER_TEST_GLOBALS_HPP_ */
diff --git a/test/offer_tests/offer_test_service.cpp b/test/offer_tests/offer_test_service.cpp
index a734ed3..2396d1a 100644
--- a/test/offer_tests/offer_test_service.cpp
+++ b/test/offer_tests/offer_test_service.cpp
@@ -35,7 +35,10 @@ public:
wait_until_registered_(true),
offer_thread_(std::bind(&offer_test_service::run, this)),
shutdown_method_called_(false) {
- app_->init();
+ if (!app_->init()) {
+ VSOMEIP_ERROR << "Couldn't initialize application";
+ EXPECT_TRUE(false);
+ }
app_->register_state_handler(
std::bind(&offer_test_service::on_state, this,
std::placeholders::_1));
@@ -94,6 +97,7 @@ public:
// this is will trigger a warning
app_->stop_offer_service(service_info_.service_id, service_info_.instance_id, 44, 4711);
app_->stop_offer_service(service_info_.service_id, service_info_.instance_id);
+ app_->clear_all_handler();
app_->stop();
}
diff --git a/test/offer_tests/offer_test_service_external.cpp b/test/offer_tests/offer_test_service_external.cpp
index d14103f..c031587 100644
--- a/test/offer_tests/offer_test_service_external.cpp
+++ b/test/offer_tests/offer_test_service_external.cpp
@@ -34,7 +34,10 @@ public:
wait_until_registered_(true),
wait_until_service_available_(true),
offer_thread_(std::bind(&offer_test_service::run, this)) {
- app_->init();
+ if (!app_->init()) {
+ VSOMEIP_ERROR << "Couldn't initialize application";
+ EXPECT_TRUE(false);
+ }
app_->register_state_handler(
std::bind(&offer_test_service::on_state, this,
std::placeholders::_1));
@@ -91,17 +94,19 @@ public:
void run() {
VSOMEIP_DEBUG << "[" << std::setw(4) << std::setfill('0') << std::hex
<< service_info_.service_id << "] Running";
- std::unique_lock<std::mutex> its_lock(mutex_);
- while (wait_until_registered_) {
- condition_.wait(its_lock);
- }
+ {
+ std::unique_lock<std::mutex> its_lock(mutex_);
+ while (wait_until_registered_) {
+ condition_.wait(its_lock);
+ }
- VSOMEIP_DEBUG << "[" << std::setw(4) << std::setfill('0') << std::hex
- << service_info_.service_id << "] Offering";
- offer();
+ VSOMEIP_DEBUG << "[" << std::setw(4) << std::setfill('0') << std::hex
+ << service_info_.service_id << "] Offering";
+ offer();
- while(wait_until_service_available_) {
- condition_.wait(its_lock);
+ while(wait_until_service_available_) {
+ condition_.wait(its_lock);
+ }
}
std::this_thread::sleep_for(std::chrono::seconds(1));
@@ -114,6 +119,7 @@ public:
msg->set_message_type(vsomeip::message_type_e::MT_REQUEST_NO_RETURN);
app_->send(msg);
std::this_thread::sleep_for(std::chrono::seconds(2));
+ app_->clear_all_handler();
app_->stop();
}
diff --git a/test/payload_tests/payload_test_client.cpp b/test/payload_tests/payload_test_client.cpp
index 60529fe..27759b7 100644
--- a/test/payload_tests/payload_test_client.cpp
+++ b/test/payload_tests/payload_test_client.cpp
@@ -42,7 +42,10 @@ payload_test_client::payload_test_client(
void payload_test_client::init()
{
- app_->init();
+ if (!app_->init()) {
+ VSOMEIP_ERROR << "Couldn't initialize application";
+ EXPECT_TRUE(false);
+ }
app_->register_state_handler(
std::bind(&payload_test_client::on_state, this,
@@ -74,11 +77,7 @@ void payload_test_client::stop()
{
shutdown_service();
}
- app_->unregister_availability_handler(vsomeip_test::TEST_SERVICE_SERVICE_ID,
- vsomeip_test::TEST_SERVICE_INSTANCE_ID);
- app_->unregister_state_handler();
- app_->unregister_message_handler(vsomeip::ANY_SERVICE,
- vsomeip_test::TEST_SERVICE_INSTANCE_ID, vsomeip::ANY_METHOD);
+ app_->clear_all_handler();
}
void payload_test_client::shutdown_service()
diff --git a/test/payload_tests/payload_test_client.hpp b/test/payload_tests/payload_test_client.hpp
index 7f9f9e5..8af352e 100644
--- a/test/payload_tests/payload_test_client.hpp
+++ b/test/payload_tests/payload_test_client.hpp
@@ -10,6 +10,7 @@
#include <vsomeip/vsomeip.hpp>
+#include <cmath>
#include <thread>
#include <mutex>
#include <condition_variable>
diff --git a/test/payload_tests/payload_test_service.cpp b/test/payload_tests/payload_test_service.cpp
index 6773743..74191da 100644
--- a/test/payload_tests/payload_test_service.cpp
+++ b/test/payload_tests/payload_test_service.cpp
@@ -23,7 +23,10 @@ void payload_test_service::init()
{
std::lock_guard<std::mutex> its_lock(mutex_);
- app_->init();
+ if (!app_->init()) {
+ VSOMEIP_ERROR << "Couldn't initialize application";
+ EXPECT_TRUE(false);
+ }
app_->register_message_handler(vsomeip_test::TEST_SERVICE_SERVICE_ID,
vsomeip_test::TEST_SERVICE_INSTANCE_ID, vsomeip_test::TEST_SERVICE_METHOD_ID,
std::bind(&payload_test_service::on_message, this,
@@ -49,11 +52,7 @@ void payload_test_service::start()
void payload_test_service::stop()
{
VSOMEIP_INFO << "Stopping...";
- app_->unregister_message_handler(vsomeip_test::TEST_SERVICE_SERVICE_ID,
- vsomeip_test::TEST_SERVICE_INSTANCE_ID, vsomeip_test::TEST_SERVICE_METHOD_ID);
- app_->unregister_message_handler(vsomeip_test::TEST_SERVICE_SERVICE_ID,
- vsomeip_test::TEST_SERVICE_INSTANCE_ID, vsomeip_test::TEST_SERVICE_METHOD_ID_SHUTDOWN);
- app_->unregister_state_handler();
+ app_->clear_all_handler();
app_->stop();
}
diff --git a/test/routing_tests/conf/external_local_routing_test_client_external.json.in b/test/routing_tests/conf/external_local_routing_test_client_external.json.in
index 3633538..958f196 100644
--- a/test/routing_tests/conf/external_local_routing_test_client_external.json.in
+++ b/test/routing_tests/conf/external_local_routing_test_client_external.json.in
@@ -1,6 +1,7 @@
{
"unicast" : "@TEST_IP_SLAVE@",
"netmask" : "255.255.255.0",
+ "diagnosis" : "0x16",
"logging" :
{
"level" : "debug",
@@ -18,7 +19,7 @@
[
{
"name" : "external_local_routing_test_client_external",
- "id" : "0x1344"
+ "id" : "0x1644"
}
],
@@ -27,7 +28,7 @@
{
"service" : "0x1234",
"instance" : "0x5678",
- "unicast" : "@TEST_IP_MASTER@",
+ "unicast" : "@TEST_IP_MASTER@",
"unreliable" : "30509"
}
],
diff --git a/test/routing_tests/conf/external_local_routing_test_service.json.in b/test/routing_tests/conf/external_local_routing_test_service.json.in
index 0ef1f77..a4deb82 100644
--- a/test/routing_tests/conf/external_local_routing_test_service.json.in
+++ b/test/routing_tests/conf/external_local_routing_test_service.json.in
@@ -1,5 +1,6 @@
{
"unicast" : "@TEST_IP_MASTER@",
+ "diagnosis":"0x12",
"logging" :
{
"level" : "debug",
diff --git a/test/routing_tests/local_routing_test_starter.sh b/test/routing_tests/conf/local_routing_test_starter.sh.bat.in
index fd82594..ab96d8e 100755
--- a/test/routing_tests/local_routing_test_starter.sh
+++ b/test/routing_tests/conf/local_routing_test_starter.sh.bat.in
@@ -59,7 +59,7 @@ do
wait $job || ((FAIL+=1))
done
-# Check if client and server both exited sucessfully and the service didnt't
+# Check if client and server both exited successfully and the service didnt't
# have any open
if [ $FAIL -eq 0 ]
then
diff --git a/test/routing_tests/conf/local_routing_test_starter.sh.in b/test/routing_tests/conf/local_routing_test_starter.sh.in
new file mode 100755
index 0000000..6f81609
--- /dev/null
+++ b/test/routing_tests/conf/local_routing_test_starter.sh.in
@@ -0,0 +1,79 @@
+#!/bin/bash
+# Copyright (C) 2015-2016 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 client and service with
+# one command. This is necessary as ctest - which is used to run the
+# tests - isn't able to start two binaries for one testcase. Therefore
+# the testcase simply executes this script. This script then runs client
+# and service and checks that both exit sucessfully.
+
+FAIL=0
+
+# Parameter 1: the pid to check
+check_tcp_udp_sockets_are_closed ()
+{
+ # Check that the service does not listen on any TCP/UDP socket
+ # or has any active connection via a TCP/UDP socket
+ # awk is used to avoid the case when a inode number is the same as a PID. The awk
+ # program filters the netstat output down to the protocol (1st field) and
+ # the PID/Program name (last field) fields.
+ SERVICE_SOCKETS_LISTENING=$(netstat -tulpen 2> /dev/null | awk '{print $1 "\t" $NF}' | grep $1 | wc -l)
+ if [ $SERVICE_SOCKETS_LISTENING -ne 0 ]
+ then
+ ((FAIL+=1))
+ fi
+
+ SERVICE_SOCKETS_CONNECTED=$(netstat -tupen 2> /dev/null | awk '{print $1 "\t" $NF}' | grep $1 | wc -l)
+ if [ $SERVICE_SOCKETS_CONNECTED -ne 0 ]
+ then
+ ((FAIL+=1))
+ fi
+}
+
+export VSOMEIP_CONFIGURATION=local_routing_test_service.json
+# start daemon
+../daemon/./vsomeipd &
+PID_VSOMEIPD=$!
+
+WAIT_PIDS=()
+# Start the service
+export VSOMEIP_APPLICATION_NAME=local_routing_test_service
+./local_routing_test_service &
+SERIVCE_PID=$!
+WAIT_PIDS+=($!)
+sleep 1;
+
+check_tcp_udp_sockets_are_closed $SERIVCE_PID
+
+# Start the client
+export VSOMEIP_APPLICATION_NAME=local_routing_test_client
+export VSOMEIP_CONFIGURATION=local_routing_test_client.json
+./local_routing_test_client &
+CLIENT_PID=$!
+WAIT_PIDS+=($!)
+
+check_tcp_udp_sockets_are_closed $SERIVCE_PID
+check_tcp_udp_sockets_are_closed $CLIENT_PID
+
+# Wait until client and service are finished
+for job in ${WAIT_PIDS[*]}
+do
+ # Fail gets incremented if either client or service exit
+ # with a non-zero exit code
+ wait $job || ((FAIL+=1))
+done
+
+kill $PID_VSOMEIPD
+sleep 1
+
+# Check if client and server both exited successfully and the service didnt't
+# have any open
+if [ $FAIL -eq 0 ]
+then
+ exit 0
+else
+ exit 1
+fi
diff --git a/test/routing_tests/external_local_routing_test_service.cpp b/test/routing_tests/external_local_routing_test_service.cpp
index e8d8891..d92f958 100644
--- a/test/routing_tests/external_local_routing_test_service.cpp
+++ b/test/routing_tests/external_local_routing_test_service.cpp
@@ -20,7 +20,10 @@ void external_local_routing_test_service::init()
{
std::lock_guard<std::mutex> its_lock(mutex_);
- app_->init();
+ if (!app_->init()) {
+ VSOMEIP_ERROR << "Couldn't initialize application";
+ EXPECT_TRUE(false);
+ }
app_->register_message_handler(vsomeip_test::TEST_SERVICE_SERVICE_ID,
vsomeip_test::TEST_SERVICE_INSTANCE_ID, vsomeip_test::TEST_SERVICE_METHOD_ID,
std::bind(&external_local_routing_test_service::on_message, this,
@@ -47,9 +50,7 @@ void external_local_routing_test_service::start()
void external_local_routing_test_service::stop()
{
VSOMEIP_INFO << "Stopping...";
- app_->unregister_message_handler(vsomeip_test::TEST_SERVICE_SERVICE_ID,
- vsomeip_test::TEST_SERVICE_INSTANCE_ID, vsomeip_test::TEST_SERVICE_METHOD_ID);
- app_->unregister_state_handler();
+ app_->clear_all_handler();
app_->stop();
}
diff --git a/test/routing_tests/local_routing_test_client.cpp b/test/routing_tests/local_routing_test_client.cpp
index a97c63c..f280eb2 100644
--- a/test/routing_tests/local_routing_test_client.cpp
+++ b/test/routing_tests/local_routing_test_client.cpp
@@ -20,7 +20,10 @@ local_routing_test_client::local_routing_test_client(bool _use_tcp) :
void local_routing_test_client::init()
{
- app_->init();
+ if (!app_->init()) {
+ VSOMEIP_ERROR << "Couldn't initialize application";
+ EXPECT_TRUE(false);
+ }
app_->register_state_handler(
std::bind(&local_routing_test_client::on_state, this,
@@ -47,12 +50,7 @@ void local_routing_test_client::start()
void local_routing_test_client::stop()
{
VSOMEIP_INFO << "Stopping...";
- app_->unregister_availability_handler(vsomeip_test::TEST_SERVICE_SERVICE_ID,
- vsomeip_test::TEST_SERVICE_INSTANCE_ID);
- app_->unregister_state_handler();
- app_->unregister_message_handler(vsomeip::ANY_SERVICE,
- vsomeip_test::TEST_SERVICE_INSTANCE_ID, vsomeip::ANY_METHOD);
-
+ app_->clear_all_handler();
app_->stop();
}
diff --git a/test/routing_tests/local_routing_test_client.json b/test/routing_tests/local_routing_test_client.json
index 4509768..2b4bdaa 100644
--- a/test/routing_tests/local_routing_test_client.json
+++ b/test/routing_tests/local_routing_test_client.json
@@ -1,6 +1,7 @@
{
"unicast" : "127.0.0.1",
"netmask" : "255.255.255.0",
+ "diagnosis":"0x12",
"logging" :
{
"level" : "debug",
@@ -18,7 +19,7 @@
[
{
"name" : "local_routing_test_client",
- "id" : "0x1343"
+ "id" : "0x1255"
}
],
diff --git a/test/routing_tests/local_routing_test_service.cpp b/test/routing_tests/local_routing_test_service.cpp
index 1f879dc..3a61ddf 100644
--- a/test/routing_tests/local_routing_test_service.cpp
+++ b/test/routing_tests/local_routing_test_service.cpp
@@ -19,7 +19,10 @@ void local_routing_test_service::init()
{
std::lock_guard<std::mutex> its_lock(mutex_);
- app_->init();
+ if (!app_->init()) {
+ VSOMEIP_ERROR << "Couldn't initialize application";
+ EXPECT_TRUE(false);
+ }
app_->register_message_handler(vsomeip_test::TEST_SERVICE_SERVICE_ID,
vsomeip_test::TEST_SERVICE_INSTANCE_ID, vsomeip_test::TEST_SERVICE_METHOD_ID,
std::bind(&local_routing_test_service::on_message, this,
@@ -41,9 +44,7 @@ void local_routing_test_service::start()
void local_routing_test_service::stop()
{
VSOMEIP_INFO << "Stopping...";
- app_->unregister_message_handler(vsomeip_test::TEST_SERVICE_SERVICE_ID,
- vsomeip_test::TEST_SERVICE_INSTANCE_ID, vsomeip_test::TEST_SERVICE_METHOD_ID);
- app_->unregister_state_handler();
+ app_->clear_all_handler();
app_->stop();
}
diff --git a/test/routing_tests/local_routing_test_service.json b/test/routing_tests/local_routing_test_service.json
index edd9be6..f5da8c6 100644
--- a/test/routing_tests/local_routing_test_service.json
+++ b/test/routing_tests/local_routing_test_service.json
@@ -1,5 +1,6 @@
{
"unicast" : "127.0.0.1",
+ "diagnosis":"0x12",
"logging" :
{
"level" : "debug",
diff --git a/test/someip_test_globals.hpp b/test/someip_test_globals.hpp
index fcde342..cb127e5 100644
--- a/test/someip_test_globals.hpp
+++ b/test/someip_test_globals.hpp
@@ -21,10 +21,10 @@ constexpr vsomeip::method_t TEST_SERVICE_METHOD_ID_SHUTDOWN = 0x7777;
constexpr vsomeip::client_t TEST_SERVICE_CLIENT_ID = 0x1277;
// Client local
-constexpr vsomeip::client_t TEST_CLIENT_CLIENT_ID = 0x1343;
+constexpr vsomeip::client_t TEST_CLIENT_CLIENT_ID = 0x1255;
// Client external
-constexpr vsomeip::client_t TEST_CLIENT_EXTERNAL_CLIENT_ID = 0x1344;
+constexpr vsomeip::client_t TEST_CLIENT_EXTERNAL_CLIENT_ID = 0x1644;
constexpr std::uint32_t NUMBER_OF_MESSAGES_TO_SEND = 10;
diff --git a/test/subscribe_notify_one_tests/conf/subscribe_notify_one_test_diff_client_ids_diff_ports_master.json.in b/test/subscribe_notify_one_tests/conf/subscribe_notify_one_test_diff_client_ids_diff_ports_master.json.in
index 27cc8c4..7acf45b 100644
--- a/test/subscribe_notify_one_tests/conf/subscribe_notify_one_test_diff_client_ids_diff_ports_master.json.in
+++ b/test/subscribe_notify_one_tests/conf/subscribe_notify_one_test_diff_client_ids_diff_ports_master.json.in
@@ -65,7 +65,13 @@
"enable":"true",
"multicast":"224.0.0.1",
"port":"30490",
- "protocol":"udp"
+ "protocol":"udp",
+ "initial_delay_min" : "10",
+ "initial_delay_max" : "10",
+ "repetitions_base_delay" : "30",
+ "repetitions_max" : "3",
+ "cyclic_offer_delay" : "1000",
+ "ttl" : "3"
},
"supports_selective_broadcasts" :
{
diff --git a/test/subscribe_notify_one_tests/conf/subscribe_notify_one_test_diff_client_ids_diff_ports_slave.json.in b/test/subscribe_notify_one_tests/conf/subscribe_notify_one_test_diff_client_ids_diff_ports_slave.json.in
index 1541410..7db7eed 100644
--- a/test/subscribe_notify_one_tests/conf/subscribe_notify_one_test_diff_client_ids_diff_ports_slave.json.in
+++ b/test/subscribe_notify_one_tests/conf/subscribe_notify_one_test_diff_client_ids_diff_ports_slave.json.in
@@ -65,7 +65,13 @@
"enable":"true",
"multicast":"224.0.0.1",
"port":"30490",
- "protocol":"udp"
+ "protocol":"udp",
+ "initial_delay_min" : "10",
+ "initial_delay_max" : "10",
+ "repetitions_base_delay" : "30",
+ "repetitions_max" : "3",
+ "cyclic_offer_delay" : "1000",
+ "ttl" : "3"
},
"supports_selective_broadcasts" :
{
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 9641690..fd3c047 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
@@ -36,7 +36,10 @@ public:
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)) {
- app_->init();
+ if (!app_->init()) {
+ VSOMEIP_ERROR << "Couldn't initialize application";
+ EXPECT_TRUE(false);
+ }
app_->register_state_handler(
std::bind(&subscribe_notify_one_test_service::on_state, this,
std::placeholders::_1));
@@ -362,6 +365,7 @@ public:
}
std::this_thread::sleep_for(std::chrono::seconds(6));
+ app_->clear_all_handler();
app_->stop();
}
diff --git a/test/subscribe_notify_tests/conf/subscribe_notify_test_diff_client_ids_diff_ports_autoconfig_master.json.in b/test/subscribe_notify_tests/conf/subscribe_notify_test_diff_client_ids_diff_ports_autoconfig_master.json.in
index 9c64a13..332f55f 100644
--- a/test/subscribe_notify_tests/conf/subscribe_notify_test_diff_client_ids_diff_ports_autoconfig_master.json.in
+++ b/test/subscribe_notify_tests/conf/subscribe_notify_test_diff_client_ids_diff_ports_autoconfig_master.json.in
@@ -49,6 +49,12 @@
"enable":"true",
"multicast":"224.0.0.1",
"port":"30490",
- "protocol":"udp"
+ "protocol":"udp",
+ "initial_delay_min" : "10",
+ "initial_delay_max" : "10",
+ "repetitions_base_delay" : "30",
+ "repetitions_max" : "3",
+ "cyclic_offer_delay" : "1000",
+ "ttl" : "3"
}
} \ No newline at end of file
diff --git a/test/subscribe_notify_tests/conf/subscribe_notify_test_diff_client_ids_diff_ports_autoconfig_slave.json.in b/test/subscribe_notify_tests/conf/subscribe_notify_test_diff_client_ids_diff_ports_autoconfig_slave.json.in
index 2d62dbe..ca25c33 100644
--- a/test/subscribe_notify_tests/conf/subscribe_notify_test_diff_client_ids_diff_ports_autoconfig_slave.json.in
+++ b/test/subscribe_notify_tests/conf/subscribe_notify_test_diff_client_ids_diff_ports_autoconfig_slave.json.in
@@ -49,6 +49,12 @@
"enable":"true",
"multicast":"224.0.0.1",
"port":"30490",
- "protocol":"udp"
+ "protocol":"udp",
+ "initial_delay_min" : "10",
+ "initial_delay_max" : "10",
+ "repetitions_base_delay" : "30",
+ "repetitions_max" : "3",
+ "cyclic_offer_delay" : "1000",
+ "ttl" : "3"
}
} \ No newline at end of file
diff --git a/test/subscribe_notify_tests/conf/subscribe_notify_test_diff_client_ids_diff_ports_master.json.in b/test/subscribe_notify_tests/conf/subscribe_notify_test_diff_client_ids_diff_ports_master.json.in
index a363388..87d1934 100644
--- a/test/subscribe_notify_tests/conf/subscribe_notify_test_diff_client_ids_diff_ports_master.json.in
+++ b/test/subscribe_notify_tests/conf/subscribe_notify_test_diff_client_ids_diff_ports_master.json.in
@@ -65,6 +65,12 @@
"enable":"true",
"multicast":"224.0.0.1",
"port":"30490",
- "protocol":"udp"
+ "protocol":"udp",
+ "initial_delay_min" : "10",
+ "initial_delay_max" : "10",
+ "repetitions_base_delay" : "30",
+ "repetitions_max" : "3",
+ "cyclic_offer_delay" : "1000",
+ "ttl" : "3"
}
} \ No newline at end of file
diff --git a/test/subscribe_notify_tests/conf/subscribe_notify_test_diff_client_ids_diff_ports_same_service_id_master.json.in b/test/subscribe_notify_tests/conf/subscribe_notify_test_diff_client_ids_diff_ports_same_service_id_master.json.in
index 38dadb8..a3cdab7 100644
--- a/test/subscribe_notify_tests/conf/subscribe_notify_test_diff_client_ids_diff_ports_same_service_id_master.json.in
+++ b/test/subscribe_notify_tests/conf/subscribe_notify_test_diff_client_ids_diff_ports_same_service_id_master.json.in
@@ -65,6 +65,12 @@
"enable":"true",
"multicast":"224.0.0.1",
"port":"30490",
- "protocol":"udp"
+ "protocol":"udp",
+ "initial_delay_min" : "10",
+ "initial_delay_max" : "10",
+ "repetitions_base_delay" : "30",
+ "repetitions_max" : "3",
+ "cyclic_offer_delay" : "1000",
+ "ttl" : "3"
}
} \ No newline at end of file
diff --git a/test/subscribe_notify_tests/conf/subscribe_notify_test_diff_client_ids_diff_ports_same_service_id_slave.json.in b/test/subscribe_notify_tests/conf/subscribe_notify_test_diff_client_ids_diff_ports_same_service_id_slave.json.in
index 6abc1e3..1ee1123 100644
--- a/test/subscribe_notify_tests/conf/subscribe_notify_test_diff_client_ids_diff_ports_same_service_id_slave.json.in
+++ b/test/subscribe_notify_tests/conf/subscribe_notify_test_diff_client_ids_diff_ports_same_service_id_slave.json.in
@@ -65,6 +65,12 @@
"enable":"true",
"multicast":"224.0.0.1",
"port":"30490",
- "protocol":"udp"
+ "protocol":"udp",
+ "initial_delay_min" : "10",
+ "initial_delay_max" : "10",
+ "repetitions_base_delay" : "30",
+ "repetitions_max" : "3",
+ "cyclic_offer_delay" : "1000",
+ "ttl" : "3"
}
} \ No newline at end of file
diff --git a/test/subscribe_notify_tests/conf/subscribe_notify_test_diff_client_ids_diff_ports_slave.json.in b/test/subscribe_notify_tests/conf/subscribe_notify_test_diff_client_ids_diff_ports_slave.json.in
index 7307fb2..43f0453 100644
--- a/test/subscribe_notify_tests/conf/subscribe_notify_test_diff_client_ids_diff_ports_slave.json.in
+++ b/test/subscribe_notify_tests/conf/subscribe_notify_test_diff_client_ids_diff_ports_slave.json.in
@@ -65,6 +65,12 @@
"enable":"true",
"multicast":"224.0.0.1",
"port":"30490",
- "protocol":"udp"
+ "protocol":"udp",
+ "initial_delay_min" : "10",
+ "initial_delay_max" : "10",
+ "repetitions_base_delay" : "30",
+ "repetitions_max" : "3",
+ "cyclic_offer_delay" : "1000",
+ "ttl" : "3"
}
} \ No newline at end of file
diff --git a/test/subscribe_notify_tests/conf/subscribe_notify_test_diff_client_ids_partial_same_ports_master.json.in b/test/subscribe_notify_tests/conf/subscribe_notify_test_diff_client_ids_partial_same_ports_master.json.in
index 8d8cfb0..fb7073f 100644
--- a/test/subscribe_notify_tests/conf/subscribe_notify_test_diff_client_ids_partial_same_ports_master.json.in
+++ b/test/subscribe_notify_tests/conf/subscribe_notify_test_diff_client_ids_partial_same_ports_master.json.in
@@ -65,6 +65,12 @@
"enable":"true",
"multicast":"224.0.0.1",
"port":"30490",
- "protocol":"udp"
+ "protocol":"udp",
+ "initial_delay_min" : "10",
+ "initial_delay_max" : "10",
+ "repetitions_base_delay" : "30",
+ "repetitions_max" : "3",
+ "cyclic_offer_delay" : "1000",
+ "ttl" : "3"
}
} \ No newline at end of file
diff --git a/test/subscribe_notify_tests/conf/subscribe_notify_test_diff_client_ids_partial_same_ports_slave.json.in b/test/subscribe_notify_tests/conf/subscribe_notify_test_diff_client_ids_partial_same_ports_slave.json.in
index b429266..27f9f34 100644
--- a/test/subscribe_notify_tests/conf/subscribe_notify_test_diff_client_ids_partial_same_ports_slave.json.in
+++ b/test/subscribe_notify_tests/conf/subscribe_notify_test_diff_client_ids_partial_same_ports_slave.json.in
@@ -65,6 +65,12 @@
"enable":"true",
"multicast":"224.0.0.1",
"port":"30490",
- "protocol":"udp"
+ "protocol":"udp",
+ "initial_delay_min" : "10",
+ "initial_delay_max" : "10",
+ "repetitions_base_delay" : "30",
+ "repetitions_max" : "3",
+ "cyclic_offer_delay" : "1000",
+ "ttl" : "3"
}
} \ No newline at end of file
diff --git a/test/subscribe_notify_tests/conf/subscribe_notify_test_diff_client_ids_same_ports_master.json.in b/test/subscribe_notify_tests/conf/subscribe_notify_test_diff_client_ids_same_ports_master.json.in
index 09788c9..a60ee3d 100644
--- a/test/subscribe_notify_tests/conf/subscribe_notify_test_diff_client_ids_same_ports_master.json.in
+++ b/test/subscribe_notify_tests/conf/subscribe_notify_test_diff_client_ids_same_ports_master.json.in
@@ -65,6 +65,12 @@
"enable":"true",
"multicast":"224.0.0.1",
"port":"30490",
- "protocol":"udp"
+ "protocol":"udp",
+ "initial_delay_min" : "10",
+ "initial_delay_max" : "10",
+ "repetitions_base_delay" : "30",
+ "repetitions_max" : "3",
+ "cyclic_offer_delay" : "1000",
+ "ttl" : "3"
}
} \ No newline at end of file
diff --git a/test/subscribe_notify_tests/conf/subscribe_notify_test_diff_client_ids_same_ports_slave.json.in b/test/subscribe_notify_tests/conf/subscribe_notify_test_diff_client_ids_same_ports_slave.json.in
index 9c4d63c..9854b75 100644
--- a/test/subscribe_notify_tests/conf/subscribe_notify_test_diff_client_ids_same_ports_slave.json.in
+++ b/test/subscribe_notify_tests/conf/subscribe_notify_test_diff_client_ids_same_ports_slave.json.in
@@ -65,6 +65,12 @@
"enable":"true",
"multicast":"224.0.0.1",
"port":"30490",
- "protocol":"udp"
+ "protocol":"udp",
+ "initial_delay_min" : "10",
+ "initial_delay_max" : "10",
+ "repetitions_base_delay" : "30",
+ "repetitions_max" : "3",
+ "cyclic_offer_delay" : "1000",
+ "ttl" : "3"
}
} \ No newline at end of file
diff --git a/test/subscribe_notify_tests/conf/subscribe_notify_test_same_client_ids_diff_ports_master.json.in b/test/subscribe_notify_tests/conf/subscribe_notify_test_same_client_ids_diff_ports_master.json.in
index a363388..87d1934 100644
--- a/test/subscribe_notify_tests/conf/subscribe_notify_test_same_client_ids_diff_ports_master.json.in
+++ b/test/subscribe_notify_tests/conf/subscribe_notify_test_same_client_ids_diff_ports_master.json.in
@@ -65,6 +65,12 @@
"enable":"true",
"multicast":"224.0.0.1",
"port":"30490",
- "protocol":"udp"
+ "protocol":"udp",
+ "initial_delay_min" : "10",
+ "initial_delay_max" : "10",
+ "repetitions_base_delay" : "30",
+ "repetitions_max" : "3",
+ "cyclic_offer_delay" : "1000",
+ "ttl" : "3"
}
} \ No newline at end of file
diff --git a/test/subscribe_notify_tests/conf/subscribe_notify_test_same_client_ids_diff_ports_slave.json.in b/test/subscribe_notify_tests/conf/subscribe_notify_test_same_client_ids_diff_ports_slave.json.in
index bc38eaf..3786f74 100644
--- a/test/subscribe_notify_tests/conf/subscribe_notify_test_same_client_ids_diff_ports_slave.json.in
+++ b/test/subscribe_notify_tests/conf/subscribe_notify_test_same_client_ids_diff_ports_slave.json.in
@@ -65,6 +65,12 @@
"enable":"true",
"multicast":"224.0.0.1",
"port":"30490",
- "protocol":"udp"
+ "protocol":"udp",
+ "initial_delay_min" : "10",
+ "initial_delay_max" : "10",
+ "repetitions_base_delay" : "30",
+ "repetitions_max" : "3",
+ "cyclic_offer_delay" : "1000",
+ "ttl" : "3"
}
} \ No newline at end of file
diff --git a/test/subscribe_notify_tests/conf/subscribe_notify_test_same_client_ids_same_ports_master.json.in b/test/subscribe_notify_tests/conf/subscribe_notify_test_same_client_ids_same_ports_master.json.in
index 09788c9..a60ee3d 100644
--- a/test/subscribe_notify_tests/conf/subscribe_notify_test_same_client_ids_same_ports_master.json.in
+++ b/test/subscribe_notify_tests/conf/subscribe_notify_test_same_client_ids_same_ports_master.json.in
@@ -65,6 +65,12 @@
"enable":"true",
"multicast":"224.0.0.1",
"port":"30490",
- "protocol":"udp"
+ "protocol":"udp",
+ "initial_delay_min" : "10",
+ "initial_delay_max" : "10",
+ "repetitions_base_delay" : "30",
+ "repetitions_max" : "3",
+ "cyclic_offer_delay" : "1000",
+ "ttl" : "3"
}
} \ No newline at end of file
diff --git a/test/subscribe_notify_tests/conf/subscribe_notify_test_same_client_ids_same_ports_slave.json.in b/test/subscribe_notify_tests/conf/subscribe_notify_test_same_client_ids_same_ports_slave.json.in
index caed298..cbe671e 100644
--- a/test/subscribe_notify_tests/conf/subscribe_notify_test_same_client_ids_same_ports_slave.json.in
+++ b/test/subscribe_notify_tests/conf/subscribe_notify_test_same_client_ids_same_ports_slave.json.in
@@ -65,6 +65,12 @@
"enable":"true",
"multicast":"224.0.0.1",
"port":"30490",
- "protocol":"udp"
+ "protocol":"udp",
+ "initial_delay_min" : "10",
+ "initial_delay_max" : "10",
+ "repetitions_base_delay" : "30",
+ "repetitions_max" : "3",
+ "cyclic_offer_delay" : "1000",
+ "ttl" : "3"
}
} \ No newline at end of file
diff --git a/test/subscribe_notify_tests/subscribe_notify_test_service.cpp b/test/subscribe_notify_tests/subscribe_notify_test_service.cpp
index a07f00c..9dd3bbb 100644
--- a/test/subscribe_notify_tests/subscribe_notify_test_service.cpp
+++ b/test/subscribe_notify_tests/subscribe_notify_test_service.cpp
@@ -37,7 +37,10 @@ public:
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)) {
- app_->init();
+ if (!app_->init()) {
+ VSOMEIP_ERROR << "Couldn't initialize application";
+ EXPECT_TRUE(false);
+ }
app_->register_state_handler(
std::bind(&subscribe_notify_test_service::on_state, this,
std::placeholders::_1));
@@ -356,6 +359,7 @@ public:
}
std::this_thread::sleep_for(std::chrono::seconds(1));
+ app_->clear_all_handler();
app_->stop();
}