From 78be04b467566633318a277ccd2d968c1c4e46bf Mon Sep 17 00:00:00 2001 From: Dirk Huss Date: Wed, 25 Nov 2015 15:11:49 +0100 Subject: vSomeIP 2.0.0 --- .gitignore | 19 + CMakeLists.txt | 672 +++++---- README | 279 ++-- config/vsomeip-local-tcp-client.json | 163 +-- config/vsomeip-local-tcp-service.json | 153 +- config/vsomeip-local.json | 172 ++- config/vsomeip-magic-cookies-client.json | 83 -- config/vsomeip-magic-cookies-service.json | 83 -- config/vsomeip-tcp-client.json | 162 +-- config/vsomeip-tcp-service.json | 178 ++- config/vsomeip-test.json | 130 -- config/vsomeip-udp-client.json | 79 +- config/vsomeip-udp-service.json | 184 ++- config/vsomeip.json | 113 +- daemon/CMakeLists.txt | 17 + daemon/vsomeipd.cpp | 83 ++ examples/CMakeLists.txt | 37 + examples/hello_world/hello_world_client.cpp | 26 +- examples/hello_world/hello_world_service.cpp | 14 +- examples/hello_world/readme | 4 +- examples/notify-sample.cpp | 43 +- examples/readme.txt | 8 +- examples/request-sample.cpp | 341 ++--- examples/response-sample.cpp | 45 +- examples/sample-ids.hpp | 18 +- examples/subscribe-sample.cpp | 233 +-- examples/vsomeipd.cpp | 18 - exportmap.gcc | 70 +- .../configuration/include/configuration.hpp | 89 ++ .../configuration/include/configuration_impl.hpp | 117 +- .../configuration/include/internal.hpp.in | 105 +- implementation/configuration/include/service.hpp | 4 +- .../configuration/include/servicegroup.hpp | 27 - implementation/configuration/src/configuration.cpp | 9 +- .../configuration/src/configuration_impl.cpp | 737 +++++----- implementation/endpoints/include/buffer.hpp | 3 +- .../endpoints/include/client_endpoint_impl.hpp | 18 +- implementation/endpoints/include/endpoint.hpp | 4 + .../endpoints/include/endpoint_definition.hpp | 14 +- implementation/endpoints/include/endpoint_host.hpp | 2 + implementation/endpoints/include/endpoint_impl.hpp | 16 +- .../include/local_client_endpoint_impl.hpp | 124 +- .../include/local_server_endpoint_impl.hpp | 211 +-- .../endpoints/include/server_endpoint_impl.hpp | 13 +- .../endpoints/include/tcp_client_endpoint_impl.hpp | 13 +- .../endpoints/include/tcp_server_endpoint_impl.hpp | 24 +- .../endpoints/include/udp_client_endpoint_impl.hpp | 11 +- .../endpoints/include/udp_server_endpoint_impl.hpp | 10 +- .../include/virtual_server_endpoint_impl.hpp | 62 + .../endpoints/src/client_endpoint_impl.cpp | 67 +- .../endpoints/src/endpoint_definition.cpp | 33 +- implementation/endpoints/src/endpoint_impl.cpp | 33 +- .../endpoints/src/local_client_endpoint_impl.cpp | 77 +- .../endpoints/src/local_server_endpoint_impl.cpp | 528 +++---- .../endpoints/src/server_endpoint_impl.cpp | 81 +- .../endpoints/src/tcp_client_endpoint_impl.cpp | 109 +- .../endpoints/src/tcp_server_endpoint_impl.cpp | 585 ++++---- .../endpoints/src/udp_client_endpoint_impl.cpp | 101 +- .../endpoints/src/udp_server_endpoint_impl.cpp | 505 +++---- .../endpoints/src/virtual_server_endpoint_impl.cpp | 114 ++ implementation/logging/include/logger.hpp | 48 + implementation/logging/include/logger_impl.hpp | 6 +- implementation/logging/src/logger_impl.cpp | 16 +- .../message/include/message_header_impl.hpp | 6 +- implementation/message/src/deserializer.cpp | 202 +-- implementation/message/src/message_base_impl.cpp | 46 +- implementation/message/src/message_header_impl.cpp | 87 +- implementation/message/src/message_impl.cpp | 26 +- implementation/message/src/payload_impl.cpp | 42 +- implementation/message/src/serializer.cpp | 128 +- implementation/routing/include/event.hpp | 9 + implementation/routing/include/eventgroupinfo.hpp | 5 +- implementation/routing/include/routing_manager.hpp | 13 +- .../routing/include/routing_manager_host.hpp | 2 +- .../routing/include/routing_manager_impl.hpp | 107 +- .../routing/include/routing_manager_proxy.hpp | 70 +- .../routing/include/routing_manager_stub.hpp | 10 +- .../routing/include/routing_manager_stub_host.hpp | 18 +- implementation/routing/include/servicegroup.hpp | 41 - implementation/routing/include/serviceinfo.hpp | 6 +- implementation/routing/src/event.cpp | 116 +- implementation/routing/src/eventgroupinfo.cpp | 65 +- .../routing/src/routing_manager_impl.cpp | 1520 ++++++++++++++------ .../routing/src/routing_manager_proxy.cpp | 401 ++++-- .../routing/src/routing_manager_stub.cpp | 740 +++++----- implementation/routing/src/servicegroup.cpp | 70 - implementation/routing/src/serviceinfo.cpp | 9 +- .../runtime/include/application_impl.hpp | 53 +- implementation/runtime/include/runtime_impl.hpp | 11 +- implementation/runtime/src/application_impl.cpp | 311 +++- implementation/runtime/src/runtime_impl.cpp | 20 +- .../service_discovery/include/defines.hpp | 19 +- .../service_discovery/include/entry_impl.hpp | 8 +- .../include/enumeration_types.hpp | 7 + .../service_discovery/include/ip_option_impl.hpp | 41 + .../service_discovery/include/ipv4_option_impl.hpp | 17 +- .../service_discovery/include/ipv6_option_impl.hpp | 19 +- .../service_discovery/include/message_impl.hpp | 2 + .../include/service_discovery.hpp | 7 +- .../include/service_discovery_fsm.hpp | 11 +- .../include/service_discovery_host.hpp | 16 +- .../include/service_discovery_impl.hpp | 56 +- .../service_discovery/include/subscription.hpp | 5 +- .../src/configuration_option_impl.cpp | 8 +- .../service_discovery/src/entry_impl.cpp | 25 +- .../service_discovery/src/eventgroupentry_impl.cpp | 7 +- .../service_discovery/src/ip_option_impl.cpp | 59 + .../service_discovery/src/ipv4_option_impl.cpp | 46 +- .../service_discovery/src/ipv6_option_impl.cpp | 43 +- .../service_discovery/src/message_impl.cpp | 44 +- .../service_discovery/src/option_impl.cpp | 21 +- .../src/service_discovery_fsm.cpp | 99 +- .../src/service_discovery_impl.cpp | 816 +++++++---- .../service_discovery/src/subscription.cpp | 10 +- implementation/utility/include/byteorder.hpp | 42 +- implementation/utility/include/utility.hpp | 13 +- implementation/utility/src/utility.cpp | 88 +- interface/vsomeip/application.hpp | 52 +- interface/vsomeip/configuration.hpp | 93 -- interface/vsomeip/constants.hpp | 7 +- interface/vsomeip/defines.hpp | 8 - interface/vsomeip/deserializable.hpp | 24 - interface/vsomeip/enumeration_types.hpp | 6 +- interface/vsomeip/handler.hpp | 2 +- interface/vsomeip/internal/deserializable.hpp | 24 + interface/vsomeip/internal/serializable.hpp | 30 + interface/vsomeip/logger.hpp | 48 - interface/vsomeip/message_base.hpp | 5 +- interface/vsomeip/payload.hpp | 5 +- interface/vsomeip/runtime.hpp | 6 +- interface/vsomeip/serializable.hpp | 25 - interface/vsomeip/vsomeip.hpp | 5 +- test/CMakeLists.txt | 1250 ++++++++++------ test/application_tests/application_test.cpp | 174 +++ test/application_tests/application_test.json | 45 + .../application_test_no_dispatch_threads.json | 37 + test/application_tests/application_test_starter.sh | 31 + test/big_payload_tests/big_payload_test_client.cpp | 185 +++ test/big_payload_tests/big_payload_test_client.hpp | 49 + .../big_payload_test_client_local_start.sh | 10 + .../big_payload_test_client_start.sh | 10 + .../big_payload_test_external_starter.sh | 48 + .../big_payload_tests/big_payload_test_globals.hpp | 17 + test/big_payload_tests/big_payload_test_local.json | 54 + .../big_payload_test_local_starter.sh | 38 + .../big_payload_tests/big_payload_test_service.cpp | 163 +++ .../big_payload_tests/big_payload_test_service.hpp | 43 + .../big_payload_test_service_external_start.sh | 10 + .../big_payload_test_service_local_start.sh | 10 + .../conf/big_payload_test_tcp_client.json.in | 43 + .../conf/big_payload_test_tcp_service.json.in | 54 + test/client_id_tests/client_id_test_globals.hpp | 32 + .../client_id_test_master_starter.sh | 64 + test/client_id_tests/client_id_test_service.cpp | 248 ++++ .../client_id_test_slave_starter.sh | 50 + ..._test_diff_client_ids_diff_ports_master.json.in | 56 + ...d_test_diff_client_ids_diff_ports_slave.json.in | 70 + ..._test_diff_client_ids_same_ports_master.json.in | 56 + ...d_test_diff_client_ids_same_ports_slave.json.in | 70 + ..._test_same_client_ids_diff_ports_master.json.in | 56 + ...d_test_same_client_ids_diff_ports_slave.json.in | 70 + ..._test_same_client_ids_same_ports_master.json.in | 56 + ...d_test_same_client_ids_same_ports_slave.json.in | 70 + test/configuration-test.cpp | 214 --- .../configuration-test-deprecated.json | 131 ++ test/configuration_tests/configuration-test.cpp | 346 +++++ test/configuration_tests/configuration-test.json | 103 ++ .../header_factory_test_client.cpp | 45 +- .../header_factory_test_client.hpp | 2 +- .../header_factory_test_client.json | 121 +- .../header_factory_test_client_start.sh | 2 +- .../header_factory_test_send_receive_starter.sh | 4 +- .../header_factory_test_service.cpp | 27 +- .../header_factory_test_service.hpp | 2 +- .../header_factory_test_service.json | 189 ++- .../header_factory_test_service_start.sh | 2 +- test/magic-cookies-test-client.cpp | 179 --- test/magic_cookies_test_client_start.sh | 9 - test/magic_cookies_test_service_start.sh | 9 - test/magic_cookies_test_starter.sh | 90 -- .../conf/magic_cookies_test_client.json.in | 85 ++ .../conf/magic_cookies_test_service.json.in | 88 ++ .../magic_cookies_test_client.cpp | 192 +++ .../magic_cookies_test_client_start.sh | 9 + .../magic_cookies_test_service.cpp | 155 ++ .../magic_cookies_test_service_start.sh | 9 + .../magic_cookies_test_starter.sh | 90 ++ ...rnal_local_payload_test_client_external.json.in | 48 + ...xternal_local_payload_test_client_local.json.in | 49 + .../external_local_payload_test_service.json.in | 46 + ...xternal_local_payload_test_client_external.json | 54 - ...nal_local_payload_test_client_external_start.sh | 2 +- ...l_local_payload_test_client_external_starter.sh | 4 +- .../external_local_payload_test_client_local.json | 54 - ...yload_test_client_local_and_external_starter.sh | 6 +- ...ternal_local_payload_test_client_local_start.sh | 2 +- ...rnal_local_payload_test_client_local_starter.sh | 4 +- .../external_local_payload_test_service.json | 67 - ...l_payload_test_service_client_external_start.sh | 2 +- .../external_local_payload_test_service_start.sh | 2 +- test/payload_tests/local_payload_test_client.json | 15 +- .../local_payload_test_client_start.sh | 2 +- test/payload_tests/local_payload_test_service.json | 31 +- .../local_payload_test_service_start.sh | 2 +- test/payload_tests/local_payload_test_starter.sh | 4 +- test/payload_tests/payload_test_client.cpp | 63 +- test/payload_tests/payload_test_client.hpp | 2 +- test/payload_tests/payload_test_service.cpp | 33 +- test/payload_tests/payload_test_service.hpp | 2 +- test/payload_tests/stopwatch.cpp | 18 +- test/payload_tests/stopwatch.hpp | 4 +- test/readme.txt | 99 +- ...rnal_local_routing_test_client_external.json.in | 43 + .../external_local_routing_test_service.json.in | 41 + ...xternal_local_routing_test_client_external.json | 49 - ...nal_local_routing_test_client_external_start.sh | 2 +- .../external_local_routing_test_service.cpp | 19 +- .../external_local_routing_test_service.hpp | 4 +- .../external_local_routing_test_service.json | 62 - .../external_local_routing_test_service_start.sh | 2 +- .../external_local_routing_test_starter.sh | 4 +- test/routing_tests/local_routing_test_client.cpp | 50 +- test/routing_tests/local_routing_test_client.hpp | 4 +- test/routing_tests/local_routing_test_client.json | 10 +- .../local_routing_test_client_start.sh | 2 +- test/routing_tests/local_routing_test_service.cpp | 30 +- test/routing_tests/local_routing_test_service.hpp | 8 +- test/routing_tests/local_routing_test_service.json | 31 +- .../local_routing_test_service_start.sh | 2 +- test/routing_tests/local_routing_test_starter.sh | 4 +- test/someip_test_globals.hpp | 2 + vsomeip.pc.in | 11 + 232 files changed, 12450 insertions(+), 7163 deletions(-) delete mode 100644 config/vsomeip-magic-cookies-client.json delete mode 100644 config/vsomeip-magic-cookies-service.json delete mode 100644 config/vsomeip-test.json create mode 100644 daemon/CMakeLists.txt create mode 100644 daemon/vsomeipd.cpp create mode 100644 examples/CMakeLists.txt delete mode 100644 examples/vsomeipd.cpp create mode 100644 implementation/configuration/include/configuration.hpp delete mode 100644 implementation/configuration/include/servicegroup.hpp create mode 100644 implementation/endpoints/include/virtual_server_endpoint_impl.hpp create mode 100644 implementation/endpoints/src/virtual_server_endpoint_impl.cpp create mode 100644 implementation/logging/include/logger.hpp delete mode 100644 implementation/routing/include/servicegroup.hpp delete mode 100644 implementation/routing/src/servicegroup.cpp create mode 100644 implementation/service_discovery/include/ip_option_impl.hpp create mode 100644 implementation/service_discovery/src/ip_option_impl.cpp delete mode 100644 interface/vsomeip/configuration.hpp delete mode 100644 interface/vsomeip/deserializable.hpp create mode 100644 interface/vsomeip/internal/deserializable.hpp create mode 100644 interface/vsomeip/internal/serializable.hpp delete mode 100644 interface/vsomeip/logger.hpp delete mode 100644 interface/vsomeip/serializable.hpp create mode 100644 test/application_tests/application_test.cpp create mode 100644 test/application_tests/application_test.json create mode 100644 test/application_tests/application_test_no_dispatch_threads.json create mode 100755 test/application_tests/application_test_starter.sh create mode 100644 test/big_payload_tests/big_payload_test_client.cpp create mode 100644 test/big_payload_tests/big_payload_test_client.hpp create mode 100755 test/big_payload_tests/big_payload_test_client_local_start.sh create mode 100755 test/big_payload_tests/big_payload_test_client_start.sh create mode 100755 test/big_payload_tests/big_payload_test_external_starter.sh create mode 100644 test/big_payload_tests/big_payload_test_globals.hpp create mode 100644 test/big_payload_tests/big_payload_test_local.json create mode 100755 test/big_payload_tests/big_payload_test_local_starter.sh create mode 100644 test/big_payload_tests/big_payload_test_service.cpp create mode 100644 test/big_payload_tests/big_payload_test_service.hpp create mode 100755 test/big_payload_tests/big_payload_test_service_external_start.sh create mode 100755 test/big_payload_tests/big_payload_test_service_local_start.sh create mode 100644 test/big_payload_tests/conf/big_payload_test_tcp_client.json.in create mode 100644 test/big_payload_tests/conf/big_payload_test_tcp_service.json.in create mode 100644 test/client_id_tests/client_id_test_globals.hpp create mode 100755 test/client_id_tests/client_id_test_master_starter.sh create mode 100644 test/client_id_tests/client_id_test_service.cpp create mode 100755 test/client_id_tests/client_id_test_slave_starter.sh create mode 100644 test/client_id_tests/conf/client_id_test_diff_client_ids_diff_ports_master.json.in create mode 100644 test/client_id_tests/conf/client_id_test_diff_client_ids_diff_ports_slave.json.in create mode 100644 test/client_id_tests/conf/client_id_test_diff_client_ids_same_ports_master.json.in create mode 100644 test/client_id_tests/conf/client_id_test_diff_client_ids_same_ports_slave.json.in create mode 100644 test/client_id_tests/conf/client_id_test_same_client_ids_diff_ports_master.json.in create mode 100644 test/client_id_tests/conf/client_id_test_same_client_ids_diff_ports_slave.json.in create mode 100644 test/client_id_tests/conf/client_id_test_same_client_ids_same_ports_master.json.in create mode 100644 test/client_id_tests/conf/client_id_test_same_client_ids_same_ports_slave.json.in delete mode 100644 test/configuration-test.cpp create mode 100644 test/configuration_tests/configuration-test-deprecated.json create mode 100644 test/configuration_tests/configuration-test.cpp create mode 100644 test/configuration_tests/configuration-test.json delete mode 100644 test/magic-cookies-test-client.cpp delete mode 100755 test/magic_cookies_test_client_start.sh delete mode 100755 test/magic_cookies_test_service_start.sh delete mode 100755 test/magic_cookies_test_starter.sh create mode 100644 test/magic_cookies_tests/conf/magic_cookies_test_client.json.in create mode 100644 test/magic_cookies_tests/conf/magic_cookies_test_service.json.in create mode 100644 test/magic_cookies_tests/magic_cookies_test_client.cpp create mode 100755 test/magic_cookies_tests/magic_cookies_test_client_start.sh create mode 100644 test/magic_cookies_tests/magic_cookies_test_service.cpp create mode 100755 test/magic_cookies_tests/magic_cookies_test_service_start.sh create mode 100755 test/magic_cookies_tests/magic_cookies_test_starter.sh create mode 100644 test/payload_tests/conf/external_local_payload_test_client_external.json.in create mode 100644 test/payload_tests/conf/external_local_payload_test_client_local.json.in create mode 100644 test/payload_tests/conf/external_local_payload_test_service.json.in delete mode 100644 test/payload_tests/external_local_payload_test_client_external.json delete mode 100644 test/payload_tests/external_local_payload_test_client_local.json delete mode 100644 test/payload_tests/external_local_payload_test_service.json create mode 100644 test/routing_tests/conf/external_local_routing_test_client_external.json.in create mode 100644 test/routing_tests/conf/external_local_routing_test_service.json.in delete mode 100644 test/routing_tests/external_local_routing_test_client_external.json delete mode 100644 test/routing_tests/external_local_routing_test_service.json create mode 100644 vsomeip.pc.in diff --git a/.gitignore b/.gitignore index 762ae85..1b7d204 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,22 @@ /.settings /doc /implementation/configuration/include/internal.hpp +/test/big_payload_tests/big_payload_test_tcp_client.json +/test/big_payload_tests/big_payload_test_tcp_service.json +/test/configuration_tests/configuration-test.json +/test/configuration_tests/configuration-test-deprecated.json +/test/magic_cookies_tests/magic_cookies_test_client.json +/test/magic_cookies_tests/magic_cookies_test_service.json +/test/payload_tests/external_local_payload_test_client_external.json +/test/payload_tests/external_local_payload_test_client_local.json +/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/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 +/test/client_id_tests/client_id_test_diff_client_ids_same_ports_slave.json +/test/client_id_tests/client_id_test_same_client_ids_diff_ports_master.json +/test/client_id_tests/client_id_test_same_client_ids_diff_ports_slave.json +/test/client_id_tests/client_id_test_same_client_ids_same_ports_master.json +/test/client_id_tests/client_id_test_same_client_ids_same_ports_slave.json diff --git a/CMakeLists.txt b/CMakeLists.txt index 07c91e4..877273c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,311 +1,361 @@ -# Copyright (C) 2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) -# This Source Code Form is subject to the terms of the Mozilla Public -# License, v. 2.0. If a copy of the MPL was not distributed with this -# file, You can obtain one at http://mozilla.org/MPL/2.0/. - -cmake_minimum_required (VERSION 2.8) -project (vsomeip) - -set (VSOMEIP_MAJOR_VERSION 1) -set (VSOMEIP_MINOR_VERSION 3) -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) - -################################################################################################### -# see http://www.cmake.org/Wiki/CMake/Tutorials/How_to_create_a_ProjectConfig.cmake_file -################################################################################################### - -# Offer the user the choice of overriding the installation directories -set (INSTALL_LIB_DIR lib CACHE PATH "Installation directory for libraries") -set (INSTALL_BIN_DIR bin CACHE PATH "Installation directory for executables") -set (INSTALL_INCLUDE_DIR include CACHE PATH "Installation directory for header files") - -if (WIN32 AND NOT CYGWIN) - set (DEF_INSTALL_CMAKE_DIR CMake) -else () - set (DEF_INSTALL_CMAKE_DIR lib/cmake/vsomeip) -endif () - -set (INSTALL_CMAKE_DIR ${DEF_INSTALL_CMAKE_DIR} CACHE PATH "Installation directory for CMake files") - -# Make relative paths absolute (needed later on) -foreach (p LIB BIN INCLUDE CMAKE) - set (var INSTALL_${p}_DIR) - if (NOT IS_ABSOLUTE "${${var}}") - set (ABSOLUTE_${var} "${CMAKE_INSTALL_PREFIX}/${${var}}") # Add all targets to the build-tree export set - endif () -endforeach () - -################################################################################################### - -# OS -if (${CMAKE_SYSTEM_NAME} MATCHES "Linux") - set(OS "LINUX") - set(DL_LIBRARY "dl") - set(EXPORTSYMBOLS "-Wl,-export-dynamic -Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/exportmap.gcc") - set(NO_DEPRECATED "") - set(OPTIMIZE "") - set(OS_CXX_FLAGS "-D_GLIBCXX_USE_NANOSLEEP -pthread") -endif (${CMAKE_SYSTEM_NAME} MATCHES "Linux") - -if (${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD") - set(OS "FREEBSD") - set(DL_LIBRARY "") - set(EXPORTSYMBOLS "") - set(NO_DEPRECATED "-Wno-deprecated") - set(OPTIMIZE "") - set(OS_CXX_FLAGS "-pthread") -endif (${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD") - -include_directories( - "interface" -) -# Threads -find_package(Threads REQUIRED) - -# Boost -find_package( Boost 1.54 COMPONENTS system thread log REQUIRED ) -include_directories( ${Boost_INCLUDE_DIR} ) - -# Base library -file(GLOB vsomeip_SRC - "implementation/configuration/src/*.cpp" - "implementation/endpoints/src/*.cpp" - "implementation/logging/src/*.cpp" - "implementation/message/src/*.cpp" - "implementation/routing/src/*.cpp" - "implementation/runtime/src/*.cpp" - "implementation/utility/src/*.cpp" -) - -if (MSVC) -set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_WINSOCK_DEPRECATED_NO_WARNINGS -D_WIN32_WINNT=0x0501 -DWIN32 -DUSE_VSOMEIP_STATISTICS -DCOMMONAPI_INTERNAL_COMPILATION -DBOOST_LOG_DYN_LINK /EHsc") -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D_CRT_SECURE_NO_WARNINGS -D_WINSOCK_DEPRECATED_NO_WARNINGS -D_WIN32_WINNT=0x0501 -DWIN32 -DUSE_VSOMEIP_STATISTICS -DCOMMONAPI_INTERNAL_COMPILATION -DBOOST_LOG_DYN_LINK /EHsc") -set(USE_RT "") -set(Boost_LIBRARIES "") -link_directories(${Boost_LIBRARY_DIR}) -else() -set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D${OS} ${OS_CXX_FLAGS} -DUSE_VSOMEIP_STATISTICS -DBOOST_LOG_DYN_LINK -g ${OPTIMIZE} -std=c++0x ${NO_DEPRECATED} ${EXPORTSYMBOLS}") -set(USE_RT "rt") -endif() - -add_library(vsomeip SHARED ${vsomeip_SRC}) -set_target_properties (vsomeip PROPERTIES VERSION ${VSOMEIP_VERSION} SOVERSION ${VSOMEIP_MAJOR_VERSION}) -target_link_libraries(vsomeip ${Boost_LIBRARIES} ${USE_RT} ${DL_LIBRARY}) - -file(GLOB vsomeip-sd_SRC - "implementation/service_discovery/src/*.cpp" -) - -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}) - -# Configuration files - -set(EXAMPLE_CONFIG_FILES - "config/vsomeip.json" - "config/vsomeip-local.json" - "config/vsomeip-tcp-client.json" - "config/vsomeip-tcp-service.json" - "config/vsomeip-udp-client.json" - "config/vsomeip-udp-service.json" -) - -# Examples -add_executable(request-sample examples/request-sample.cpp ${EXAMPLE_CONFIG_FILES}) -target_link_libraries(request-sample vsomeip ${Boost_LIBRARIES} ${DL_LIBRARY}) - -add_executable(response-sample examples/response-sample.cpp ${EXAMPLE_CONFIG_FILES}) -target_link_libraries(response-sample vsomeip ${Boost_LIBRARIES} ${DL_LIBRARY}) - -add_executable(subscribe-sample examples/subscribe-sample.cpp ${EXAMPLE_CONFIG_FILES}) -target_link_libraries(subscribe-sample vsomeip ${Boost_LIBRARIES} ${DL_LIBRARY}) - -add_executable(notify-sample examples/notify-sample.cpp ${EXAMPLE_CONFIG_FILES}) -target_link_libraries(notify-sample vsomeip ${Boost_LIBRARIES} ${DL_LIBRARY}) - -add_executable(vsomeipd examples/vsomeipd.cpp ${EXAMPLE_CONFIG_FILES}) -target_link_libraries(vsomeipd vsomeip ${Boost_LIBRARIES} ${DL_LIBRARY}) - -################################################################################################### - -file (GLOB_RECURSE vsomeip_INCLUDE "interface/*.hpp") - -set_target_properties (vsomeip PROPERTIES PUBLIC_HEADER "${vsomeip_INCLUDE}") - -install ( - TARGETS vsomeip - # IMPORTANT: Add the vsomeip library to the "export-set" - EXPORT vsomeipTargets - RUNTIME DESTINATION "${INSTALL_BIN_DIR}" COMPONENT bin - LIBRARY DESTINATION "${INSTALL_LIB_DIR}" COMPONENT shlib - PUBLIC_HEADER DESTINATION "${INSTALL_INCLUDE_DIR}/vsomeip" COMPONENT dev -) - -install ( - TARGETS vsomeip-sd - LIBRARY DESTINATION "${INSTALL_LIB_DIR}" COMPONENT shlib - RUNTIME DESTINATION "${INSTALL_BIN_DIR}" COMPONENT bin -) - -install ( - TARGETS request-sample response-sample subscribe-sample notify-sample vsomeipd - RUNTIME DESTINATION "${INSTALL_BIN_DIR}" COMPONENT bin -) - -install ( - FILES ${EXAMPLE_CONFIG_FILES} DESTINATION etc/vsomeip COMPONENT config -) - -# Add all targets to the build-tree export set -export (TARGETS vsomeip FILE "${PROJECT_BINARY_DIR}/vsomeipTargets.cmake") - -# Export the package for use from the build-tree -# (this registers the build-tree with a global CMake-registry) -export (PACKAGE vsomeip) - -# Create the vsomeipConfig.cmake and vsomeipConfigVersion files -file (RELATIVE_PATH REL_INCLUDE_DIR "${ABSOLUTE_INSTALL_CMAKE_DIR}" "${ABSOLUTE_INSTALL_INCLUDE_DIR}") - -# ... for the build tree -set (CONF_INCLUDE_DIRS "${PROJECT_SOURCE_DIR}/interface" "${PROJECT_BINARY_DIR}") -configure_file (vsomeipConfig.cmake.in "${PROJECT_BINARY_DIR}/vsomeipConfig.cmake" @ONLY) - -# ... for the install tree -set (CONF_INCLUDE_DIRS "\${VSOMEIP_CMAKE_DIR}/${REL_INCLUDE_DIR}") -configure_file (vsomeipConfig.cmake.in "${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/vsomeipConfig.cmake" @ONLY) - -# ... for both -configure_file (vsomeipConfigVersion.cmake.in "${PROJECT_BINARY_DIR}/vsomeipConfigVersion.cmake" @ONLY) - -# confugure internal.hpp for correct version number -configure_file ( - "${PROJECT_SOURCE_DIR}/implementation/configuration/include/internal.hpp.in" - "${PROJECT_SOURCE_DIR}/implementation/configuration/include/internal.hpp" -) - -# Install the vsomeipConfig.cmake and vsomeipConfigVersion.cmake -install ( - FILES - "${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/vsomeipConfig.cmake" - "${PROJECT_BINARY_DIR}/vsomeipConfigVersion.cmake" - DESTINATION "${INSTALL_CMAKE_DIR}" - COMPONENT dev -) - -# Install the export set for use with the install-tree -install ( - EXPORT vsomeipTargets - DESTINATION "${INSTALL_CMAKE_DIR}" - COMPONENT dev -) - -############################################################################## -# build documentation -############################################################################## -add_custom_target(doc) - -find_package(Doxygen) -if (NOT DOXYGEN_FOUND) - message(WARNING "Doxygen is not installed. Documentation can not be built.") -else() - # set configuration variables for doxygen.in - set(PROJECT "vsomeip") - set(DOCDIR documentation) - set(SRCDIR .) - set(GENERATE_HTML YES) - set(GENERATE_HTMLHELP NO) - set(GENERATE_CHI NO) - set(GENERATE_LATEX NO) - set(GENERATE_PDF NO) - set(GENERATE_RTF NO) - set(GENERATE_MAN NO) - set(GENERATE_XML NO) - set(HAVE_DOT YES) - - if(HAVE_DOT) - # Note: the @DOT_PATH@ variable won't be used in doxygen.in as doxygen - # somehow manages to strip the last slash from the path and therfore no - # graphs are generated. Therefore dot should be available in your $PATH - FIND_PROGRAM(DOT_PATH dot) - if ("${DOT_PATH}" STREQUAL "DOT_PATH-NOTFOUND") - message(WARNING "dot (graphviz) is not installed. Graphs in documentation can't be generated.") - else() - message("dot found") - endif() - endif() - - configure_file(documentation/doxygen.in ${PROJECT_BINARY_DIR}/Doxyfile @ONLY) - add_custom_target(doxygen-doc - COMMAND ${DOXYGEN_EXECUTABLE} ${PROJECT_BINARY_DIR}/Doxyfile - SOURCES ${PROJECT_BINARY_DIR}/Doxyfile) - - add_dependencies(doc doxygen-doc) -endif() - -find_program(ASCIIDOC_PATH asciidoc) -find_program(SOURCE_HIGHLIGHT_PATH source-highlight) -if ("${ASCIIDOC_PATH}" STREQUAL "ASCIIDOC_PATH-NOTFOUND") - message(WARNING "asciidoc is not installed. Readme can not be built.") -elseif("${SOURCE_HIGHLIGHT_PATH}" STREQUAL "SOURCE_HIGHLIGHT_PATH-NOTFOUND") - message(WARNING "source-highlight is not installed. Readme can not be built.") -else() - message("asciidoc found") - message("source-highlight found") - add_custom_command(TARGET doc - POST_BUILD - COMMAND asciidoc - -a version=${VSOMEIP_VERSION} - -b html - -o documentation/README.html - ${PROJECT_BINARY_DIR}/../README) -endif() - -############################################################################## -# Test section -############################################################################## - -############################################################################## -# google test - -# check for set environment variable -if(DEFINED ENV{GTEST_ROOT}) - message("GTEST_ROOT is set. GTEST_ROOT = $ENV{GTEST_ROOT}") -else() - message("GTEST_ROOT is not defined. For building the tests environment variable - GTEST_ROOT have to be defined. Tests can not be built.") - # early exit - return() # test can not be build -> make commands build_tests and check are not available -endif() - -# build google test as static library (always) -> therefore deactivate BUILD_SHARED_LIBS in case it is active -set(BUILD_SHARED_LIBS_AUTOMATIC_OFF 0) -if ("${BUILD_SHARED_LIBS}" STREQUAL "ON") - set(BUILD_SHARED_LIBS OFF) - set(BUILD_SHARED_LIBS_AUTOMATIC_OFF 1) -endif() -add_subdirectory($ENV{GTEST_ROOT} ${CMAKE_CURRENT_BINARY_DIR}/gtest EXCLUDE_FROM_ALL) -if ("${BUILD_SHARED_LIBS_AUTOMATIC_OFF}" STREQUAL "1") - set(BUILD_SHARED_LIBS ON) - set(BUILD_SHARED_LIBS_AUTOMATIC_OFF 0) -endif() - -############################################################################## -# build tests - -enable_testing() - -add_custom_target(build_tests) - -set(CMAKE_CTEST_COMMAND ctest -V) -add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND}) - -add_dependencies(check build_tests) - -############################################################################## -# add test directory - -add_subdirectory( test EXCLUDE_FROM_ALL ) +# Copyright (C) 2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +cmake_minimum_required (VERSION 2.8.12) +project (vsomeip) + +set (VSOMEIP_MAJOR_VERSION 2) +set (VSOMEIP_MINOR_VERSION 0) +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) + +################################################################################################### +# see http://www.cmake.org/Wiki/CMake/Tutorials/How_to_create_a_ProjectConfig.cmake_file +################################################################################################### + +# Offer the user the choice of overriding the installation directories +set (INSTALL_LIB_DIR lib CACHE PATH "Installation directory for libraries") +set (INSTALL_BIN_DIR bin CACHE PATH "Installation directory for executables") +set (INSTALL_INCLUDE_DIR include CACHE PATH "Installation directory for header files") + +if (WIN32 AND NOT CYGWIN) + set (DEF_INSTALL_CMAKE_DIR CMake) +else () + set (DEF_INSTALL_CMAKE_DIR lib/cmake/vsomeip) +endif () + +set (INSTALL_CMAKE_DIR ${DEF_INSTALL_CMAKE_DIR} CACHE PATH "Installation directory for CMake files") + +# Make relative paths absolute (needed later on) +foreach (p LIB BIN INCLUDE CMAKE) + set (var INSTALL_${p}_DIR) + if (NOT IS_ABSOLUTE "${${var}}") + set (ABSOLUTE_${var} "${CMAKE_INSTALL_PREFIX}/${${var}}") # Add all targets to the build-tree export set + endif () +endforeach () + +################################################################################################### + +# OS +if (${CMAKE_SYSTEM_NAME} MATCHES "Linux") + set(OS "LINUX") + set(DL_LIBRARY "dl") + set(EXPORTSYMBOLS "-Wl,-export-dynamic -Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/exportmap.gcc") + set(NO_DEPRECATED "") + set(OPTIMIZE "") + set(OS_CXX_FLAGS "-D_GLIBCXX_USE_NANOSLEEP -pthread -O -Wall -Wextra -Wformat -Wformat-security -Wconversion -fexceptions -fstrict-aliasing -fstack-protector -fasynchronous-unwind-tables -fno-omit-frame-pointer -D_FORTIFY_SOURCE=2") +endif (${CMAKE_SYSTEM_NAME} MATCHES "Linux") + +if (${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD") + set(OS "FREEBSD") + set(DL_LIBRARY "") + set(EXPORTSYMBOLS "") + set(NO_DEPRECATED "-Wno-deprecated") + set(OPTIMIZE "") + set(OS_CXX_FLAGS "-pthread") +endif (${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD") + +include_directories( + "interface" +) +# Threads +find_package(Threads REQUIRED) + +# Boost +find_package( Boost 1.54 COMPONENTS system thread log REQUIRED ) +include_directories( ${Boost_INCLUDE_DIR} ) + +# Base library +file(GLOB vsomeip_SRC + "implementation/configuration/src/*.cpp" + "implementation/endpoints/src/*.cpp" + "implementation/logging/src/*.cpp" + "implementation/message/src/*.cpp" + "implementation/routing/src/*.cpp" + "implementation/runtime/src/*.cpp" + "implementation/utility/src/*.cpp" +) + +if (MSVC) +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_WINSOCK_DEPRECATED_NO_WARNINGS -D_WIN32_WINNT=0x0501 -DWIN32 -DUSE_VSOMEIP_STATISTICS -DCOMMONAPI_INTERNAL_COMPILATION -DBOOST_LOG_DYN_LINK /EHsc") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D_CRT_SECURE_NO_WARNINGS -D_WINSOCK_DEPRECATED_NO_WARNINGS -D_WIN32_WINNT=0x0501 -DWIN32 -DUSE_VSOMEIP_STATISTICS -DCOMMONAPI_INTERNAL_COMPILATION -DBOOST_LOG_DYN_LINK /EHsc") +set(USE_RT "") +set(Boost_LIBRARIES "") +link_directories(${Boost_LIBRARY_DIR}) +else() +set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D${OS} ${OS_CXX_FLAGS} -DUSE_VSOMEIP_STATISTICS -DBOOST_LOG_DYN_LINK -g ${OPTIMIZE} -std=c++0x ${NO_DEPRECATED} ${EXPORTSYMBOLS}") +set(USE_RT "rt") +endif() + +add_library(vsomeip SHARED ${vsomeip_SRC}) +set_target_properties (vsomeip PROPERTIES VERSION ${VSOMEIP_VERSION} SOVERSION ${VSOMEIP_MAJOR_VERSION}) +# PRIVATE means the listed libraries won't be included in the "link interface", +# meaning the exported vsomeipTargets.cmake targets won't try to link against +# them (which shouldn't be required). ${Boost_LIBRARIES} includes absolute +# build host paths as of writing, which also makes this important as it breaks +# the build. +target_link_libraries(vsomeip PRIVATE ${Boost_LIBRARIES} ${USE_RT} ${DL_LIBRARY}) + +file(GLOB vsomeip-sd_SRC + "implementation/service_discovery/src/*.cpp" +) + +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}) + +# Configuration files + +set(EXAMPLE_CONFIG_FILES + "config/vsomeip.json" + "config/vsomeip-local.json" + "config/vsomeip-tcp-client.json" + "config/vsomeip-tcp-service.json" + "config/vsomeip-udp-client.json" + "config/vsomeip-udp-service.json" +) + +################################################################################################### +set (VSOMEIP_DIAGNOSIS_ADDRESS "0x11") +if (DIAGNOSIS_ADDRESS) +set (VSOMEIP_DIAGNOSIS_ADDRESS ${DIAGNOSIS_ADDRESS}) +endif () +set (VSOMEIP_UNICAST_ADDRESS "127.0.0.1") +if (UNICAST_ADDRESS) +set (VSOMEIP_UNICAST_ADDRESS ${UNICAST_ADDRESS}) +endif () +set (VSOMEIP_ROUTING "vsomeipd") +if (ROUTING) +set (VSOMEIP_ROUTING ${ROUTING}) +endif () +message("Predefined unicast address: ${VSOMEIP_UNICAST_ADDRESS}") +message("Predefined diagnosis address: ${VSOMEIP_DIAGNOSIS_ADDRESS}") +message("Predefined routing application: ${VSOMEIP_ROUTING}") + + +################################################################################################### + +set(INCLUDE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/interface/vsomeip") + +file (GLOB_RECURSE vsomeip_INCLUDE RELATIVE ${INCLUDE_PATH} "interface/*.hpp" ) + +foreach ( file ${vsomeip_INCLUDE} ) + get_filename_component( dir ${file} DIRECTORY ) + install( FILES "${INCLUDE_PATH}/${file}" DESTINATION "${INSTALL_INCLUDE_DIR}/vsomeip/${dir}" COMPONENT dev) +endforeach() + +install ( + TARGETS vsomeip + # IMPORTANT: Add the vsomeip library to the "export-set" + EXPORT vsomeipTargets + RUNTIME DESTINATION "${INSTALL_BIN_DIR}" COMPONENT bin + LIBRARY DESTINATION "${INSTALL_LIB_DIR}" COMPONENT shlib + COMPONENT dev +) + +install ( + TARGETS vsomeip-sd + LIBRARY DESTINATION "${INSTALL_LIB_DIR}" COMPONENT shlib + RUNTIME DESTINATION "${INSTALL_BIN_DIR}" COMPONENT bin +) + +install ( + FILES ${EXAMPLE_CONFIG_FILES} DESTINATION etc/vsomeip COMPONENT config +) + +# Add all targets to the build-tree export set +export (TARGETS vsomeip FILE "${PROJECT_BINARY_DIR}/vsomeipTargets.cmake") + +# Export the package for use from the build-tree +# (this registers the build-tree with a global CMake-registry) +export (PACKAGE vsomeip) + +# Create the vsomeipConfig.cmake and vsomeipConfigVersion files +file (RELATIVE_PATH REL_INCLUDE_DIR "${ABSOLUTE_INSTALL_CMAKE_DIR}" "${ABSOLUTE_INSTALL_INCLUDE_DIR}") + +# ... for the build tree +set (CONF_INCLUDE_DIRS "${PROJECT_SOURCE_DIR}/interface" "${PROJECT_BINARY_DIR}") +configure_file (vsomeipConfig.cmake.in "${PROJECT_BINARY_DIR}/vsomeipConfig.cmake" @ONLY) + +# ... for the install tree +set (CONF_INCLUDE_DIRS "\${VSOMEIP_CMAKE_DIR}/${REL_INCLUDE_DIR}") +configure_file (vsomeipConfig.cmake.in "${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/vsomeipConfig.cmake" @ONLY) + +# ... for both +configure_file (vsomeipConfigVersion.cmake.in "${PROJECT_BINARY_DIR}/vsomeipConfigVersion.cmake" @ONLY) + +# confugure internal.hpp for correct version number +configure_file ( + "${PROJECT_SOURCE_DIR}/implementation/configuration/include/internal.hpp.in" + "${PROJECT_SOURCE_DIR}/implementation/configuration/include/internal.hpp" +) + +# Install the vsomeipConfig.cmake and vsomeipConfigVersion.cmake +install ( + FILES + "${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/vsomeipConfig.cmake" + "${PROJECT_BINARY_DIR}/vsomeipConfigVersion.cmake" + DESTINATION "${INSTALL_CMAKE_DIR}" + COMPONENT dev +) + +# Install the export set for use with the install-tree +install ( + EXPORT vsomeipTargets + DESTINATION "${INSTALL_CMAKE_DIR}" + COMPONENT dev +) + +############################################################################## +# build documentation +############################################################################## +add_custom_target(doc) + +find_package(Doxygen) +if (NOT DOXYGEN_FOUND) + message(WARNING "Doxygen is not installed. Documentation can not be built.") +else() + # set configuration variables for doxygen.in + set(PROJECT "vsomeip") + set(DOCDIR documentation) + set(SRCDIR .) + set(GENERATE_HTML YES) + set(GENERATE_HTMLHELP NO) + set(GENERATE_CHI NO) + set(GENERATE_LATEX NO) + set(GENERATE_PDF NO) + set(GENERATE_RTF NO) + set(GENERATE_MAN NO) + set(GENERATE_XML NO) + set(HAVE_DOT YES) + + if(HAVE_DOT) + # Note: the @DOT_PATH@ variable won't be used in doxygen.in as doxygen + # somehow manages to strip the last slash from the path and therfore no + # graphs are generated. Therefore dot should be available in your $PATH + FIND_PROGRAM(DOT_PATH dot) + if ("${DOT_PATH}" STREQUAL "DOT_PATH-NOTFOUND") + message(WARNING "dot (graphviz) is not installed. Graphs in documentation can't be generated.") + else() + message("dot found") + endif() + endif() + + configure_file(documentation/doxygen.in ${PROJECT_BINARY_DIR}/Doxyfile @ONLY) + add_custom_target(doxygen-doc + COMMAND ${DOXYGEN_EXECUTABLE} ${PROJECT_BINARY_DIR}/Doxyfile + SOURCES ${PROJECT_BINARY_DIR}/Doxyfile) + + add_dependencies(doc doxygen-doc) +endif() + +find_program(ASCIIDOC_PATH asciidoc) +find_program(SOURCE_HIGHLIGHT_PATH source-highlight) +if ("${ASCIIDOC_PATH}" STREQUAL "ASCIIDOC_PATH-NOTFOUND") + message(WARNING "asciidoc is not installed. Readme can not be built.") +elseif("${SOURCE_HIGHLIGHT_PATH}" STREQUAL "SOURCE_HIGHLIGHT_PATH-NOTFOUND") + message(WARNING "source-highlight is not installed. Readme can not be built.") +else() + message("asciidoc found") + message("source-highlight found") + add_custom_command(TARGET doc + POST_BUILD + COMMAND asciidoc + -a version=${VSOMEIP_VERSION} + -b html + -o documentation/README.html + ${PROJECT_BINARY_DIR}/../README) +endif() + +############################################################################## +# create pkg-config file +if(NOT WIN32) + configure_file(vsomeip.pc.in ${PROJECT_BINARY_DIR}/vsomeip.pc @ONLY) + install(FILES ${PROJECT_BINARY_DIR}/vsomeip.pc DESTINATION lib/pkconfig) +endif() + +############################################################################## +# build daemon (Non-Windows only) +if (NOT MSVC) +add_custom_target( daemon ) +add_subdirectory( daemon ) +endif() + +# build examples +add_custom_target( examples ) +add_subdirectory( examples EXCLUDE_FROM_ALL ) + + +############################################################################## +# Test section +############################################################################## + +############################################################################## +# google test + +# check for set environment variable +if(DEFINED ENV{GTEST_ROOT}) + message("GTEST_ROOT is set. GTEST_ROOT = $ENV{GTEST_ROOT}") +else() + message("GTEST_ROOT is not defined. For building the tests environment variable + GTEST_ROOT have to be defined. Tests can not be built.") + # early exit + return() # test can not be build -> make commands build_tests and check are not available +endif() + +# build google test as static library (always) -> therefore deactivate BUILD_SHARED_LIBS in case it is active +set(BUILD_SHARED_LIBS_AUTOMATIC_OFF 0) +if ("${BUILD_SHARED_LIBS}" STREQUAL "ON") + set(BUILD_SHARED_LIBS OFF) + set(BUILD_SHARED_LIBS_AUTOMATIC_OFF 1) +endif() +add_subdirectory($ENV{GTEST_ROOT} ${CMAKE_CURRENT_BINARY_DIR}/gtest EXCLUDE_FROM_ALL) +if ("${BUILD_SHARED_LIBS_AUTOMATIC_OFF}" STREQUAL "1") + set(BUILD_SHARED_LIBS ON) + set(BUILD_SHARED_LIBS_AUTOMATIC_OFF 0) +endif() + + + +############################################################################## +# build tests + +enable_testing() +SET(TESTS_BAT "OFF" CACHE BOOL + "Controls whether only BAT tests should be build or not") +SET(TEST_SYMLINK_CONFIG_FILES "OFF" CACHE BOOL + "Controls if the json and scripts needed needed to run the tests are copied or symlinked into the build directroy (ignored on Windows)") +SET(TEST_SYMLINK_CONFIG_FILES_RELATIVE "OFF" CACHE BOOL + "Controls if the json and scripts needed needed to run the tests are symlinked relatively into the build directroy (ignored on Windows)") + +SET(TEST_IP_DEFAULT_VALUE "XXX.XXX.XXX.XXX") +SET(TEST_IP_MASTER "${TEST_IP_DEFAULT_VALUE}" CACHE STRING + "The IP address of the interface which will act as test master") +SET(TEST_IP_SLAVE "${TEST_IP_DEFAULT_VALUE}" CACHE STRING + "The IP address of the interface which will act as test slave") + +if((${TEST_IP_MASTER} STREQUAL ${TEST_IP_DEFAULT_VALUE}) OR + (${TEST_IP_SLAVE} STREQUAL ${TEST_IP_DEFAULT_VALUE})) + message(WARNING "TEST_IP_MASTER and/or TEST_IP_SLAVE isn't set. " + "Only local tests will be runnable " + "Please specify them via for example " + "-DTEST_IP_MASTER=10.0.3.1 -DTEST_IP_SLAVE=10.0.3.125") +endif() + +add_custom_target(build_tests) +add_dependencies(build_tests vsomeip) +add_dependencies(build_tests vsomeip-sd) + +set(CMAKE_CTEST_COMMAND ctest -V) +add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND}) + +add_dependencies(check build_tests) + +############################################################################## +# add test directory + +add_subdirectory( test EXCLUDE_FROM_ALL ) diff --git a/README b/README index f77e558..86dcaa1 100644 --- a/README +++ b/README @@ -69,7 +69,7 @@ For compilation call: mkdir build cd build cmake .. -make -j8 +make ---- To specify a installation directory (like `--prefix=` if you're used to @@ -77,19 +77,43 @@ autotools) call cmake like: [source, bash] ---- cmake -DCMAKE_INSTALL_PREFIX:PATH=$YOUR_PATH .. -make -j8 +make make install ---- +Compilation of examples +^^^^^^^^^^^^^^^^^^^^^^^ +For compilation of the examples call: +[source, bash] +---- +mkdir build +cd build +cmake .. +make examples +---- + Compilation of tests ^^^^^^^^^^^^^^^^^^^^ -To compile the tests, first unzip gtest to location of your desire. Then run: +To compile the tests, first unzip gtest to location of your desire. +Some of the tests require a second node on the same network. There are two cmake +variables which are used to automatically adapt the json files to the used +network setup: + +* `TEST_IP_MASTER`: The IP address of the interface which will act as test + master. +* `TEST_IP_SLAVE`: The IP address of the interface of the second node which will + act as test slave. + +If one of this variables isn't specified, only the tests using local +communication exclusively will be runnable. + +Example, compilation of tests: [source, bash] ---- mkdir build cd build export GTEST_ROOT=$PATH_TO_GTEST/gtest-1.7.0/ -cmake .. +cmake -DTEST_IP_MASTER=10.0.3.1 -DTEST_IP_SLAVE=10.0.3.125 .. make check ---- @@ -104,6 +128,33 @@ Additional make targets for the tests: * For further information about the tests please have a look at the `readme.txt` in the `test` subdirectory. +For development purposes two cmake variables exist which control if the +json files and test scripts are copied (default) or symlinked into the build +directory. These settings are ignored on Windows. + +* `TEST_SYMLINK_CONFIG_FILES`: Controls if the json and scripts needed + to run the tests are copied or symlinked into the build directory. (Default: + OFF, ignored on Windows) +* `TEST_SYMLINK_CONFIG_FILES_RELATIVE`: Controls if the json and scripts needed + to run the tests are symlinked relatively into the build directory. + (Default: OFF, ignored on Windows) + +Example cmake call: +[source, bash] +---- +cmake -DTEST_SYMLINK_CONFIG_FILES=ON -DTEST_SYMLINK_CONFIG_FILES_RELATIVE=ON .. +---- + +For compilation of only a subset of tests (for a quick +functionality check) the cmake variable `TESTS_BAT` has +to be set: + +Example cmake call: +[source, bash] +---- +cmake -DTESTS_BAT=ON .. +---- + Generating the documentation ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ To generate the documentation call cmake as described in <> and @@ -121,9 +172,17 @@ On startup the following environment variables are read out: name of the application. This name is later used to map a client id to the application in the configuration file. It is independent from the application's binary name. -* `VSOMEIP_CONFIGURATION_FILE`: This environment variable can be used to specify - a configuration file to be used by the application. If this variable is not - defined the default configuration file `/etc/vsomeip.json` will be used. +* `VSOMEIP_CONFIGURATION`: vsomeip uses the default configuration file `/etc/vsomeip.json` + and/or the default configuration folder `/etc/vsomeip`. This can be overridden by a + 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). + +NOTE: If the file/folder that is configured by `VSOMEIP_CONFIGURATION` does _not_ exist, +the default configuration locations will be used. + +NOTE: vsomeip will parse and use the configuration from all files in a configuration folder +but will _not_ consider directories within the configuration folder. In the following example the application `my_vsomeip_application` is started. The settings are read from the file `my_settings.json` in the current working @@ -134,7 +193,7 @@ directory. The client id for the application can be found under the name ---- #!/bin/bash export VSOMEIP_APPLICATION_NAME=my_vsomeip_client -export VSOMEIP_CONFIGURATION_FILE=my_settings.json +export VSOMEIP_CONFIGURATION=my_settings.json ./my_vsomeip_application ---- @@ -216,77 +275,6 @@ application thread. If an application wants/must do time consuming work directly within event, availability or message callbacks, 'num_dispatchers' should be set to '2' or higher. + -//Service groups -* 'servicegroups (array)' -+ -Services can be grouped together into one service group. A service group -contains the services of a specific service provider and its connection -information. -+ -NOTE: It is also possible to define multiple service groups to address services -from different service providers. -+ -** 'name' -+ -The name of the service group. -+ -** 'unicast' -+ -The IP address of the service provider (valid values: _local_ if the service -provider is the local host otherwise the _valid IP address_ of the remote -service provider). -+ -** 'delays' -+ -Contains delays related to the Service Discovery respectively to the service -instances. -+ -NOTE: The multicast messages of the Service Discovery come with the risk of -overflowing the net with too many messages. Therefore, the Service Discovery can -be configured with a suitable message sending behavior. - -*** 'initial' -+ -NOTE: A Service instance goes through different phases. One phase is called -Initial Wait Phase. This phase is entered when the service is fully available -and waits for the messages of a client's Service Discovery. - -**** 'minimum' -+ -Specifies the minimum time during which the messages of a client's Service -Discovery will be ignored (value in milliseconds). - -**** 'maximum' -+ -Specifies the maximum time during which the messages of a client's Service -Discovery will be ignored (value in milliseconds). - -*** `repetition-base` -+ -NOTE: On condition that the initial delay is over, the Repetition Phase is -entered. In this phase the services will be offered repeatedly via multicast by -the Service Discovery of the service provider. -+ -The repetition base delay specifies the time after that the first offer will be -started to send (value in milliseconds). - -*** `repetition-max` -+ -Specifies the amount of sent offers within the repetition phase. - -*** `cyclic-offer` -+ -NOTE: After the specific amount of repetitions, the Main Phase is entered. In -the Main Phase the Service Discovery of the service provider starts with a -cyclic offer of the services. -+ -The cyclic offer specifies the interval in which the services will be offered -via multicast (value in milliseconds). - -*** `cyclic-request` -+ -Specifies the cyclic-request-delay. Currently unused. - ** `services` (array) + Contains the services of the service provider. @@ -299,6 +287,22 @@ The id of the service. + The id of the service instance. +*** `protocol` (optional) ++ +The protocol that is used to implement the service instance. The default setting +is _someip_. If a different setting is provided, vsomeip does not open the specified +port (server side) or does not connect to the specified port (client side). Thus, +this option can be used to let the service discovery announce a service that is +externally implemented. + +*** `unicast` (optional) ++ +The unicast that hosts the service instance. ++ +NOTE: The unicast address is needed if external service instances shall be used, +but service discovery is disabled. In this case, the provided unicast address +is used to access the service instance. + *** `reliable` + Specifies that the communication with the service is reliable respectively the @@ -376,6 +380,43 @@ _true_,_false_). + The multicast address which the events are sent to. +* `payload-sizes` (array) ++ +Array to specify the maximum allowed payload sizes per IP and port. If not +specified, or a smaller value than the default values is specified, the default +values are used. The settings in this array only affect communication over TCP +and local communication over UNIX domain sockets. + +** `unicast` ++ +On client side: the IP of the remote service to which the oversized messages +should be sent. +On service side: the IP of the offered service which should receive the +oversized messages and is allowed to respond with oversized messages. +If client and service only communicate locally, any IP can be entered here as +for local communication only the maximum specified payload size is relevant. + +** `ports` (array) ++ +Array which holds pairs of port and payload-size statements. + +*** `port` ++ +On client side: the port of the remote service to which the oversized messages +should be sent. +On service side: the port of the offered service which should receive the +oversized messages and is allowed to respond with oversized messages. +If client and service only communicate locally, any port number can be entered. + +*** `max-payload-size` ++ +On client side: the maximum payload size in bytes of a message sent to the +remote service hosted on beforehand specified IP and port. +On service side: the maximum payload size in bytes of messages received by the +service offered on previously specified IP and port. If multiple services are +hosted on the same port all of them are allowed to receive oversized messages +and send oversized responses. + * `routing` + The name of the application that is responsible for the routing. @@ -386,22 +427,88 @@ Contains settings related to the Service Discovery of the host application. ** `enable` + -Specifies whether the Service Discovery is enabled ( valid values: _true_, -_false_). +Specifies whether the Service Discovery is enabled (valid values: _true_, +_false_). The default value is _true_. ** `multicast` + The multicast address which the messages of the Service Discovery will be sent -to. +to. The default value is "224.0.0.1". ** `port` + -The port of the Service Discovery. +The port of the Service Discovery. The default setting is 30490. ** `protocol` + The protocol that is used for sending the Service Discovery messages (valid -values: _tcp_,_udp_) +values: _tcp_, _udp_). The default setting is _udp_. + +** `initial_delay_min` ++ +Minimum delay before first offer message. + +** `initial_delay_max` ++ +Maximum delay before first offer message. + +** `repetitions_base_delay` ++ +Base delay sending offer messages within the repetition phase. + +** `repetitions_max` ++ +Maximum number of repetitions for provided services within the +repetition phase. + +** `ttl` ++ +Lifetime of entries for provided services as well as consumed services and eventgroups. + +** `cyclic_offer_delay` ++ +Cycle of the OfferService messages in the main phase. + +** `request_response_delay` ++ +Minimum delay of a unicast message to a multicast message for +provided services and eventgroups. + +Autoconfiguration +----------------- +vsomeip supports the automatic configuration of client identifiers and the routing. +The first application that starts using vsomeip will automatically become the +routing manager if it is _not_ explicitly configured. The client identifiers +are generated from the diagnosis address that can be specified by defining +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. + +vsomeipd +-------- +The vsomeipd is a minimal vsomeip application intended to offer routing manager +functionality on a node where one system wide configuration file is present. + +The vsomeipd uses the application name `vsomeipd` by default. This name can be +overridden by specifying `-DROUTING=$DESIRED_NAME` during the cmake call. + +Example: Starting the daemon on a system where the system wide configuration is +stored under `/etc/vsomeip.json`: +[source, bash] +---- +VSOMEIP_CONFIGURATION=/etc/vsomeip.json ./vsomeipd +---- + +When using the daemon it should be ensured that: + +* In the system wide configuration file the vsomeipd is defined as + routing manager, meaning it contains the line `"routing" : "vsomeipd"`. + If the default name is overridden the entry has to be adapted accordingly. + The system wide configuration file should contain the information about all + other offered services on the system as well. +* There's no other vsomeip configuration file used on the system which contains + a `"routing"` entry. As there can only be one routing manager per system. + vsomeip Hello World ------------------- @@ -436,7 +543,7 @@ Starting and expected output of service ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ [source, bash] ---- -$ VSOMEIP_CONFIGURATION_FILE=../helloworld-local.json \ +$ VSOMEIP_CONFIGURATION=../helloworld-local.json \ VSOMEIP_APPLICATION_NAME=hello_world_service \ ./hello_world_service 2015-04-01 11:31:13.248437 [info] Using configuration file: ../helloworld-local.json @@ -450,7 +557,7 @@ Starting and expected output of client ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ [source, bash] ---- -$ VSOMEIP_CONFIGURATION_FILE=../helloworld-local.json \ +$ VSOMEIP_CONFIGURATION=../helloworld-local.json \ VSOMEIP_APPLICATION_NAME=hello_world_client \ ./hello_world_client 2015-04-01 11:31:22.704166 [info] Using configuration file: ../helloworld-local.json diff --git a/config/vsomeip-local-tcp-client.json b/config/vsomeip-local-tcp-client.json index eecd9ad..863356f 100644 --- a/config/vsomeip-local-tcp-client.json +++ b/config/vsomeip-local-tcp-client.json @@ -1,83 +1,84 @@ { - "unicast" : "10.0.2.15", - "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" - } - ], - "servicegroups" : - [ - { - "name" : "remote", - "unicast" : "192.168.56.104", - "services" : - [ - { - "service" : "0x1234", - "instance" : "0x5678", - "reliable" : { "port" : "30509", "magic-cookies" : false }, - "events" : - [ - { - "event" : "0x0777", - "is_field" : "true" - }, - { - "event" : "0x0778", - "is_field" : "false" - }, - { - "event" : "0x0779", - "is_field" : "true" - } - ], - "eventgroups" : - [ - { - "eventgroup" : "0x4455", - "events" : [ "0x777", "0x778" ] - }, - { - "eventgroup" : "0x4465", - "events" : [ "0x778", "0x779" ] - }, - { - "eventgroup" : "0x4555", - "events" : [ "0x777", "0x779" ] - } - ] - } - ] - } - ], - "routing" : "client-sample", - "service-discovery" : - { - "enable" : "true", - "multicast" : "224.0.0.1", - "port" : "30491", - "protocol" : "udp" - } + "unicast" : "192.168.56.101", + "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" + } + ], + "services" : + [ + { + "service" : "0x1234", + "instance" : "0x5678", + "unicast" : "192.168.56.102", + "reliable" : { "port" : "30509", "magic-cookies" : false }, + "events" : + [ + { + "event" : "0x0777", + "is_field" : "true" + }, + { + "event" : "0x0778", + "is_field" : "false" + }, + { + "event" : "0x0779", + "is_field" : "true" + } + ], + "eventgroups" : + [ + { + "eventgroup" : "0x4455", + "events" : [ "0x777", "0x778" ] + }, + { + "eventgroup" : "0x4465", + "events" : [ "0x778", "0x779" ] + }, + { + "eventgroup" : "0x4555", + "events" : [ "0x777", "0x779" ] + } + ] + } + ], + "routing" : "client-sample", + "service-discovery" : + { + "enable" : "true", + "multicast" : "224.0.0.1", + "port" : "30491", + "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-local-tcp-service.json b/config/vsomeip-local-tcp-service.json index 7c1fe8b..621d099 100644 --- a/config/vsomeip-local-tcp-service.json +++ b/config/vsomeip-local-tcp-service.json @@ -1,82 +1,75 @@ { - "unicast" : "10.0.2.15", - "logging" : - { - "level" : "debug", - "console" : "true", - "file" : { "enable" : "false", "path" : "/tmp/vsomeip.log" }, - "dlt" : "false" - }, - "applications" : - [ - { - "name" : "service-sample", - "id" : "0x1277" - } - ], - "servicegroups" : - [ - { - "name" : "default", - "delays" : - { - "initial" : { "minimum" : "10", "maximum" : 100 }, - "repetition-base" : "200", - "repetition-max" : "3", - "cyclic-offer" : "2000", - "cyclic-request" : "2001" - }, - "services" : - [ - { - "service" : "0x1234", - "instance" : "0x5678", - "reliable" : { "port" : "30509", "magic-cookies" : "false" }, - "events" : - [ - { - "event" : "0x0777", - "is_field" : "false", - "is_reliable" : "true", - "update-cycle" : 2000 - }, - { - "event" : "0x0778", - "is_field" : "true", - "is_reliable" : "true", - "update-cycle" : 0 - }, - { - "event" : "0x0779", - "is_field" : "false", - "is_reliable" : "true" - } - ], - "eventgroups" : - [ - { - "eventgroup" : "0x4455", - "events" : [ "0x777", "0x778" ] - }, - { - "eventgroup" : "0x4465", - "events" : [ "0x778", "0x779" ] - }, - { - "eventgroup" : "0x4555", - "events" : [ "0x777", "0x779" ] - } - ] - } - ] - } - ], - "routing" : "service-sample", - "service-discovery" : - { - "enable" : "true", - "multicast" : "224.0.0.1", - "port" : "30490", - "protocol" : "udp" - } + "unicast" : "192.168.56.102", + "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", "magic-cookies" : "false" }, + "events" : + [ + { + "event" : "0x0777", + "is_field" : "false", + "is_reliable" : "true", + "update-cycle" : 2000 + }, + { + "event" : "0x0778", + "is_field" : "true", + "is_reliable" : "true", + "update-cycle" : 0 + }, + { + "event" : "0x0779", + "is_field" : "false", + "is_reliable" : "true" + } + ], + "eventgroups" : + [ + { + "eventgroup" : "0x4455", + "events" : [ "0x777", "0x778" ] + }, + { + "eventgroup" : "0x4465", + "events" : [ "0x778", "0x779" ] + }, + { + "eventgroup" : "0x4555", + "events" : [ "0x777", "0x779" ] + } + ] + } + ], + "routing" : "service-sample", + "service-discovery" : + { + "enable" : "true", + "multicast" : "224.0.0.1", + "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-local.json b/config/vsomeip-local.json index f1be1fb..967a9af 100644 --- a/config/vsomeip-local.json +++ b/config/vsomeip-local.json @@ -1,94 +1,82 @@ { - "unicast" : "10.0.2.15", - "logging" : - { - "level" : "debug", - "console" : "true", - "file" : { "enable" : "false", "path" : "/tmp/vsomeip.log" }, - "dlt" : "false" - }, - "applications" : - [ - { - "name" : "service-sample", - "id" : "0x1277" - }, - { - "name" : "client-sample", - "id" : "0x1344" - } - ], - "servicegroups" : - [ - { - "name" : "default", - "unicast" : "local", - "delays" : - { - "initial" : - { - "minimum" : "10", - "maximum" : 100 - }, - "repetition-base" : "200", - "repetition-max" : "3", - "cyclic-offer" : "2000", - "cyclic-request" : "2001" - }, - "services" : - [ - { - "service" : "0x1234", - "instance" : "0x5678", - "unreliable" : "30509", - "multicast" : - { - "address" : "224.225.226.233", - "port" : "32344" - }, - "events" : - [ - { - "event" : "0x0777", - "is_field" : "true", - "update-cycle" : 2000 - }, - { - "event" : "0x0778", - "is_field" : "true", - "update-cycle" : 0 - }, - { - "event" : "0x0779", - "is_field" : "true" - } - ], - "eventgroups" : - [ - { - "eventgroup" : "0x4455", - "events" : [ "0x777", "0x778" ] - }, - { - "eventgroup" : "0x4465", - "events" : [ "0x778", "0x779" ], - "is_multicast" : "true" - }, - { - "eventgroup" : "0x4555", - "events" : [ "0x777", "0x779" ] - } - ] - } - ] - } - ], - "routing" : "service-sample", - "service-discovery" : - { - "enable" : "true", - "multicast" : "224.244.224.245", - "port" : "30490", - "protocol" : "udp" - } + "unicast" : "10.0.2.15", + "logging" : + { + "level" : "debug", + "console" : "true", + "file" : { "enable" : "false", "path" : "/tmp/vsomeip.log" }, + "dlt" : "false" + }, + "applications" : + [ + { + "name" : "service-sample", + "id" : "0x1277" + }, + { + "name" : "client-sample", + "id" : "0x1344" + } + ], + "services" : + [ + { + "service" : "0x1234", + "instance" : "0x5678", + "unreliable" : "30509", + "multicast" : + { + "address" : "224.225.226.233", + "port" : "32344" + }, + "events" : + [ + { + "event" : "0x0777", + "is_field" : "true", + "update-cycle" : 2000 + }, + { + "event" : "0x0778", + "is_field" : "true", + "update-cycle" : 0 + }, + { + "event" : "0x0779", + "is_field" : "true" + } + ], + "eventgroups" : + [ + { + "eventgroup" : "0x4455", + "events" : [ "0x777", "0x778" ] + }, + { + "eventgroup" : "0x4465", + "events" : [ "0x778", "0x779" ], + "is_multicast" : "true" + }, + { + "eventgroup" : "0x4555", + "events" : [ "0x777", "0x779" ] + } + ] + } + ], + "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-magic-cookies-client.json b/config/vsomeip-magic-cookies-client.json deleted file mode 100644 index 572fbf9..0000000 --- a/config/vsomeip-magic-cookies-client.json +++ /dev/null @@ -1,83 +0,0 @@ -{ - "unicast" : "192.168.56.101", - "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" - } - ], - "servicegroups" : - [ - { - "name" : "remote", - "unicast" : "192.168.56.101", - "services" : - [ - { - "service" : "0x1234", - "instance" : "0x5678", - "reliable" : { "port" : "30509", "enable-magic-cookies" : "true" }, - "events" : - [ - { - "event" : "0x0777", - "is_field" : "true" - }, - { - "event" : "0x0778", - "is_field" : "false" - }, - { - "event" : "0x0779", - "is_field" : "true" - } - ], - "eventgroups" : - [ - { - "eventgroup" : "0x4455", - "events" : [ "0x777", "0x778" ] - }, - { - "eventgroup" : "0x4465", - "events" : [ "0x778", "0x779" ] - }, - { - "eventgroup" : "0x4555", - "events" : [ "0x777", "0x779" ] - } - ] - } - ] - } - ], - "routing" : "client-sample", - "service-discovery" : - { - "enable" : "false", - "multicast" : "224.0.0.1", - "port" : "30490", - "protocol" : "udp" - } -} diff --git a/config/vsomeip-magic-cookies-service.json b/config/vsomeip-magic-cookies-service.json deleted file mode 100644 index 97f7106..0000000 --- a/config/vsomeip-magic-cookies-service.json +++ /dev/null @@ -1,83 +0,0 @@ -{ - "unicast" : "192.168.56.101", - "logging" : - { - "level" : "debug", - "console" : "true", - "file" : { "enable" : "false", "path" : "/tmp/vsomeip.log" }, - "dlt" : "false" - }, - "applications" : - [ - { - "name" : "service-sample", - "id" : "0x1277" - } - ], - "servicegroups" : - [ - { - "name" : "default", - "unicast" : "local", - "delays" : - { - "initial" : { "minimum" : "10", "maximum" : 100 }, - "repetition-base" : "200", - "repetition-max" : "3", - "cyclic-offer" : "2000", - "cyclic-request" : "2001" - }, - "services" : - [ - { - "service" : "0x1234", - "instance" : "0x5678", - "reliable" : { "port" : "30509", "enable-magic-cookies" : "true" }, - "events" : - [ - { - "event" : "0x0777", - "is_field" : "false", - "is_reliable" : "true", - "update-cycle" : 2000 - }, - { - "event" : "0x0778", - "is_field" : "true", - "is_reliable" : "true", - "update-cycle" : 0 - }, - { - "event" : "0x0779", - "is_field" : "false", - "is_reliable" : "true" - } - ], - "eventgroups" : - [ - { - "eventgroup" : "0x4455", - "events" : [ "0x777", "0x778" ] - }, - { - "eventgroup" : "0x4465", - "events" : [ "0x778", "0x779" ] - }, - { - "eventgroup" : "0x4555", - "events" : [ "0x777", "0x779" ] - } - ] - } - ] - } - ], - "routing" : "service-sample", - "service-discovery" : - { - "enable" : "false", - "multicast" : "224.0.0.1", - "port" : "30490", - "protocol" : "udp" - } -} diff --git a/config/vsomeip-tcp-client.json b/config/vsomeip-tcp-client.json index f7083f3..52e349a 100644 --- a/config/vsomeip-tcp-client.json +++ b/config/vsomeip-tcp-client.json @@ -1,83 +1,83 @@ { - "unicast" : "127.0.0.1", - "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" - } - ], - "servicegroups" : - [ - { - "name" : "remote", - "unicast" : "127.0.0.1", - "services" : - [ - { - "service" : "0x1234", - "instance" : "0x5678", - "reliable" : { "port" : "30509", "enable-magic-cookies" : false }, - "events" : - [ - { - "event" : "0x0777", - "is_field" : "true" - }, - { - "event" : "0x0778", - "is_field" : "false" - }, - { - "event" : "0x0779", - "is_field" : "true" - } - ], - "eventgroups" : - [ - { - "eventgroup" : "0x4455", - "events" : [ "0x777", "0x778" ] - }, - { - "eventgroup" : "0x4465", - "events" : [ "0x778", "0x779" ] - }, - { - "eventgroup" : "0x4555", - "events" : [ "0x777", "0x779" ] - } - ] - } - ] - } - ], - "routing" : "client-sample", - "service-discovery" : - { - "enable" : "false", - "multicast" : "224.244.224.245", - "port" : "30490", - "protocol" : "udp" - } + "unicast" : "127.0.0.1", + "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" + } + ], + "services" : + [ + { + "service" : "0x1234", + "instance" : "0x5678", + "reliable" : { "port" : "30509", "enable-magic-cookies" : false }, + "events" : + [ + { + "event" : "0x0777", + "is_field" : "true" + }, + { + "event" : "0x0778", + "is_field" : "false" + }, + { + "event" : "0x0779", + "is_field" : "true" + } + ], + "eventgroups" : + [ + { + "eventgroup" : "0x4455", + "events" : [ "0x777", "0x778" ] + }, + { + "eventgroup" : "0x4465", + "events" : [ "0x778", "0x779" ] + }, + { + "eventgroup" : "0x4555", + "events" : [ "0x777", "0x779" ] + } + ] + } + ], + "routing" : "client-sample", + "service-discovery" : + { + "enable" : "false", + "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.json b/config/vsomeip-tcp-service.json index 3c38889..a2445ee 100644 --- a/config/vsomeip-tcp-service.json +++ b/config/vsomeip-tcp-service.json @@ -1,97 +1,85 @@ { - "unicast" : "192.168.56.101", - "logging" : - { - "level" : "debug", - "console" : "true", - "file" : { "enable" : "false", "path" : "/tmp/vsomeip.log" }, - "dlt" : "false" - }, - "applications" : - [ - { - "name" : "service-sample", - "id" : "0x1277" - } - ], - "servicegroups" : - [ - { - "name" : "default", - "unicast" : "127.0.0.1", - "delays" : - { - "initial" : - { - "minimum" : "10", - "maximum" : 100 - }, - "repetition-base" : "200", - "repetition-max" : "3", - "cyclic-offer" : "2000", - "cyclic-request" : "2001" - }, - "services" : - [ - { - "service" : "0x1234", - "instance" : "0x5678", - "reliable" : { "port" : "30509", "enable-magic-cookies" : "false" }, - "events" : - [ - { - "event" : "0x0777", - "is_field" : "false", - "is_reliable" : "true", - "update-cycle" : 2000 - }, - { - "event" : "0x0778", - "is_field" : "true", - "is_reliable" : "true", - "update-cycle" : 0 - }, - { - "event" : "0x0779", - "is_field" : "false", - "is_reliable" : "true" - } - ], - "eventgroups" : - [ - { - "eventgroup" : "0x4455", - "events" : [ "0x777", "0x778" ] - }, - { - "eventgroup" : "0x4465", - "events" : [ "0x778", "0x779" ] - }, - { - "eventgroup" : "0x4555", - "events" : [ "0x777", "0x779" ] - } - ] - }, - { - "service" : "0x1235", - "instance" : "0x5678", - "unreliable" : "30509", - "multicast" : - { - "address" : "224.225.226.234", - "port" : "32344" - } - } - ] - } - ], - "routing" : "service-sample", - "service-discovery" : - { - "enable" : "true", - "multicast" : "224.244.224.245", - "port" : "30490", - "protocol" : "udp" - } + "unicast" : "192.168.56.101", + "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" }, + "events" : + [ + { + "event" : "0x8777", + "is_field" : "false", + "is_reliable" : "true", + "update-cycle" : "2000" + }, + { + "event" : "0x8778", + "is_field" : "true", + "is_reliable" : "true", + "update-cycle" : "0" + }, + { + "event" : "0x8779", + "is_field" : "false", + "is_reliable" : "true" + } + ], + "eventgroups" : + [ + { + "eventgroup" : "0x4455", + "events" : [ "0x8777", "0x8778" ] + }, + { + "eventgroup" : "0x4465", + "events" : [ "0x8778", "0x8779" ] + }, + { + "eventgroup" : "0x4555", + "events" : [ "0x8777", "0x8779" ] + } + ] + }, + { + "service" : "0x1235", + "instance" : "0x5678", + "unreliable" : "30509", + "multicast" : + { + "address" : "224.225.226.234", + "port" : "32344" + } + } + ], + "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-test.json b/config/vsomeip-test.json deleted file mode 100644 index 1debb52..0000000 --- a/config/vsomeip-test.json +++ /dev/null @@ -1,130 +0,0 @@ -{ - "unicast" : "10.0.2.15", - "logging" : - { - "level" : "debug", - "console" : "true", - "file" : { "enable" : "true", "path" : "/home/someip/another-file.log" }, - "dlt" : "false" - }, - "applications" : - [ - { - "name" : "A", - "id" : "0x7788" - }, - { - "name" : "B", - "id" : "0x9933" - } - ], - "servicegroups" : - [ - { - "name" : "default", - "unicast" : "local", - "delays" : - { - "initial" : { "minimum" : "10", "maximum" : "100" }, - "repetition-base" : "200", - "repetition-max" : "7", - "cyclic-offer" : "2000", - "cyclic-request" : "2001" - }, - "services" : - [ - { - "service" : "0x1234", - "instance" : "0x0022", - "reliable" : { "port" : "30506", "magic_cookies" : "false" }, - "unreliable" : "31000", - "events" : - [ - { - "event" : "0x0778", - "is_field" : "false" - }, - { - "event" : "0x779", - "is_field" : "true" - }, - { - "event" : "0x77A", - "is_field" : "false" - } - ], - "eventgroups" : - [ - { - "eventgroup" : "0x4567", - "multicast" : "225.226.227.228", - "events" : [ "0x778", "0x779" ] - }, - { - "eventgroup" : "0x4569", - "multicast" : "225.227.227.228", - "events" : [ "0x779", "0x77A" ] - }, - { - "eventgroup" : "0x4569", - "multicast" : "225.222.227.228", - "events" : [ "0x778", "0x77A" ] - } - ] - }, - { - "service" : "0x1234", - "instance" : "0x0023", - "reliable" : "30503" - } - ] - }, - { - "name" : "extra", - "unicast" : "local", - "delays" : - { - "initial" : { "minimum" : "100", "maximum" : "200" }, - "repetition-base" : "300", - "repetition-max" : "5", - "cyclic-offer" : "2500", - "cyclic-request" : "2221" - }, - "services" : - [ - { - "service" : "0x2277", - "instance" : "0x0022", - "reliable" : { "port" : "30505" }, - "unreliable" : "31001" - }, - { - "service" : "0x2266", - "instance" : "0x0022", - "reliable" : "30505", - "unreliable" : "30507" - } - ] - }, - { - "name" : "remote", - "unicast" : "10.0.2.23", - "services" : - [ - { - "service" : "0x4466", - "instance" : "0x0321", - "reliable" : "30506", - "unreliable" : "30444" - } - ] - } - ], - "routing" : "A", - "service-discovery" : - { - "enable" : "true", - "port" : "30666", - "protocol" : "tcp" - } -} \ No newline at end of file diff --git a/config/vsomeip-udp-client.json b/config/vsomeip-udp-client.json index 5b57e45..9c8a846 100644 --- a/config/vsomeip-udp-client.json +++ b/config/vsomeip-udp-client.json @@ -1,38 +1,45 @@ { - "unicast" : "192.168.56.101", - "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" - } - ], - "routing" : "client-sample", - "service-discovery" : - { - "enable" : "true", - "multicast" : "224.244.224.245", - "port" : "30490", - "protocol" : "udp" - } + "unicast" : "192.168.56.101", + "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" + } + ], + "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.json b/config/vsomeip-udp-service.json index 5d7fa5d..b04aa4e 100644 --- a/config/vsomeip-udp-service.json +++ b/config/vsomeip-udp-service.json @@ -1,100 +1,88 @@ { - "unicast" : "192.168.56.101", - "logging" : - { - "level" : "debug", - "console" : "true", - "file" : { "enable" : "false", "path" : "/tmp/vsomeip.log" }, - "dlt" : "false" - }, - "applications" : - [ - { - "name" : "service-sample", - "id" : "0x1277" - } - ], - "servicegroups" : - [ - { - "name" : "default", - "unicast" : "local", - "delays" : - { - "initial" : - { - "minimum" : "10", - "maximum" : 100 - }, - "repetition-base" : "200", - "repetition-max" : "3", - "cyclic-offer" : "2000", - "cyclic-request" : "2001" - }, - "services" : - [ - { - "service" : "0x1234", - "instance" : "0x5678", - "unreliable" : "30509", - "multicast" : - { - "address" : "224.225.226.233", - "port" : "32344" - }, - "events" : - [ - { - "event" : "0x0777", - "is_field" : "true", - "update-cycle" : 2000 - }, - { - "event" : "0x0778", - "is_field" : "true", - "update-cycle" : 0 - }, - { - "event" : "0x0779", - "is_field" : "true" - } - ], - "eventgroups" : - [ - { - "eventgroup" : "0x4455", - "events" : [ "0x777", "0x778" ] - }, - { - "eventgroup" : "0x4465", - "events" : [ "0x778", "0x779" ], - "is_multicast" : "true" - }, - { - "eventgroup" : "0x4555", - "events" : [ "0x777", "0x779" ] - } - ] - }, - { - "service" : "0x1235", - "instance" : "0x5678", - "unreliable" : "30509", - "multicast" : - { - "address" : "224.225.226.234", - "port" : "32344" - } - } - ] - } - ], - "routing" : "service-sample", - "service-discovery" : - { - "enable" : "true", - "multicast" : "224.244.224.245", - "port" : "30490", - "protocol" : "udp" - } + "unicast" : "192.168.56.101", + "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", + "multicast" : + { + "address" : "224.225.226.233", + "port" : "32344" + }, + "events" : + [ + { + "event" : "0x8777", + "is_field" : "true", + "update-cycle" : 2000 + }, + { + "event" : "0x8778", + "is_field" : "true", + "update-cycle" : 0 + }, + { + "event" : "0x8779", + "is_field" : "true" + } + ], + "eventgroups" : + [ + { + "eventgroup" : "0x4455", + "events" : [ "0x8777", "0x8778" ] + }, + { + "eventgroup" : "0x4465", + "events" : [ "0x8778", "0x8779" ], + "is_multicast" : "true" + }, + { + "eventgroup" : "0x4555", + "events" : [ "0x8777", "0x8779" ] + } + ] + }, + { + "service" : "0x1235", + "instance" : "0x5678", + "unreliable" : "30509", + "multicast" : + { + "address" : "224.225.226.234", + "port" : "32344" + } + } + ], + "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.json b/config/vsomeip.json index 60c2f12..b119c07 100644 --- a/config/vsomeip.json +++ b/config/vsomeip.json @@ -1,62 +1,55 @@ { - "unicast" : "192.168.56.101", - "logging" : - { - "level" : "debug", - "console" : "true", - "file" : { "enable" : "false", "path" : "/var/log/vsomeip.log" }, - "dlt" : "false" - }, - "applications" : - [ - { - "name" : "client-sample", - "id" : "0x1343" - }, - { - "name" : "other-client-sample", - "id" : "0x1344" - }, - { - "name" : "service-sample", - "id" : "0x1277" - } - ], - "servicegroups" : - [ - { - "name" : "default", - "delays" : - { - "initial" : { "minimum" : "10", "maximum" : "100" }, - "repetition-base" : "200", - "repetition-max" : "3", - "cyclic-offer" : "2000", - "cyclic-request" : "2001" - }, - "services" : - [ - { - "service" : "0x1234", - "instance" : "0x5678", - "reliable" : { "port" : "30509", "enable-magic-cookies" : "false" }, - "unreliable" : "31000" - }, - { - "service" : "0x1235", - "instance" : "0x5678", - "reliable" : { "port" : "30506", "enable-magic-cookies" : false }, - "unreliable" : "31000" - } - ] - } - ], - "routing" : "client-sample", - "service-discovery" : - { - "enable" : "true", - "multicast" : "224.244.224.245", - "port" : "30490", - "protocol" : "udp" - } + "unicast" : "192.168.56.101", + "logging" : + { + "level" : "debug", + "console" : "true", + "file" : { "enable" : "false", "path" : "/var/log/vsomeip.log" }, + "dlt" : "false" + }, + "applications" : + [ + { + "name" : "client-sample", + "id" : "0x1343" + }, + { + "name" : "other-client-sample", + "id" : "0x1344" + }, + { + "name" : "service-sample", + "id" : "0x1277" + } + ], + "services" : + [ + { + "service" : "0x1234", + "instance" : "0x5678", + "reliable" : { "port" : "30509", "enable-magic-cookies" : "false" }, + "unreliable" : "31000" + }, + { + "service" : "0x1235", + "instance" : "0x5678", + "reliable" : { "port" : "30506", "enable-magic-cookies" : false }, + "unreliable" : "31000" + } + ], + "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/daemon/CMakeLists.txt b/daemon/CMakeLists.txt new file mode 100644 index 0000000..bdc0f3c --- /dev/null +++ b/daemon/CMakeLists.txt @@ -0,0 +1,17 @@ +# Copyright (C) 2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +cmake_minimum_required (VERSION 2.8) + +# Daemon +add_executable(vsomeipd vsomeipd.cpp) +target_link_libraries(vsomeipd vsomeip ${Boost_LIBRARIES} ${systemd-journal_LIBRARIES} ${DL_LIBRARY}) + +install ( + TARGETS vsomeipd + RUNTIME DESTINATION "${INSTALL_BIN_DIR}" COMPONENT bin +) + +################################################################################################### diff --git a/daemon/vsomeipd.cpp b/daemon/vsomeipd.cpp new file mode 100644 index 0000000..db60e23 --- /dev/null +++ b/daemon/vsomeipd.cpp @@ -0,0 +1,83 @@ +// Copyright (C) 2015 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 +#include + +#include + +#include +#include "../implementation/configuration/include/internal.hpp" + +/* + * Create a vsomeip application object and start it. + */ +int process(void) { + std::shared_ptr its_runtime + = vsomeip::runtime::get(); + + if (!its_runtime) { + return -1; + } + + std::shared_ptr its_application + = its_runtime->create_application(VSOMEIP_ROUTING); + + if (its_application->init()) { + its_application->start(); + return 0; + } else { + return -1; + } +} + +/* + * Parse command line options + * -h | --help print usage information + * -d | --daemonize start background processing by forking the process + * + * and start processing. + */ +int main(int argc, char **argv) { + bool must_daemonize(false); + if (argc > 1) { + for (int i = 0; i < argc; i++) { + std::string its_argument(argv[i]); + if (its_argument == "-d" || its_argument == "--daemonize") { + must_daemonize = true; + } else if (its_argument == "-h" || its_argument == "--help") { + std::cout << "usage: " + << argv[0] << " [-h|--help][-d|--daemonize]" + << std::endl; + return 0; + } + } + } + + /* Fork the process if processing shall be done in the background */ + if (must_daemonize) { + pid_t its_process, its_signature; + + its_process = fork(); + + if (its_process < 0) { + return EXIT_FAILURE; + } + + if (its_process > 0) { + return EXIT_SUCCESS; + } + + umask(0); + + its_signature = setsid(); + if (its_signature < 0) { + return EXIT_FAILURE; + } + } + + return process(); +} diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt new file mode 100644 index 0000000..e419589 --- /dev/null +++ b/examples/CMakeLists.txt @@ -0,0 +1,37 @@ +# Copyright (C) 2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +cmake_minimum_required (VERSION 2.8) + +set(EXAMPLE_CONFIG_FILES + "../config/vsomeip.json" + "../config/vsomeip-local.json" + "../config/vsomeip-tcp-client.json" + "../config/vsomeip-tcp-service.json" + "../config/vsomeip-udp-client.json" + "../config/vsomeip-udp-service.json" +) + +# Examples +add_executable(request-sample request-sample.cpp ${EXAMPLE_CONFIG_FILES}) +target_link_libraries(request-sample vsomeip ${Boost_LIBRARIES} ${DL_LIBRARY}) + +add_executable(response-sample response-sample.cpp ${EXAMPLE_CONFIG_FILES}) +target_link_libraries(response-sample vsomeip ${Boost_LIBRARIES} ${DL_LIBRARY}) + +add_executable(subscribe-sample subscribe-sample.cpp ${EXAMPLE_CONFIG_FILES}) +target_link_libraries(subscribe-sample vsomeip ${Boost_LIBRARIES} ${DL_LIBRARY}) + +add_executable(notify-sample notify-sample.cpp ${EXAMPLE_CONFIG_FILES}) +target_link_libraries(notify-sample vsomeip ${Boost_LIBRARIES} ${DL_LIBRARY}) + +add_dependencies(examples request-sample response-sample subscribe-sample notify-sample) + +install ( + TARGETS request-sample response-sample subscribe-sample notify-sample + RUNTIME DESTINATION "${INSTALL_BIN_DIR}" COMPONENT bin +) + +################################################################################################### diff --git a/examples/hello_world/hello_world_client.cpp b/examples/hello_world/hello_world_client.cpp index 1bbdf58..2099eee 100644 --- a/examples/hello_world/hello_world_client.cpp +++ b/examples/hello_world/hello_world_client.cpp @@ -26,23 +26,23 @@ public: // init the application app_->init(); - // register an event handler to get called back after registration at the + // register a state handler to get called back after registration at the // runtime was successful - app_->register_event_handler( - std::bind(&hello_world_client::on_event_cbk, this, + app_->register_state_handler( + std::bind(&hello_world_client::on_state_cbk, this, std::placeholders::_1)); - // register a callback which is called as soon as the service is available - app_->register_availability_handler(service_id, service_instance_id, - std::bind(&hello_world_client::on_availability_cbk, this, - std::placeholders::_1, std::placeholders::_2, - std::placeholders::_3)); - // register a callback for responses from the service app_->register_message_handler(vsomeip::ANY_SERVICE, service_instance_id, vsomeip::ANY_METHOD, std::bind(&hello_world_client::on_message_cbk, this, std::placeholders::_1)); + + // register a callback which is called as soon as the service is available + app_->register_availability_handler(service_id, service_instance_id, + std::bind(&hello_world_client::on_availability_cbk, this, + std::placeholders::_1, std::placeholders::_2, + std::placeholders::_3)); } void start() @@ -52,9 +52,9 @@ public: app_->start(); } - void on_event_cbk(vsomeip::event_type_e _event) + void on_state_cbk(vsomeip::state_type_e _state) { - if(_event == vsomeip::event_type_e::ET_REGISTERED) + if(_state == vsomeip::state_type_e::ST_REGISTERED) { // we are registered at the runtime now we can request the service // and wait for the on_availability callback to be called @@ -111,8 +111,8 @@ public: void stop() { - // unregister the event handler - app_->unregister_event_handler(); + // unregister the state handler + app_->unregister_state_handler(); // unregister the message handler app_->unregister_message_handler(vsomeip::ANY_SERVICE, service_instance_id, vsomeip::ANY_METHOD); diff --git a/examples/hello_world/hello_world_service.cpp b/examples/hello_world/hello_world_service.cpp index 3afc7e7..eece51c 100644 --- a/examples/hello_world/hello_world_service.cpp +++ b/examples/hello_world/hello_world_service.cpp @@ -32,10 +32,10 @@ public: std::bind(&hello_world_service::on_message_cbk, this, std::placeholders::_1)); - // register an event handler to get called back after registration at the + // register a state handler to get called back after registration at the // runtime was successful - app_->register_event_handler( - std::bind(&hello_world_service::on_event_cbk, this, + app_->register_state_handler( + std::bind(&hello_world_service::on_state_cbk, this, std::placeholders::_1)); } @@ -50,8 +50,8 @@ public: { // Stop offering the service app_->stop_offer_service(service_id, service_instance_id); - // unregister the event handler - app_->unregister_event_handler(); + // unregister the state handler + app_->unregister_state_handler(); // unregister the message handler app_->unregister_message_handler(service_id, service_instance_id, service_method_id); @@ -59,9 +59,9 @@ public: app_->stop(); } - void on_event_cbk(vsomeip::event_type_e _event) + void on_state_cbk(vsomeip::state_type_e _state) { - if(_event == vsomeip::event_type_e::ET_REGISTERED) + if(_state == vsomeip::state_type_e::ST_REGISTERED) { // we are registered at the runtime and can offer our service app_->offer_service(service_id, service_instance_id); diff --git a/examples/hello_world/readme b/examples/hello_world/readme index e2e1408..9b19424 100644 --- a/examples/hello_world/readme +++ b/examples/hello_world/readme @@ -21,12 +21,12 @@ the devices addresses. To start the hello world client and service from their build-directory do: HOST1: -VSOMEIP_CONFIGURATION_FILE=../helloworld-local.json \ +VSOMEIP_CONFIGURATION=../helloworld-local.json \ VSOMEIP_APPLICATION_NAME=hello_world_service \ ./hello_world_service HOST1: -VSOMEIP_CONFIGURATION_FILE=../helloworld-local.json \ +VSOMEIP_CONFIGURATION=../helloworld-local.json \ VSOMEIP_APPLICATION_NAME=hello_world_client \ ./hello_world_client diff --git a/examples/notify-sample.cpp b/examples/notify-sample.cpp index 78aadc7..442f74b 100644 --- a/examples/notify-sample.cpp +++ b/examples/notify-sample.cpp @@ -17,19 +17,22 @@ class service_sample { public: service_sample(bool _use_tcp, uint32_t _cycle) : - app_(vsomeip::runtime::get()->create_application()), is_registered_( - false), use_tcp_(_use_tcp), cycle_(_cycle), offer_thread_( - std::bind(&service_sample::run, this)), notify_thread_( - std::bind(&service_sample::notify, this)), is_offered_( - false) { + app_(vsomeip::runtime::get()->create_application()), + is_registered_(false), + use_tcp_(_use_tcp), + cycle_(_cycle), + blocked_(false), + is_offered_(false), + offer_thread_(std::bind(&service_sample::run, this)), + notify_thread_(std::bind(&service_sample::notify, this)) { } void init() { std::lock_guard its_lock(mutex_); app_->init(); - app_->register_event_handler( - std::bind(&service_sample::on_event, this, + app_->register_state_handler( + std::bind(&service_sample::on_state, this, std::placeholders::_1)); app_->register_message_handler( @@ -46,6 +49,14 @@ public: std::bind(&service_sample::on_set, this, std::placeholders::_1)); + std::set its_groups; + its_groups.insert(SAMPLE_EVENTGROUP_ID); + app_->offer_event( + SAMPLE_SERVICE_ID, + SAMPLE_INSTANCE_ID, + SAMPLE_EVENT_ID, + its_groups, + true); payload_ = vsomeip::runtime::get()->create_payload(); blocked_ = true; @@ -68,12 +79,12 @@ public: is_offered_ = false; } - void on_event(vsomeip::event_type_e _event) { - VSOMEIP_INFO << "Application " << app_->get_name() << " is " - << (_event == vsomeip::event_type_e::ET_REGISTERED ? - "registered." : "deregistered."); + void on_state(vsomeip::state_type_e _state) { + std::cout << "Application " << app_->get_name() << " is " + << (_state == vsomeip::state_type_e::ST_REGISTERED ? + "registered." : "deregistered.") << std::endl; - if (_event == vsomeip::event_type_e::ET_REGISTERED) { + if (_state == vsomeip::state_type_e::ST_REGISTERED) { if (!is_registered_) { is_registered_ = true; } @@ -141,7 +152,7 @@ public: payload_->set_data(its_data, its_size); - VSOMEIP_INFO << "Setting event (Length=" << std::dec << its_size << ")."; + std::cout << "Setting event (Length=" << std::dec << its_size << ")." << std::endl; app_->notify(SAMPLE_SERVICE_ID, SAMPLE_INSTANCE_ID, SAMPLE_EVENT_ID, payload_); its_size++; @@ -157,17 +168,19 @@ private: bool use_tcp_; uint32_t cycle_; - std::thread offer_thread_; std::mutex mutex_; std::condition_variable condition_; bool blocked_; - std::thread notify_thread_; std::mutex notify_mutex_; std::condition_variable notify_condition_; bool is_offered_; std::shared_ptr payload_; + + // blocked_ / is_offered_ must be initialized before starting the threads! + std::thread offer_thread_; + std::thread notify_thread_; }; int main(int argc, char **argv) { diff --git a/examples/readme.txt b/examples/readme.txt index 9b2c378..745c5f2 100644 --- a/examples/readme.txt +++ b/examples/readme.txt @@ -8,10 +8,10 @@ the configuration files need to be adapted to match the devices addresses. To start the request/response-example from the build-directory do: -HOST1: env VSOMEIP_CONFIGURATION_FILE=../config/vsomeip-local.json VSOMEIP_APPLICATION_NAME=client-sample ./request-sample -HOST2: env VSOMEIP_CONFIGURATION_FILE=../config/vsomeip-local.json VSOMEIP_APPLICATION_NAME=service-sample ./response-sample +HOST1: env VSOMEIP_CONFIGURATION=../config/vsomeip-local.json VSOMEIP_APPLICATION_NAME=client-sample ./request-sample +HOST2: env VSOMEIP_CONFIGURATION=../config/vsomeip-local.json VSOMEIP_APPLICATION_NAME=service-sample ./response-sample To start the subscribe/notify-example from the build-directory do: -HOST1: env VSOMEIP_CONFIGURATION_FILE=../config/vsomeip-local.json VSOMEIP_APPLICATION_NAME=client-sample ./subscribe-sample -HOST2: env VSOMEIP_CONFIGURATION_FILE=../config/vsomeip-local.json VSOMEIP_APPLICATION_NAME=service-sample ./notify-sample +HOST1: env VSOMEIP_CONFIGURATION=../config/vsomeip-local.json VSOMEIP_APPLICATION_NAME=client-sample ./subscribe-sample +HOST2: env VSOMEIP_CONFIGURATION=../config/vsomeip-local.json VSOMEIP_APPLICATION_NAME=service-sample ./notify-sample diff --git a/examples/request-sample.cpp b/examples/request-sample.cpp index 43969d5..ccdcffe 100644 --- a/examples/request-sample.cpp +++ b/examples/request-sample.cpp @@ -16,176 +16,185 @@ class client_sample { public: - client_sample(bool _use_tcp, bool _be_quiet, uint32_t _cycle) - : app_(vsomeip::runtime::get()->create_application()), - request_(vsomeip::runtime::get()->create_request()), - use_tcp_(_use_tcp), - be_quiet_(_be_quiet), - cycle_(_cycle), - sender_(std::bind(&client_sample::run, this)), - running_(true), - is_available_(false) { - } - - void init() { - app_->init(); - - VSOMEIP_INFO << "Client settings [protocol=" - << (use_tcp_ ? "TCP" : "UDP") - << ":quiet=" - << (be_quiet_ ? "true" : "false") - << ":cycle=" - << cycle_ - << "]"; - - app_->register_event_handler( - std::bind( - &client_sample::on_event, - this, - std::placeholders::_1)); - - app_->register_availability_handler(SAMPLE_SERVICE_ID, SAMPLE_INSTANCE_ID, - std::bind(&client_sample::on_availability, - this, - std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); - - app_->register_availability_handler(SAMPLE_SERVICE_ID + 1, SAMPLE_INSTANCE_ID, - std::bind(&client_sample::on_availability, - this, - std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); - - app_->register_message_handler( - vsomeip::ANY_SERVICE, SAMPLE_INSTANCE_ID, vsomeip::ANY_METHOD, - std::bind(&client_sample::on_message, - this, - std::placeholders::_1)); - - request_->set_service(SAMPLE_SERVICE_ID); - request_->set_instance(SAMPLE_INSTANCE_ID); - request_->set_method(SAMPLE_METHOD_ID); - - std::shared_ptr< vsomeip::payload > its_payload = vsomeip::runtime::get()->create_payload(); - std::vector< vsomeip::byte_t > its_payload_data; - for (std::size_t i = 0; i < 10; ++i) its_payload_data.push_back(i % 256); - its_payload->set_data(its_payload_data); - request_->set_payload(its_payload); - } - - void start() { - app_->start(); - } - - void on_event(vsomeip::event_type_e _event) { - if (_event == vsomeip::event_type_e::ET_REGISTERED) { - app_->request_service(SAMPLE_SERVICE_ID, SAMPLE_INSTANCE_ID); - } - } - - 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."); - - if (SAMPLE_SERVICE_ID == _service && SAMPLE_INSTANCE_ID == _instance) { - if (is_available_ && !_is_available) { - is_available_ = false; - } else if (_is_available && !is_available_) { - is_available_ = true; - send(); - } - } - } - - void on_message(const std::shared_ptr< vsomeip::message > &_response) { - VSOMEIP_INFO << "Received a response from Service [" - << std::setw(4) << std::setfill('0') << std::hex << _response->get_service() - << "." - << std::setw(4) << std::setfill('0') << std::hex << _response->get_instance() - << "] to Client/Session [" - << std::setw(4) << std::setfill('0') << std::hex << _response->get_client() - << "/" - << std::setw(4) << std::setfill('0') << std::hex << _response->get_session() - << "]"; - if (is_available_) - send(); - } - - void send() { - if (!be_quiet_) - { - std::lock_guard< std::mutex > its_lock(mutex_); - blocked_ = true; - condition_.notify_one(); - } - } - - void run() { - while (running_) { - { - std::unique_lock its_lock(mutex_); - while (!blocked_) condition_.wait(its_lock); - std::this_thread::sleep_for(std::chrono::milliseconds(cycle_)); - app_->send(request_, true); - VSOMEIP_INFO << "Client/Session [" - << std::setw(4) << std::setfill('0') << std::hex << request_->get_client() - << "/" - << std::setw(4) << std::setfill('0') << std::hex << request_->get_session() - << "] sent a request to Service [" - << std::setw(4) << std::setfill('0') << std::hex << request_->get_service() - << "." - << std::setw(4) << std::setfill('0') << std::hex << request_->get_instance() - << "]"; - blocked_ = false; - } - } - } + client_sample(bool _use_tcp, bool _be_quiet, uint32_t _cycle) + : app_(vsomeip::runtime::get()->create_application()), + request_(vsomeip::runtime::get()->create_request(_use_tcp)), + use_tcp_(_use_tcp), + be_quiet_(_be_quiet), + cycle_(_cycle), + running_(true), + blocked_(false), + is_available_(false), + sender_(std::bind(&client_sample::run, this)) { + } + + void init() { + app_->init(); + + std::cout << "Client settings [protocol=" + << (use_tcp_ ? "TCP" : "UDP") + << ":quiet=" + << (be_quiet_ ? "true" : "false") + << ":cycle=" + << cycle_ + << "]" + << std::endl; + + app_->register_state_handler( + std::bind( + &client_sample::on_state, + this, + std::placeholders::_1)); + + app_->register_message_handler( + vsomeip::ANY_SERVICE, SAMPLE_INSTANCE_ID, vsomeip::ANY_METHOD, + std::bind(&client_sample::on_message, + this, + std::placeholders::_1)); + + request_->set_service(SAMPLE_SERVICE_ID); + request_->set_instance(SAMPLE_INSTANCE_ID); + request_->set_method(SAMPLE_METHOD_ID); + + std::shared_ptr< vsomeip::payload > its_payload = vsomeip::runtime::get()->create_payload(); + std::vector< vsomeip::byte_t > its_payload_data; + for (std::size_t i = 0; i < 10; ++i) its_payload_data.push_back(i % 256); + its_payload->set_data(its_payload_data); + request_->set_payload(its_payload); + + app_->register_availability_handler(SAMPLE_SERVICE_ID, SAMPLE_INSTANCE_ID, + std::bind(&client_sample::on_availability, + this, + std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); + + app_->register_availability_handler(SAMPLE_SERVICE_ID + 1, SAMPLE_INSTANCE_ID, + std::bind(&client_sample::on_availability, + this, + std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); + } + + void start() { + app_->start(); + } + + void on_state(vsomeip::state_type_e _state) { + if (_state == vsomeip::state_type_e::ST_REGISTERED) { + app_->request_service(SAMPLE_SERVICE_ID, SAMPLE_INSTANCE_ID); + } + } + + void on_availability(vsomeip::service_t _service, vsomeip::instance_t _instance, bool _is_available) { + std::cout << "Service [" + << std::setw(4) << std::setfill('0') << std::hex << _service << "." << _instance + << "] is " + << (_is_available ? "available." : "NOT available.") + << std::endl; + + if (SAMPLE_SERVICE_ID == _service && SAMPLE_INSTANCE_ID == _instance) { + if (is_available_ && !_is_available) { + is_available_ = false; + } else if (_is_available && !is_available_) { + is_available_ = true; + send(); + } + } + } + + void on_message(const std::shared_ptr< vsomeip::message > &_response) { + std::cout << "Received a response from Service [" + << std::setw(4) << std::setfill('0') << std::hex << _response->get_service() + << "." + << std::setw(4) << std::setfill('0') << std::hex << _response->get_instance() + << "] to Client/Session [" + << std::setw(4) << std::setfill('0') << std::hex << _response->get_client() + << "/" + << std::setw(4) << std::setfill('0') << std::hex << _response->get_session() + << "]" + << std::endl; + if (is_available_) + send(); + } + + void send() { + if (!be_quiet_) + { + std::lock_guard< std::mutex > its_lock(mutex_); + blocked_ = true; + condition_.notify_one(); + } + } + + void run() { + while (running_) { + { + std::unique_lock its_lock(mutex_); + while (!blocked_) condition_.wait(its_lock); + std::this_thread::sleep_for(std::chrono::milliseconds(cycle_)); + if (is_available_) { + app_->send(request_, true); + std::cout << "Client/Session [" + << std::setw(4) << std::setfill('0') << std::hex << request_->get_client() + << "/" + << std::setw(4) << std::setfill('0') << std::hex << request_->get_session() + << "] sent a request to Service [" + << std::setw(4) << std::setfill('0') << std::hex << request_->get_service() + << "." + << std::setw(4) << std::setfill('0') << std::hex << request_->get_instance() + << "]" + << std::endl; + blocked_ = false; + } + + } + } + } private: - std::shared_ptr< vsomeip::application > app_; - std::shared_ptr< vsomeip::message > request_; - bool use_tcp_; - bool be_quiet_; - uint32_t cycle_; - vsomeip::session_t session_; - std::mutex mutex_; - std::condition_variable condition_; - std::thread sender_; - bool running_; - bool blocked_; - bool is_available_; + std::shared_ptr< vsomeip::application > app_; + std::shared_ptr< vsomeip::message > request_; + bool use_tcp_; + bool be_quiet_; + uint32_t cycle_; + vsomeip::session_t session_; + std::mutex mutex_; + std::condition_variable condition_; + bool running_; + bool blocked_; + bool is_available_; + + std::thread sender_; }; int main(int argc, char **argv) { - bool use_tcp = false; - bool be_quiet = false; - uint32_t cycle = 1000; // Default: 1s - - std::string tcp_enable("--tcp"); - std::string udp_enable("--udp"); - std::string quiet_enable("--quiet"); - std::string cycle_arg("--cycle"); - - int i = 1; - while (i < argc) { - if (tcp_enable == argv[i]) { - use_tcp = true; - } else if (udp_enable == argv[i]) { - use_tcp = false; - } else if (quiet_enable == argv[i]) { - be_quiet = true; - } else if (cycle_arg == argv[i] && i+1 < argc) { - i++; - std::stringstream converter; - converter << argv[i]; - converter >> cycle; - } - i++; - } - - client_sample its_sample(use_tcp, be_quiet, cycle); - its_sample.init(); - its_sample.start(); - return 0; + bool use_tcp = false; + bool be_quiet = false; + uint32_t cycle = 1000; // Default: 1s + + std::string tcp_enable("--tcp"); + std::string udp_enable("--udp"); + std::string quiet_enable("--quiet"); + std::string cycle_arg("--cycle"); + + int i = 1; + while (i < argc) { + if (tcp_enable == argv[i]) { + use_tcp = true; + } else if (udp_enable == argv[i]) { + use_tcp = false; + } else if (quiet_enable == argv[i]) { + be_quiet = true; + } else if (cycle_arg == argv[i] && i+1 < argc) { + i++; + std::stringstream converter; + converter << argv[i]; + converter >> cycle; + } + i++; + } + + client_sample its_sample(use_tcp, be_quiet, cycle); + its_sample.init(); + its_sample.start(); + return 0; } diff --git a/examples/response-sample.cpp b/examples/response-sample.cpp index 9d43a29..31adace 100644 --- a/examples/response-sample.cpp +++ b/examples/response-sample.cpp @@ -20,6 +20,7 @@ public: app_(vsomeip::runtime::get()->create_application()), is_registered_(false), use_static_routing_(_use_static_routing), + blocked_(false), offer_thread_(std::bind(&service_sample::run, this)) { } @@ -27,16 +28,16 @@ public: std::lock_guard its_lock(mutex_); app_->init(); + app_->register_state_handler( + std::bind(&service_sample::on_state, this, + std::placeholders::_1)); app_->register_message_handler( - SAMPLE_SERVICE_ID, SAMPLE_INSTANCE_ID, SAMPLE_METHOD_ID, + SAMPLE_SERVICE_ID, SAMPLE_INSTANCE_ID, SAMPLE_METHOD_ID, std::bind(&service_sample::on_message, this, std::placeholders::_1)); - app_->register_event_handler( - std::bind(&service_sample::on_event, this, - std::placeholders::_1)); - - VSOMEIP_INFO<< "Static routing " << (use_static_routing_ ? "ON" : "OFF"); + std::cout << "Static routing " << (use_static_routing_ ? "ON" : "OFF") + << std::endl; } void start() { @@ -53,12 +54,13 @@ public: app_->stop_offer_service(SAMPLE_SERVICE_ID + 1, SAMPLE_INSTANCE_ID); } - void on_event(vsomeip::event_type_e _event) { - VSOMEIP_INFO << "Application " << app_->get_name() << " is " - << (_event == vsomeip::event_type_e::ET_REGISTERED ? - "registered." : "deregistered."); + void on_state(vsomeip::state_type_e _state) { + std::cout << "Application " << app_->get_name() << " is " + << (_state == vsomeip::state_type_e::ST_REGISTERED ? + "registered." : "deregistered.") + << std::endl; - if (_event == vsomeip::event_type_e::ET_REGISTERED) { + if (_state == vsomeip::state_type_e::ST_REGISTERED) { if (!is_registered_) { is_registered_ = true; blocked_ = true; @@ -70,16 +72,17 @@ public: } void on_message(const std::shared_ptr &_request) { - VSOMEIP_INFO << "Received a message with Client/Session [" << std::setw(4) - << std::setfill('0') << std::hex << _request->get_client() << "/" - << std::setw(4) << std::setfill('0') << std::hex - << _request->get_session() << "]"; + std::cout << "Received a message with Client/Session [" << std::setw(4) + << std::setfill('0') << std::hex << _request->get_client() << "/" + << std::setw(4) << std::setfill('0') << std::hex + << _request->get_session() << "]" + << std::endl; - std::shared_ptr its_response = vsomeip::runtime::get() - ->create_response(_request); + std::shared_ptr its_response + = vsomeip::runtime::get()->create_response(_request); - std::shared_ptr its_payload = vsomeip::runtime::get() - ->create_payload(); + std::shared_ptr its_payload + = vsomeip::runtime::get()->create_payload(); std::vector its_payload_data; for (std::size_t i = 0; i < 120; ++i) its_payload_data.push_back(i % 256); @@ -116,10 +119,12 @@ private: bool is_registered_; bool use_static_routing_; - std::thread offer_thread_; std::mutex mutex_; std::condition_variable condition_; bool blocked_; + + // blocked_ must be initialized before the thread is started. + std::thread offer_thread_; }; int main(int argc, char **argv) { diff --git a/examples/sample-ids.hpp b/examples/sample-ids.hpp index 28132a1..2d59164 100644 --- a/examples/sample-ids.hpp +++ b/examples/sample-ids.hpp @@ -6,18 +6,18 @@ #ifndef VSOMEIP_EXAMPLES_SAMPLE_IDS_HPP #define VSOMEIP_EXAMPLES_SAMPLE_IDS_HPP -#define SAMPLE_SERVICE_ID 0x1234 -#define SAMPLE_INSTANCE_ID 0x5678 -#define SAMPLE_METHOD_ID 0x8421 +#define SAMPLE_SERVICE_ID 0x1234 +#define SAMPLE_INSTANCE_ID 0x5678 +#define SAMPLE_METHOD_ID 0x0421 -#define SAMPLE_EVENT_ID 0x0778 -#define SAMPLE_GET_METHOD_ID 0x8001 -#define SAMPLE_SET_METHOD_ID 0x8002 +#define SAMPLE_EVENT_ID 0x8778 +#define SAMPLE_GET_METHOD_ID 0x0001 +#define SAMPLE_SET_METHOD_ID 0x0002 -#define SAMPLE_EVENTGROUP_ID 0x4465 +#define SAMPLE_EVENTGROUP_ID 0x4465 -#define OTHER_SAMPLE_SERVICE_ID 0x0248 +#define OTHER_SAMPLE_SERVICE_ID 0x0248 #define OTHER_SAMPLE_INSTANCE_ID 0x5422 -#define OTHER_SAMPLE_METHOD_ID 0x1421 +#define OTHER_SAMPLE_METHOD_ID 0x1421 #endif // VSOMEIP_EXAMPLES_SAMPLE_IDS_HPP diff --git a/examples/subscribe-sample.cpp b/examples/subscribe-sample.cpp index 3faa4d1..9a03722 100644 --- a/examples/subscribe-sample.cpp +++ b/examples/subscribe-sample.cpp @@ -16,119 +16,132 @@ class client_sample { public: - client_sample(bool _use_tcp) : - app_(vsomeip::runtime::get()->create_application()), use_tcp_( - _use_tcp) { - } - - void init() { - app_->init(); - - VSOMEIP_INFO << "Client settings [protocol=" - << (use_tcp_ ? "TCP" : "UDP") - << "]"; - - app_->register_availability_handler(SAMPLE_SERVICE_ID, SAMPLE_INSTANCE_ID, - std::bind(&client_sample::on_availability, - this, - std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); - - app_->register_message_handler(vsomeip::ANY_SERVICE, SAMPLE_INSTANCE_ID, - vsomeip::ANY_METHOD, - std::bind(&client_sample::on_message, this, - std::placeholders::_1)); - } - - void start() { - app_->start(); - } - - 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."); - - if (_is_available && SAMPLE_SERVICE_ID == _service && SAMPLE_INSTANCE_ID == _instance) { - app_->subscribe(SAMPLE_SERVICE_ID, SAMPLE_INSTANCE_ID, SAMPLE_EVENTGROUP_ID); - } - } - - void on_message(const std::shared_ptr &_response) { - std::stringstream its_message; - its_message << "Received a notification for Event [" << std::setw(4) - << std::setfill('0') << std::hex << _response->get_service() - << "." << _response->get_instance() << "." - << _response->get_method() << "] to Client/Session [" - << std::setw(4) << std::setfill('0') << std::hex - << _response->get_client() << "/" << std::setw(4) - << std::setfill('0') << std::hex << _response->get_session() - << "] = "; - std::shared_ptr its_payload = - _response->get_payload(); - its_message << "(" << std::dec << its_payload->get_length() << ") "; - for (uint32_t i = 0; i < its_payload->get_length(); ++i) - its_message << std::hex << std::setw(2) << std::setfill('0') - << (int) its_payload->get_data()[i] << " "; - VSOMEIP_INFO << its_message.str(); - - if (_response->get_client() == 0) { - if ((its_payload->get_length() % 5) == 0) { - std::shared_ptr its_get - = vsomeip::runtime::get()->create_request(); - its_get->set_service(SAMPLE_SERVICE_ID); - its_get->set_instance(SAMPLE_INSTANCE_ID); - its_get->set_method(SAMPLE_GET_METHOD_ID); - its_get->set_reliable(use_tcp_); - app_->send(its_get, true); - } - - if ((its_payload->get_length() % 8) == 0) { - std::shared_ptr its_set - = vsomeip::runtime::get()->create_request(); - its_set->set_service(SAMPLE_SERVICE_ID); - its_set->set_instance(SAMPLE_INSTANCE_ID); - its_set->set_method(SAMPLE_SET_METHOD_ID); - its_set->set_reliable(use_tcp_); - - const vsomeip::byte_t its_data[] - = { 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, - 0x48, 0x49, 0x50, 0x51, 0x52 }; - std::shared_ptr its_set_payload - = vsomeip::runtime::get()->create_payload(); - its_set_payload->set_data(its_data, sizeof(its_data)); - its_set->set_payload(its_set_payload); - app_->send(its_set, true); - } - } - } + client_sample(bool _use_tcp) : + app_(vsomeip::runtime::get()->create_application()), use_tcp_( + _use_tcp) { + } + + void init() { + app_->init(); + + std::cout << "Client settings [protocol=" + << (use_tcp_ ? "TCP" : "UDP") + << "]" + << std::endl; + + app_->register_message_handler( + vsomeip::ANY_SERVICE, SAMPLE_INSTANCE_ID, vsomeip::ANY_METHOD, + std::bind(&client_sample::on_message, this, + std::placeholders::_1)); + + app_->register_availability_handler(SAMPLE_SERVICE_ID, SAMPLE_INSTANCE_ID, + std::bind(&client_sample::on_availability, + this, + std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); + + std::set its_groups; + its_groups.insert(SAMPLE_EVENTGROUP_ID); + app_->request_event( + SAMPLE_SERVICE_ID, + SAMPLE_INSTANCE_ID, + SAMPLE_EVENT_ID, + its_groups, + true); + } + + void start() { + app_->start(); + } + + void on_availability(vsomeip::service_t _service, vsomeip::instance_t _instance, bool _is_available) { + std::cout << "Service [" + << std::setw(4) << std::setfill('0') << std::hex << _service << "." << _instance + << "] is " + << (_is_available ? "available." : "NOT available.") + << std::endl; + + if (_is_available && SAMPLE_SERVICE_ID == _service && SAMPLE_INSTANCE_ID == _instance) { + app_->subscribe(SAMPLE_SERVICE_ID, SAMPLE_INSTANCE_ID, SAMPLE_EVENTGROUP_ID); + } + } + + void on_message(const std::shared_ptr &_response) { + std::stringstream its_message; + its_message << "Received a notification for Event [" + << std::setw(4) << std::setfill('0') << std::hex + << _response->get_service() << "." + << std::setw(4) << std::setfill('0') << std::hex + << _response->get_instance() << "." + << std::setw(4) << std::setfill('0') << std::hex + << _response->get_method() << "] to Client/Session [" + << std::setw(4) << std::setfill('0') << std::hex + << _response->get_client() << "/" + << std::setw(4) << std::setfill('0') << std::hex + << _response->get_session() + << "] = "; + std::shared_ptr its_payload = + _response->get_payload(); + its_message << "(" << std::dec << its_payload->get_length() << ") "; + for (uint32_t i = 0; i < its_payload->get_length(); ++i) + its_message << std::hex << std::setw(2) << std::setfill('0') + << (int) its_payload->get_data()[i] << " "; + std::cout << its_message.str() << std::endl; + + if (_response->get_client() == 0) { + if ((its_payload->get_length() % 5) == 0) { + std::shared_ptr its_get + = vsomeip::runtime::get()->create_request(); + its_get->set_service(SAMPLE_SERVICE_ID); + its_get->set_instance(SAMPLE_INSTANCE_ID); + its_get->set_method(SAMPLE_GET_METHOD_ID); + its_get->set_reliable(use_tcp_); + app_->send(its_get, true); + } + + if ((its_payload->get_length() % 8) == 0) { + std::shared_ptr its_set + = vsomeip::runtime::get()->create_request(); + its_set->set_service(SAMPLE_SERVICE_ID); + its_set->set_instance(SAMPLE_INSTANCE_ID); + its_set->set_method(SAMPLE_SET_METHOD_ID); + its_set->set_reliable(use_tcp_); + + const vsomeip::byte_t its_data[] + = { 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0x50, 0x51, 0x52 }; + std::shared_ptr its_set_payload + = vsomeip::runtime::get()->create_payload(); + its_set_payload->set_data(its_data, sizeof(its_data)); + its_set->set_payload(its_set_payload); + app_->send(its_set, true); + } + } + } private: - std::shared_ptr< vsomeip::application > app_; - bool use_tcp_; - bool be_quiet_; + std::shared_ptr< vsomeip::application > app_; + bool use_tcp_; + bool be_quiet_; }; int main(int argc, char **argv) { - bool use_tcp = false; - bool be_quiet = false; - uint32_t cycle = 1000; // Default: 1s - - std::string tcp_enable("--tcp"); - std::string udp_enable("--udp"); - - int i = 1; - while (i < argc) { - if (tcp_enable == argv[i]) { - use_tcp = true; - } else if (udp_enable == argv[i]) { - use_tcp = false; - } - i++; - } - - client_sample its_sample(use_tcp); - its_sample.init(); - its_sample.start(); - return 0; + bool use_tcp = false; + + std::string tcp_enable("--tcp"); + std::string udp_enable("--udp"); + + int i = 1; + while (i < argc) { + if (tcp_enable == argv[i]) { + use_tcp = true; + } else if (udp_enable == argv[i]) { + use_tcp = false; + } + i++; + } + + client_sample its_sample(use_tcp); + its_sample.init(); + its_sample.start(); + return 0; } diff --git a/examples/vsomeipd.cpp b/examples/vsomeipd.cpp deleted file mode 100644 index 6d2ede7..0000000 --- a/examples/vsomeipd.cpp +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright (C) 2014-2015 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/. - -// Example(!) for the most simple daemon application - -#include - -int main(int argc, char **argv) { - std::shared_ptr its_daemon - = vsomeip::runtime::get()->create_application("vsomeipd"); - - if (its_daemon->init()) - its_daemon->start(); - - return 0; -} diff --git a/exportmap.gcc b/exportmap.gcc index 4931d62..546738d 100644 --- a/exportmap.gcc +++ b/exportmap.gcc @@ -1,38 +1,40 @@ { global: - extern "C++" { - *vsomeip::configuration; - vsomeip::configuration::*; - *vsomeip::serializer; - vsomeip::serializer::*; - *vsomeip::deserializer; - vsomeip::deserializer::*; - *vsomeip::endpoint_definition; - vsomeip::endpoint_definition*; - *vsomeip::tcp*; - vsomeip::tcp*; - *vsomeip::udp*; - vsomeip::udp*; - *vsomeip::logger; - vsomeip::logger::get*; - *vsomeip::message_base_impl; - *vsomeip::message_base_impl::*; - *vsomeip::message_header_impl; - *vsomeip::message_header_impl::*; - *vsomeip::runtime; - vsomeip::runtime::get*; - *vsomeip::application_impl; - vsomeip::application_impl*; - *vsomeip::eventgroupinfo; - vsomeip::eventgroupinfo::*; - *vsomeip::servicegroup; - vsomeip::servicegroup::*; - *vsomeip::serviceinfo; - vsomeip::serviceinfo::*; - *vsomeip::sd::runtime; - vsomeip::sd::runtime::*; - }; - VSOMEIP_SD_RUNTIME; + extern "C++" { + *vsomeip::configuration; + vsomeip::configuration::*; + *vsomeip::cfg::configuration_impl; + vsomeip::cfg::configuration_impl::*; + *vsomeip::serializer; + vsomeip::serializer::*; + *vsomeip::deserializer; + vsomeip::deserializer::*; + *vsomeip::endpoint_definition; + vsomeip::endpoint_definition*; + *vsomeip::tcp*; + vsomeip::tcp*; + *vsomeip::udp*; + vsomeip::udp*; + *vsomeip::logger; + vsomeip::logger::get*; + *vsomeip::message_base_impl; + *vsomeip::message_base_impl::*; + *vsomeip::message_header_impl; + *vsomeip::message_header_impl::*; + *vsomeip::runtime; + vsomeip::runtime::get*; + *vsomeip::application_impl; + vsomeip::application_impl*; + *vsomeip::eventgroupinfo; + vsomeip::eventgroupinfo::*; + *vsomeip::servicegroup; + vsomeip::servicegroup::*; + *vsomeip::serviceinfo; + vsomeip::serviceinfo::*; + *vsomeip::sd::runtime; + vsomeip::sd::runtime::*; + }; + VSOMEIP_SD_RUNTIME; local: - *; + *; }; diff --git a/implementation/configuration/include/configuration.hpp b/implementation/configuration/include/configuration.hpp new file mode 100644 index 0000000..2f106ee --- /dev/null +++ b/implementation/configuration/include/configuration.hpp @@ -0,0 +1,89 @@ +// Copyright (C) 2014-2015 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_CONFIGURATION_HPP +#define VSOMEIP_CONFIGURATION_HPP + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include "internal.hpp" + +namespace vsomeip { + +class event; + +class VSOMEIP_EXPORT configuration { +public: + static std::shared_ptr get( + const std::set &_input = std::set()); + static void reset(); + virtual ~configuration() {} + + virtual const boost::asio::ip::address & get_unicast_address() const = 0; + virtual bool is_v4() const = 0; + virtual bool is_v6() const = 0; + + virtual bool has_console_log() const = 0; + virtual bool has_file_log() const = 0; + virtual bool has_dlt_log() const = 0; + virtual const std::string & get_logfile() const = 0; + virtual boost::log::trivial::severity_level get_loglevel() const = 0; + + virtual const std::string & get_routing_host() const = 0; + + virtual std::string get_unicast_address(service_t _service, + instance_t _instance) const = 0; + virtual std::string get_multicast_address(service_t _service, + instance_t _instance) const = 0; + virtual uint16_t get_multicast_port(service_t _service, + instance_t _instance) const = 0; + virtual uint16_t get_multicast_group(service_t _service, + instance_t _instance) const = 0; + virtual uint16_t get_reliable_port(service_t _service, + instance_t _instance) const = 0; + virtual bool is_someip(service_t _service, instance_t _instance) const = 0; + virtual bool has_enabled_magic_cookies(std::string _address, + uint16_t _port) const = 0; + virtual uint16_t get_unreliable_port(service_t _service, + instance_t _instance) const = 0; + + virtual std::set > get_remote_services() const = 0; + + virtual client_t get_id(const std::string &_name) const = 0; + virtual std::size_t get_num_dispatchers(const std::string &_name) const = 0; + + virtual std::uint32_t get_max_message_size_local() const = 0; + virtual std::uint32_t get_message_size_reliable(const std::string& _address, + std::uint16_t _port) const = 0; + + // Service Discovery configuration + virtual bool is_sd_enabled() const = 0; + + virtual const std::string & get_sd_multicast() const = 0; + virtual uint16_t get_sd_port() const = 0; + virtual const std::string & get_sd_protocol() const = 0; + + virtual int32_t get_sd_initial_delay_min() const = 0; + virtual int32_t get_sd_initial_delay_max() const = 0; + virtual int32_t get_sd_repetitions_base_delay() const = 0; + virtual uint8_t get_sd_repetitions_max() const = 0; + 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; +}; + +} // namespace vsomeip + +#endif // VSOMEIP_CONFIGURATION_HPP diff --git a/implementation/configuration/include/configuration_impl.hpp b/implementation/configuration/include/configuration_impl.hpp index 8a57633..04f4a22 100644 --- a/implementation/configuration/include/configuration_impl.hpp +++ b/implementation/configuration/include/configuration_impl.hpp @@ -9,10 +9,11 @@ #include #include #include +#include #include -#include +#include "configuration.hpp" namespace vsomeip { namespace cfg { @@ -20,16 +21,20 @@ namespace cfg { struct service; struct servicegroup; -class configuration_impl: public configuration { +class VSOMEIP_EXPORT configuration_impl: public configuration { public: - static configuration * get(const std::string &_path); + static std::shared_ptr get( + const std::set &_input); + static void reset(); configuration_impl(); + configuration_impl(const configuration_impl &_cfg); virtual ~configuration_impl(); - bool load(const std::string &_path); + void load(const boost::property_tree::ptree &_tree); + void load_log(const std::vector &_trees); - const boost::asio::ip::address & get_unicast() const; + const boost::asio::ip::address & get_unicast_address() const; bool is_v4() const; bool is_v6() const; @@ -39,18 +44,7 @@ public: const std::string & get_logfile() const; boost::log::trivial::severity_level get_loglevel() const; - std::string get_group(service_t _service, instance_t _instance) const; - std::set get_servicegroups() const; - - bool is_local_servicegroup(const std::string &_name) const; - int32_t get_min_initial_delay(const std::string &_name) const; - int32_t get_max_initial_delay(const std::string &_name) const; - int32_t get_repetition_base_delay(const std::string &_name) const; - uint8_t get_repetition_max(const std::string &_name) const; - int32_t get_cyclic_offer_delay(const std::string &_name) const; - int32_t get_cyclic_request_delay(const std::string &_name) const; - - std::string get_unicast(service_t _service, instance_t _instance) const; + std::string get_unicast_address(service_t _service, instance_t _instance) const; std::string get_multicast_address(service_t _service, instance_t _instance) const; uint16_t get_multicast_port(service_t _service, @@ -63,56 +57,65 @@ public: uint16_t get_unreliable_port(service_t _service, instance_t _instance) const; - const std::string & get_routing_host() const; + bool is_someip(service_t _service, instance_t _instance) const; - bool is_service_discovery_enabled() const; - const std::string & get_service_discovery_multicast() const; - uint16_t get_service_discovery_port() const; - const std::string & get_service_discovery_protocol() const; + const std::string & get_routing_host() const; client_t get_id(const std::string &_name) const; std::size_t get_num_dispatchers(const std::string &_name) const; std::set > get_remote_services() const; - std::map > > > get_eventgroups() const; - std::map > > get_events() const; - void set_event(std::shared_ptr &_event) const; + std::uint32_t get_max_message_size_local() const; + std::uint32_t get_message_size_reliable(const std::string& _address, + std::uint16_t _port) const; + + // Service Discovery configuration + bool is_sd_enabled() const; + + const std::string & get_sd_multicast() const; + uint16_t get_sd_port() const; + const std::string & get_sd_protocol() const; + + int32_t get_sd_initial_delay_min() const; + int32_t get_sd_initial_delay_max() const; + int32_t get_sd_repetitions_base_delay() const; + uint8_t get_sd_repetitions_max() const; + ttl_t get_sd_ttl() const; + int32_t get_sd_cyclic_offer_delay() const; + int32_t get_sd_request_response_delay() const; private: - bool get_someip_configuration(boost::property_tree::ptree &_tree); - bool get_logging_configuration(boost::property_tree::ptree &_tree); - bool get_services_configuration(boost::property_tree::ptree &_tree); - bool get_routing_configuration(boost::property_tree::ptree &_tree); - bool get_service_discovery_configuration( - boost::property_tree::ptree &_tree); - bool get_applications_configuration(boost::property_tree::ptree &_tree); - - bool get_servicegroup_configuration( - const boost::property_tree::ptree &_tree); - bool get_delays_configuration(std::shared_ptr &_group, + void get_logging_configuration(const boost::property_tree::ptree &_tree); + + void get_someip_configuration(const boost::property_tree::ptree &_tree); + void get_services_configuration(const boost::property_tree::ptree &_tree); + void get_payload_sizes_configuration(const boost::property_tree::ptree &_tree); + void get_routing_configuration(const boost::property_tree::ptree &_tree); + void get_service_discovery_configuration( const boost::property_tree::ptree &_tree); - bool get_service_configuration(std::shared_ptr &_group, + void get_applications_configuration(const boost::property_tree::ptree &_tree); + + void get_servicegroup_configuration( const boost::property_tree::ptree &_tree); - bool get_event_configuration(std::shared_ptr &_service, + 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_event_configuration(std::shared_ptr &_service, const boost::property_tree::ptree &_tree); - bool get_eventgroup_configuration(std::shared_ptr &_service, + void get_eventgroup_configuration(std::shared_ptr &_service, const boost::property_tree::ptree &_tree); - bool get_application_configuration( + void get_application_configuration( const boost::property_tree::ptree &_tree); servicegroup * find_servicegroup(const std::string &_name) const; service * find_service(service_t _service, instance_t _instance) const; private: - static std::map the_configurations; + static std::shared_ptr the_configuration; static std::mutex mutex_; +protected: // Configuration data boost::asio::ip::address unicast_; @@ -122,21 +125,31 @@ private: std::string logfile_; boost::log::trivial::severity_level loglevel_; - std::map > servicegroups_; + std::map> applications_; + std::map > > services_; std::string routing_host_; - bool is_service_discovery_enabled_; - std::string service_discovery_multicast_; - uint16_t service_discovery_port_; - std::string service_discovery_protocol_; + bool is_sd_enabled_; + std::string sd_protocol_; + std::string sd_multicast_; + uint16_t sd_port_; - std::map> applications_; + int32_t sd_initial_delay_min_; + int32_t sd_initial_delay_max_; + int32_t sd_repetitions_base_delay_; + uint8_t sd_repetitions_max_; + ttl_t sd_ttl_; + int32_t sd_cyclic_offer_delay_; + int32_t sd_request_response_delay_; std::map > magic_cookies_; + + std::map> message_sizes_; + std::uint32_t max_configured_message_size_; }; } // namespace cfg diff --git a/implementation/configuration/include/internal.hpp.in b/implementation/configuration/include/internal.hpp.in index 4038b55..3700a89 100644 --- a/implementation/configuration/include/internal.hpp.in +++ b/implementation/configuration/include/internal.hpp.in @@ -8,53 +8,88 @@ #include -namespace vsomeip { +#define VSOMEIP_ENV_APPLICATION_NAME "VSOMEIP_APPLICATION_NAME" +#define VSOMEIP_ENV_CONFIGURATION "VSOMEIP_CONFIGURATION" +#define VSOMEIP_ENV_CONFIGURATION_MODULE "VSOMEIP_CONFIGURATION_MODULE" + +#define VSOMEIP_DEFAULT_CONFIGURATION_FILE "/etc/vsomeip.json" +#define VSOMEIP_LOCAL_CONFIGURATION_FILE "./vsomeip.json" + +#define VSOMEIP_DEFAULT_CONFIGURATION_FOLDER "/etc/vsomeip" +#define VSOMEIP_LOCAL_CONFIGURATION_FOLDER "./vsomeip" + +#define VSOMEIP_BASE_PATH "/tmp/vsomeip-" + +#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" + +#define VSOMEIP_ROUTING "@VSOMEIP_ROUTING@" +#define VSOMEIP_ROUTING_CLIENT 0 -#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" +#ifdef WIN32 +#define VSOMEIP_INTERNAL_BASE_PORT 51234 +#endif -#define VSOMEIP_ROUTING_CLIENT 0 +#define VSOMEIP_UNICAST_ADDRESS "@VSOMEIP_UNICAST_ADDRESS@" -#define VSOMEIP_DEFAULT_CONNECT_TIMEOUT 100 -#define VSOMEIP_DEFAULT_FLUSH_TIMEOUT 1000 +#define VSOMEIP_DEFAULT_CONNECT_TIMEOUT 100 +#define VSOMEIP_DEFAULT_FLUSH_TIMEOUT 1000 -#define VSOMEIP_DEFAULT_WATCHDOG_CYCLE 1000 -#define VSOMEIP_DEFAULT_WATCHDOG_TIMEOUT 1000 -#define VSOMEIP_DEFAULT_MAX_MISSING_PONGS 3 +#define VSOMEIP_DEFAULT_WATCHDOG_CYCLE 5000 +#define VSOMEIP_DEFAULT_WATCHDOG_TIMEOUT 5000 +#define VSOMEIP_DEFAULT_MAX_MISSING_PONGS 3 -#define VSOMEIP_INVALID_PORT 0xFFFF +#define VSOMEIP_COMMAND_HEADER_SIZE 7 -#define VSOMEIP_COMMAND_HEADER_SIZE 7 +#define VSOMEIP_COMMAND_TYPE_POS 0 +#define VSOMEIP_COMMAND_CLIENT_POS 1 +#define VSOMEIP_COMMAND_SIZE_POS_MIN 3 +#define VSOMEIP_COMMAND_SIZE_POS_MAX 5 +#define VSOMEIP_COMMAND_PAYLOAD_POS 7 -#define VSOMEIP_COMMAND_TYPE_POS 0 -#define VSOMEIP_COMMAND_CLIENT_POS 1 -#define VSOMEIP_COMMAND_SIZE_POS_MIN 3 -#define VSOMEIP_COMMAND_SIZE_POS_MAX 5 -#define VSOMEIP_COMMAND_PAYLOAD_POS 7 +#define VSOMEIP_REGISTER_APPLICATION 0x00 +#define VSOMEIP_DEREGISTER_APPLICATION 0x01 +#define VSOMEIP_APPLICATION_LOST 0x02 +#define VSOMEIP_ROUTING_INFO 0x03 -#define VSOMEIP_REGISTER_APPLICATION 0x00 -#define VSOMEIP_DEREGISTER_APPLICATION 0x01 -#define VSOMEIP_APPLICATION_LOST 0x02 -#define VSOMEIP_ROUTING_INFO 0x03 +#define VSOMEIP_PING 0x0E +#define VSOMEIP_PONG 0x0F -#define VSOMEIP_PING 0x0E -#define VSOMEIP_PONG 0x0F +#define VSOMEIP_OFFER_SERVICE 0x10 +#define VSOMEIP_STOP_OFFER_SERVICE 0x11 +#define VSOMEIP_SUBSCRIBE 0x12 +#define VSOMEIP_UNSUBSCRIBE 0x13 +#define VSOMEIP_REQUEST_SERVICE 0x14 +#define VSOMEIP_RELEASE_SERVICE 0x15 -#define VSOMEIP_OFFER_SERVICE 0x10 -#define VSOMEIP_STOP_OFFER_SERVICE 0x11 -#define VSOMEIP_SUBSCRIBE 0x12 -#define VSOMEIP_UNSUBSCRIBE 0x13 -#define VSOMEIP_REQUEST_SERVICE 0x14 +#define VSOMEIP_SEND 0x17 +#define VSOMEIP_NOTIFY 0x18 -#define VSOMEIP_SEND 0x17 -#define VSOMEIP_SET 0x18 +#define VSOMEIP_REGISTER_EVENT 0x19 +#define VSOMEIP_UNREGISTER_EVENT 0x1A + +#define VSOMEIP_OFFER_SERVICE_COMMAND_SIZE 20 +#define VSOMEIP_REQUEST_SERVICE_COMMAND_SIZE 21 +#define VSOMEIP_STOP_OFFER_SERVICE_COMMAND_SIZE 11 +#define VSOMEIP_SUBSCRIBE_COMMAND_SIZE 18 +#define VSOMEIP_UNSUBSCRIBE_COMMAND_SIZE 13 +#define VSOMEIP_REGISTER_EVENT_COMMAND_SIZE 15 +#define VSOMEIP_UNREGISTER_EVENT_COMMAND_SIZE 13 + +#include + +#define VSOMEIP_DATA_ID 0x677D +#define VSOMEIP_SHM_NAME "/vsomeip" +#define VSOMEIP_DIAGNOSIS_ADDRESS @VSOMEIP_DIAGNOSIS_ADDRESS@ + +namespace vsomeip { -#define VSOMEIP_OFFER_SERVICE_COMMAND_SIZE 20 -#define VSOMEIP_REQUEST_SERVICE_COMMAND_SIZE 21 -#define VSOMEIP_STOP_OFFER_SERVICE_COMMAND_SIZE 11 -#define VSOMEIP_SUBSCRIBE_COMMAND_SIZE 18 -#define VSOMEIP_UNSUBSCRIBE_COMMAND_SIZE 13 +struct configuration_data_t { + std::mutex mutex_; + unsigned short next_client_id_; + unsigned short ref_; +}; } // namespace vsomeip diff --git a/implementation/configuration/include/service.hpp b/implementation/configuration/include/service.hpp index 067dc41..bbe235e 100644 --- a/implementation/configuration/include/service.hpp +++ b/implementation/configuration/include/service.hpp @@ -20,6 +20,8 @@ struct service { service_t service_; instance_t instance_; + std::string unicast_address_; + uint16_t reliable_; uint16_t unreliable_; @@ -27,7 +29,7 @@ struct service { uint16_t multicast_port_; eventgroup_t multicast_group_; - bool use_magic_cookies_; + std::string protocol_; std::shared_ptr group_; std::map > events_; diff --git a/implementation/configuration/include/servicegroup.hpp b/implementation/configuration/include/servicegroup.hpp deleted file mode 100644 index e44d79f..0000000 --- a/implementation/configuration/include/servicegroup.hpp +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright (C) 2014-2015 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_SERVICEGROUP_HPP -#define VSOMEIP_CFG_SERVICEGROUP_HPP - -namespace vsomeip { -namespace cfg { - -struct servicegroup { - std::string name_; // Name of the ServiceGroup - std::string unicast_; // either "local" or an IP address - - uint32_t min_initial_delay_; - uint32_t max_initial_delay_; - uint32_t repetition_base_delay_; - uint32_t cyclic_offer_delay_; - uint32_t cyclic_request_delay_; - uint8_t repetition_max_; -}; - -} // namespace cfg -} // namespace vsomeip - -#endif // VSOMEIP_CFG_SERVICEGROUP_HPP diff --git a/implementation/configuration/src/configuration.cpp b/implementation/configuration/src/configuration.cpp index 9a11b22..9bc90d4 100644 --- a/implementation/configuration/src/configuration.cpp +++ b/implementation/configuration/src/configuration.cpp @@ -7,8 +7,13 @@ namespace vsomeip { -configuration * configuration::get(const std::string &_path) { - return cfg::configuration_impl::get(_path); +std::shared_ptr configuration::get( + const std::set &_input) { + return cfg::configuration_impl::get(_input); +} + +void configuration::reset() { + cfg::configuration_impl::reset(); } } // namespace vsomeip diff --git a/implementation/configuration/src/configuration_impl.cpp b/implementation/configuration/src/configuration_impl.cpp index 591a3dc..66a1219 100644 --- a/implementation/configuration/src/configuration_impl.cpp +++ b/implementation/configuration/src/configuration_impl.cpp @@ -4,12 +4,17 @@ // file, You can obtain one at http://mozilla.org/MPL/2.0/. #include -#include +#include #include #define WIN32_LEAN_AND_MEAN +#if defined ( WIN32 ) +#define __func__ __FUNCTION__ +#endif + #include +#include #include #include @@ -18,102 +23,162 @@ #include "../include/configuration_impl.hpp" #include "../include/event.hpp" #include "../include/eventgroup.hpp" -#include "../include/servicegroup.hpp" #include "../include/service.hpp" +#include "../include/internal.hpp" #include "../../logging/include/logger_impl.hpp" #include "../../routing/include/event.hpp" #include "../../service_discovery/include/defines.hpp" +#include "../../utility/include/utility.hpp" namespace vsomeip { namespace cfg { -std::map configuration_impl::the_configurations; +std::shared_ptr configuration_impl::the_configuration; std::mutex configuration_impl::mutex_; -configuration * configuration_impl::get(const std::string &_path) { - configuration *its_configuration(0); - - bool is_freshly_loaded(false); - { - std::lock_guard its_lock(mutex_); - - auto found_configuration = the_configurations.find(_path); - if (found_configuration != the_configurations.end()) { - its_configuration = found_configuration->second; - } else { - its_configuration = new configuration_impl; - if (its_configuration->load(_path)) { - the_configurations[_path] = its_configuration; - is_freshly_loaded = true; - } else { - delete its_configuration; - its_configuration = 0; +std::shared_ptr configuration_impl::get( + const std::set &_input) { + std::shared_ptr its_configuration; + std::lock_guard its_lock(mutex_); + + if (!the_configuration) { + the_configuration = std::make_shared(); + std::vector its_tree_set; + + // 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_tree_set.push_back(its_tree); + } + catch (...) { + } + } 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_tree_set.push_back(its_tree); + } + catch (...) { + } + } + } } } + + // Load log configuration + the_configuration->load_log(its_tree_set); + + // Load other configuration parts + for (auto t : its_tree_set) + the_configuration->load(t); } - if (is_freshly_loaded) - logger_impl::init(_path); + return the_configuration; +} - return its_configuration; +void configuration_impl::reset() { + the_configuration.reset(); } configuration_impl::configuration_impl() : - has_console_log_(true), has_file_log_(false), has_dlt_log_(false), logfile_( - "/tmp/vsomeip.log"), loglevel_( - boost::log::trivial::severity_level::info), routing_host_( - "vsomeipd"), is_service_discovery_enabled_(false) { + 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) { - unicast_ = unicast_.from_string("127.0.0.1"); + unicast_ = unicast_.from_string(VSOMEIP_UNICAST_ADDRESS); } -configuration_impl::~configuration_impl() { +configuration_impl::configuration_impl(const configuration_impl &_other) : + max_configured_message_size_(0) { + + applications_.insert(_other.applications_.begin(), _other.applications_.end()); + services_.insert(_other.services_.begin(), _other.services_.end()); + + unicast_ = _other.unicast_; + + has_console_log_ = _other.has_console_log_; + has_file_log_ = _other.has_file_log_; + has_dlt_log_ = _other.has_dlt_log_; + logfile_ = _other.logfile_; + + loglevel_ = _other.loglevel_; + + routing_host_ = _other.routing_host_; + + is_sd_enabled_ = _other.is_sd_enabled_; + sd_multicast_ = _other.sd_multicast_; + sd_port_ = _other.sd_port_; + sd_protocol_ = _other.sd_protocol_; + + sd_initial_delay_min_ = _other.sd_initial_delay_min_; + sd_initial_delay_max_ = _other.sd_initial_delay_max_; + sd_repetitions_base_delay_= _other.sd_repetitions_base_delay_; + sd_repetitions_max_ = _other.sd_repetitions_max_; + sd_ttl_ = _other.sd_ttl_; + sd_cyclic_offer_delay_= _other.sd_cyclic_offer_delay_; + sd_request_response_delay_= _other.sd_request_response_delay_; + + magic_cookies_.insert(_other.magic_cookies_.begin(), _other.magic_cookies_.end()); } -bool configuration_impl::load(const std::string &_path) { - bool is_loaded(true); - boost::property_tree::ptree its_tree; +configuration_impl::~configuration_impl() { +} +void configuration_impl::load(const boost::property_tree::ptree &_tree) { try { - boost::property_tree::json_parser::read_json(_path, its_tree); - // Read the configuration data - is_loaded = get_someip_configuration(its_tree); - is_loaded = get_logging_configuration(its_tree); - is_loaded = is_loaded && get_services_configuration(its_tree); - is_loaded = is_loaded && get_routing_configuration(its_tree); - is_loaded = is_loaded && get_service_discovery_configuration(its_tree); - is_loaded = is_loaded && get_applications_configuration(its_tree); + get_someip_configuration(_tree); + get_services_configuration(_tree); + get_payload_sizes_configuration(_tree); + get_routing_configuration(_tree); + get_service_discovery_configuration(_tree); + get_applications_configuration(_tree); } catch (std::exception &e) { - std::cerr << e.what() << std::endl; - is_loaded = false; } - - return is_loaded; } -bool configuration_impl::get_someip_configuration( - boost::property_tree::ptree &_tree) { - bool is_loaded(true); - try { - std::string its_value = _tree.get("unicast"); - unicast_ = unicast_.from_string(its_value); - } catch (...) { - is_loaded = false; - } - return is_loaded; +void configuration_impl::load_log(const std::vector &_trees) { + // Read the logger configuration(s) + for (auto t : _trees) + get_logging_configuration(t); + + // Initialize logger + logger_impl::init(the_configuration); } -bool configuration_impl::get_logging_configuration( - boost::property_tree::ptree &_tree) { - bool is_loaded(true); +void configuration_impl::get_logging_configuration( + const boost::property_tree::ptree &_tree) { try { auto its_logging = _tree.get_child("logging"); for (auto i = its_logging.begin(); i != its_logging.end(); ++i) { std::string its_key(i->first); if (its_key == "console") { - std::string its_value(i->second.data()); - has_console_log_ = (its_value == "true"); + std::string its_value(i->second.data()); + has_console_log_ = (its_value == "true"); } else if (its_key == "file") { for (auto j : i->second) { std::string its_sub_key(j.first); @@ -129,127 +194,187 @@ bool configuration_impl::get_logging_configuration( has_dlt_log_ = (its_value == "true"); } else if (its_key == "level") { std::string its_value(i->second.data()); - loglevel_ = (its_value == "trace" ? - boost::log::trivial::severity_level::trace : - (its_value == "debug" ? - boost::log::trivial::severity_level::debug : - (its_value == "info" ? - boost::log::trivial::severity_level::info : - (its_value == "warning" ? - boost::log::trivial::severity_level::warning : - (its_value == "error" ? - boost::log::trivial::severity_level::error : - (its_value == "fatal" ? - boost::log::trivial::severity_level::fatal : - boost::log::trivial::severity_level::info)))))); + loglevel_ + = (its_value == "trace" ? + boost::log::trivial::severity_level::trace : + (its_value == "debug" ? + boost::log::trivial::severity_level::debug : + (its_value == "info" ? + boost::log::trivial::severity_level::info : + (its_value == "warning" ? + boost::log::trivial::severity_level::warning : + (its_value == "error" ? + boost::log::trivial::severity_level::error : + (its_value == "fatal" ? + boost::log::trivial::severity_level::fatal : + boost::log::trivial::severity_level::info)))))); } } } catch (...) { - is_loaded = false; } - return is_loaded; } -bool configuration_impl::get_services_configuration( - boost::property_tree::ptree &_tree) { - bool is_loaded(true); +void configuration_impl::get_someip_configuration( + const boost::property_tree::ptree &_tree) { try { - auto its_services = _tree.get_child("servicegroups"); + std::string its_value = _tree.get("unicast"); + unicast_ = unicast_.from_string(its_value); + } catch (...) { + } +} + +void configuration_impl::get_services_configuration( + 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) - is_loaded = is_loaded && get_servicegroup_configuration(i->second); + get_service_configuration(i->second, ""); } catch (...) { - // This section is optional! + 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! + } } - return is_loaded; } -bool configuration_impl::get_servicegroup_configuration( +void configuration_impl::get_payload_sizes_configuration( const boost::property_tree::ptree &_tree) { - bool is_loaded(true); + const std::string payload_sizes("payload-sizes"); try { - std::shared_ptr its_servicegroup( - std::make_shared()); - its_servicegroup->unicast_ = "local"; // Default + 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::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::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 (...) { + } +} + +void configuration_impl::get_servicegroup_configuration( + 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 == "name") { - its_servicegroup->name_ = i->second.data(); - } else if (its_key == "unicast") { - its_servicegroup->unicast_ = i->second.data(); - } else if (its_key == "delays") { - is_loaded = is_loaded - && get_delays_configuration(its_servicegroup, - i->second); + 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") { + get_delays_configuration(i->second); } else if (its_key == "services") { for (auto j = i->second.begin(); j != i->second.end(); ++j) - is_loaded = is_loaded - && get_service_configuration(its_servicegroup, - j->second); + get_service_configuration(j->second, its_unicast_address); } } - servicegroups_[its_servicegroup->name_] = its_servicegroup; } catch (...) { - is_loaded = false; } - return is_loaded; } -bool configuration_impl::get_delays_configuration( - std::shared_ptr &_group, +void configuration_impl::get_delays_configuration( const boost::property_tree::ptree &_tree) { - bool is_loaded(true); try { std::stringstream its_converter; for (auto i = _tree.begin(); i != _tree.end(); ++i) { std::string its_key(i->first); if (its_key == "initial") { - _group->min_initial_delay_ = i->second.get("minimum"); - _group->max_initial_delay_ = i->second.get("maximum"); + sd_initial_delay_min_ = i->second.get("minimum"); + sd_initial_delay_max_ = i->second.get("maximum"); } else if (its_key == "repetition-base") { its_converter << std::dec << i->second.data(); - its_converter >> _group->repetition_base_delay_; + its_converter >> sd_repetitions_base_delay_; } else if (its_key == "repetition-max") { int tmp_repetition_max; its_converter << std::dec << i->second.data(); its_converter >> tmp_repetition_max; - _group->repetition_max_ = tmp_repetition_max; + sd_repetitions_max_ = uint8_t(tmp_repetition_max); } else if (its_key == "cyclic-offer") { its_converter << std::dec << i->second.data(); - its_converter >> _group->cyclic_offer_delay_; + its_converter >> sd_cyclic_offer_delay_; } else if (its_key == "cyclic-request") { its_converter << std::dec << i->second.data(); - its_converter >> _group->cyclic_request_delay_; + its_converter >> sd_request_response_delay_; } its_converter.str(""); its_converter.clear(); } } catch (...) { - is_loaded = false; } - return is_loaded; } -bool configuration_impl::get_service_configuration( - std::shared_ptr &_group, - const boost::property_tree::ptree &_tree) { - bool is_loaded(true); +void configuration_impl::get_service_configuration( + const boost::property_tree::ptree &_tree, + const std::string &_unicast_address) { try { + bool is_loaded(true); bool use_magic_cookies(false); std::shared_ptr its_service(std::make_shared()); its_service->reliable_ = its_service->unreliable_ = ILLEGAL_PORT; - its_service->use_magic_cookies_ = false; - its_service->group_ = _group; + its_service->unicast_address_ = _unicast_address; its_service->multicast_address_ = ""; its_service->multicast_port_ = ILLEGAL_PORT; its_service->multicast_group_ = 0xFFFF; // TODO: use symbolic constant + its_service->protocol_ = "someip"; 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") { + if (its_key == "unicast") { + its_service->unicast_address_ = its_value; + } else if (its_key == "reliable") { try { its_value = i->second.get_child("port").data(); its_converter << its_value; @@ -259,8 +384,8 @@ bool configuration_impl::get_service_configuration( its_converter >> its_service->reliable_; } try { - its_value = - i->second.get_child("enable-magic-cookies").data(); + its_value + = i->second.get_child("enable-magic-cookies").data(); use_magic_cookies = ("true" == its_value); } catch (...) { @@ -277,6 +402,8 @@ bool configuration_impl::get_service_configuration( its_converter >> its_service->multicast_port_; } catch (...) { } + } else if (its_key == "protocol") { + its_service->protocol_ = its_value; } else if (its_key == "events") { get_event_configuration(its_service, i->second); } else if (its_key == "eventgroups") { @@ -309,24 +436,18 @@ bool configuration_impl::get_service_configuration( if (is_loaded) { services_[its_service->service_][its_service->instance_] = its_service; - } - - if (use_magic_cookies) { - std::string its_unicast(_group->unicast_); - if (its_unicast == "local") - its_unicast = unicast_.to_string(); - magic_cookies_[its_unicast].insert(its_service->reliable_); + if (use_magic_cookies) { + magic_cookies_[its_service->unicast_address_].insert( + its_service->reliable_); + } } } catch (...) { - is_loaded = false; } - return is_loaded; } -bool configuration_impl::get_event_configuration( +void configuration_impl::get_event_configuration( std::shared_ptr &_service, const boost::property_tree::ptree &_tree) { - bool is_loaded(true); for (auto i = _tree.begin(); i != _tree.end(); ++i) { event_t its_event_id(0); bool its_is_field(false); @@ -361,12 +482,11 @@ bool configuration_impl::get_event_configuration( } } } - return is_loaded; } -bool configuration_impl::get_eventgroup_configuration( + +void configuration_impl::get_eventgroup_configuration( std::shared_ptr &_service, const boost::property_tree::ptree &_tree) { - bool is_loaded(true); bool is_multicast; for (auto i = _tree.begin(); i != _tree.end(); ++i) { is_multicast = false; @@ -423,68 +543,80 @@ bool configuration_impl::get_eventgroup_configuration( _service->eventgroups_[its_eventgroup->id_] = its_eventgroup; } } - return is_loaded; } -bool configuration_impl::get_routing_configuration( - boost::property_tree::ptree &_tree) { - bool is_loaded(true); +void configuration_impl::get_routing_configuration( + const boost::property_tree::ptree &_tree) { try { auto its_routing = _tree.get_child("routing"); routing_host_ = its_routing.data(); } catch (...) { - is_loaded = false; } - return is_loaded; } -bool configuration_impl::get_service_discovery_configuration( - boost::property_tree::ptree &_tree) { - bool is_loaded(true); +void configuration_impl::get_service_discovery_configuration( + const boost::property_tree::ptree &_tree) { try { auto its_service_discovery = _tree.get_child("service-discovery"); 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") { - is_service_discovery_enabled_ = (its_value == "true"); + is_sd_enabled_ = (its_value == "true"); } else if (its_key == "multicast") { - service_discovery_multicast_ = its_value; + sd_multicast_ = its_value; } else if (its_key == "port") { - std::stringstream its_converter; its_converter << its_value; - its_converter >> service_discovery_port_; + its_converter >> sd_port_; } else if (its_key == "protocol") { - service_discovery_protocol_ = its_value; + sd_protocol_ = its_value; + } else if (its_key == "initial_delay_min") { + its_converter << its_value; + its_converter >> sd_initial_delay_min_; + } else if (its_key == "initial_delay_max") { + its_converter << its_value; + its_converter >> sd_initial_delay_max_; + } else if (its_key == "repetitions_base_delay") { + its_converter << its_value; + its_converter >> sd_repetitions_base_delay_; + } else if (its_key == "repetitions_max") { + int tmp; + its_converter << its_value; + its_converter >> tmp; + sd_repetitions_max_ = (uint8_t)tmp; + } else if (its_key == "ttl") { + its_converter << its_value; + its_converter >> sd_ttl_; + } else if (its_key == "cyclic_offer_delay") { + its_converter << its_value; + its_converter >> sd_cyclic_offer_delay_; + } else if (its_key == "request_response_delay") { + its_converter << its_value; + its_converter >> sd_request_response_delay_; } } } catch (...) { - is_loaded = false; } - - return is_loaded; } -bool configuration_impl::get_applications_configuration( - boost::property_tree::ptree &_tree) { - bool is_loaded(true); +void configuration_impl::get_applications_configuration( + const boost::property_tree::ptree &_tree) { try { std::stringstream its_converter; auto its_applications = _tree.get_child("applications"); - for (auto i = its_applications.begin(); i != its_applications.end(); - ++i) - is_loaded = is_loaded && get_application_configuration(i->second); + for (auto i = its_applications.begin(); + i != its_applications.end(); + ++i) { + get_application_configuration(i->second); + } } catch (...) { - is_loaded = false; } - - return is_loaded; } -bool configuration_impl::get_application_configuration( +void configuration_impl::get_application_configuration( const boost::property_tree::ptree &_tree) { - bool is_loaded(true); std::string its_name(""); client_t its_id; std::size_t its_num_dispatchers(0); @@ -513,11 +645,10 @@ bool configuration_impl::get_application_configuration( if (its_name != "" && its_id != 0) { applications_[its_name] = {its_id, its_num_dispatchers}; } - return is_loaded; } // Public interface -const boost::asio::ip::address & configuration_impl::get_unicast() const { +const boost::asio::ip::address & configuration_impl::get_unicast_address() const { return unicast_; } @@ -549,107 +680,18 @@ boost::log::trivial::severity_level configuration_impl::get_loglevel() const { return loglevel_; } -std::set configuration_impl::get_servicegroups() const { - std::set its_keys; - for (auto i : servicegroups_) - its_keys.insert(i.first); - return its_keys; -} - -bool configuration_impl::is_local_servicegroup(const std::string &_name) const { - bool is_local(false); - - servicegroup *its_servicegroup = find_servicegroup(_name); - if (its_servicegroup) { - is_local = (its_servicegroup->unicast_ == "local" - || its_servicegroup->unicast_ == get_unicast().to_string()); - } - - return is_local; -} - -int32_t configuration_impl::get_min_initial_delay( - const std::string &_name) const { - int32_t its_delay = 0; - - servicegroup *its_servicegroup = find_servicegroup(_name); - if (its_servicegroup) - its_delay = its_servicegroup->min_initial_delay_; - - return its_delay; -} - -int32_t configuration_impl::get_max_initial_delay( - const std::string &_name) const { - int32_t its_delay = 0; - - servicegroup *its_servicegroup = find_servicegroup(_name); - if (its_servicegroup) - its_delay = its_servicegroup->max_initial_delay_; - - return its_delay; -} - -int32_t configuration_impl::get_repetition_base_delay( - const std::string &_name) const { - int32_t its_delay = 0; - - servicegroup *its_servicegroup = find_servicegroup(_name); - if (its_servicegroup) - its_delay = its_servicegroup->repetition_base_delay_; - - return its_delay; -} - -uint8_t configuration_impl::get_repetition_max(const std::string &_name) const { - uint8_t its_max = 0; - - servicegroup *its_servicegroup = find_servicegroup(_name); - if (its_servicegroup) - its_max = its_servicegroup->repetition_max_; - - return its_max; -} - -int32_t configuration_impl::get_cyclic_offer_delay( - const std::string &_name) const { - uint32_t its_delay = 0; - - servicegroup *its_servicegroup = find_servicegroup(_name); - if (its_servicegroup) - its_delay = its_servicegroup->cyclic_offer_delay_; - - return its_delay; -} - -int32_t configuration_impl::get_cyclic_request_delay( - const std::string &_name) const { - uint32_t its_delay = 0; - - servicegroup *its_servicegroup = find_servicegroup(_name); - if (its_servicegroup) - its_delay = its_servicegroup->cyclic_request_delay_; - - return its_delay; -} - -std::string configuration_impl::get_group(service_t _service, +std::string configuration_impl::get_unicast_address(service_t _service, instance_t _instance) const { - std::string its_group("default"); + std::string its_unicast_address(""); service *its_service = find_service(_service, _instance); - if (nullptr != its_service) { - its_group = its_service->group_->name_; + if (its_service) { + its_unicast_address = its_service->unicast_address_; } - return its_group; -} -std::string configuration_impl::get_unicast(service_t _service, - instance_t _instance) const { - std::string its_unicast(""); - service *its_service = find_service(_service, _instance); - if (its_service) - its_unicast = its_service->group_->unicast_; - return its_unicast; + if (its_unicast_address == "local" || its_unicast_address == "") { + its_unicast_address = get_unicast_address().to_string(); + } + return its_unicast_address; } std::string configuration_impl::get_multicast_address(service_t _service, @@ -681,8 +723,7 @@ uint16_t configuration_impl::get_multicast_group(service_t _service, uint16_t configuration_impl::get_reliable_port(service_t _service, instance_t _instance) const { - uint16_t its_reliable = ILLEGAL_PORT; - + uint16_t its_reliable(ILLEGAL_PORT); service *its_service = find_service(_service, _instance); if (its_service) its_reliable = its_service->reliable_; @@ -690,6 +731,15 @@ uint16_t configuration_impl::get_reliable_port(service_t _service, return its_reliable; } +bool configuration_impl::is_someip(service_t _service, + instance_t _instance) const { + service *its_service = find_service(_service, _instance); + if (its_service) + return (its_service->protocol_ == "someip"); + return true; // we need to explicitely configure a service to + // be something else than SOME/IP +} + bool configuration_impl::has_enabled_magic_cookies(std::string _address, uint16_t _port) const { bool has_enabled(false); @@ -718,24 +768,6 @@ const std::string & configuration_impl::get_routing_host() const { return routing_host_; } -bool configuration_impl::is_service_discovery_enabled() const { - return is_service_discovery_enabled_; -} - -const std::string & -configuration_impl::get_service_discovery_protocol() const { - return service_discovery_protocol_; -} - -const std::string & -configuration_impl::get_service_discovery_multicast() const { - return service_discovery_multicast_; -} - -uint16_t configuration_impl::get_service_discovery_port() const { - return service_discovery_port_; -} - client_t configuration_impl::get_id(const std::string &_name) const { client_t its_client = 0; @@ -764,76 +796,13 @@ configuration_impl::get_remote_services() const { std::set > its_remote_services; for (auto i : services_) { for (auto j : i.second) { - if (j.second->group_->unicast_ != "local") + if (j.second->unicast_address_ != "local" && j.second->unicast_address_ != "") its_remote_services.insert(std::make_pair(i.first, j.first)); } } return its_remote_services; } -std::map > > > -configuration_impl::get_eventgroups() const { - std::map > > > its_eventgroups; - for (auto i : services_) { - for (auto j : i.second) { - if (j.second->group_->unicast_ == "local") { - for (auto k : j.second->eventgroups_) { - for (auto l : k.second->events_) { - its_eventgroups[i.first][j.first] - [k.second->id_].insert(l->id_); - } - } - } - } - } - return its_eventgroups; -} - -std::map > > -configuration_impl::get_events() const { - std::map > > its_events; - for (auto i : services_) { - for (auto j : i.second) { - if (j.second->group_->unicast_ == "local") { - for (auto k : j.second->events_) { - its_events[i.first][j.first].insert(k.first); - } - } - } - } - return its_events; -} - -void configuration_impl::set_event( - std::shared_ptr &_event) const { - auto found_service = services_.find(_event->get_service()); - if (found_service != services_.end()) { - auto found_instance = found_service->second.find( - _event->get_instance()); - if (found_instance != found_service->second.end()) { - auto found_event = found_instance->second->events_.find( - _event->get_event()); - if (found_event != found_instance->second->events_.end()) { - _event->set_field(found_event->second->is_field_); - _event->set_reliable(found_event->second->is_reliable_); - } - } - } -} - -servicegroup *configuration_impl::find_servicegroup( - const std::string &_name) const { - servicegroup *its_servicegroup(0); - auto find_servicegroup = servicegroups_.find(_name); - if (find_servicegroup != servicegroups_.end()) { - its_servicegroup = find_servicegroup->second.get(); - } - return its_servicegroup; -} - service *configuration_impl::find_service(service_t _service, instance_t _instance) const { service *its_service(0); @@ -847,5 +816,81 @@ service *configuration_impl::find_service(service_t _service, return its_service; } +std::uint32_t configuration_impl::get_max_message_size_local() const { + uint32_t its_max_message_size = VSOMEIP_MAX_LOCAL_MESSAGE_SIZE; + if (VSOMEIP_MAX_TCP_MESSAGE_SIZE > its_max_message_size) { + its_max_message_size = VSOMEIP_MAX_TCP_MESSAGE_SIZE; + } + if (VSOMEIP_MAX_UDP_MESSAGE_SIZE > its_max_message_size) { + its_max_message_size = VSOMEIP_MAX_UDP_MESSAGE_SIZE; + } + if(its_max_message_size < max_configured_message_size_) { + its_max_message_size = max_configured_message_size_; + } + + // add sizes of the the routing_manager_proxy's messages + // to the routing_manager stub + return std::uint32_t(its_max_message_size + + VSOMEIP_COMMAND_HEADER_SIZE + sizeof(instance_t) + + sizeof(bool) + sizeof(bool)); +} + +std::uint32_t configuration_impl::get_message_size_reliable( + const std::string& _address, std::uint16_t _port) const { + auto its_address = message_sizes_.find(_address); + if(its_address != message_sizes_.end()) { + auto its_port = its_address->second.find(_port); + if(its_port != its_address->second.end()) { + return its_port->second; + } + } + return VSOMEIP_MAX_TCP_MESSAGE_SIZE; +} + +// Service Discovery configuration +bool configuration_impl::is_sd_enabled() const { + return is_sd_enabled_; +} + +const std::string & configuration_impl::get_sd_multicast() const { + return sd_multicast_; +} + +uint16_t configuration_impl::get_sd_port() const { + return sd_port_; +} + +const std::string & configuration_impl::get_sd_protocol() const { + return sd_protocol_; +} + +int32_t configuration_impl::get_sd_initial_delay_min() const { + return sd_initial_delay_min_; +} + +int32_t configuration_impl::get_sd_initial_delay_max() const { + return sd_initial_delay_max_; +} + +int32_t configuration_impl::get_sd_repetitions_base_delay() const { + return sd_repetitions_base_delay_; +} + +uint8_t configuration_impl::get_sd_repetitions_max() const { + return sd_repetitions_max_; +} + +ttl_t configuration_impl::get_sd_ttl() const { + return sd_ttl_; +} + +int32_t configuration_impl::get_sd_cyclic_offer_delay() const { + return sd_cyclic_offer_delay_; +} + +int32_t configuration_impl::get_sd_request_response_delay() const { + return sd_request_response_delay_; +} + } // namespace config } // namespace vsomeip diff --git a/implementation/endpoints/include/buffer.hpp b/implementation/endpoints/include/buffer.hpp index f76c8d1..5641117 100644 --- a/implementation/endpoints/include/buffer.hpp +++ b/implementation/endpoints/include/buffer.hpp @@ -14,8 +14,7 @@ namespace vsomeip { -typedef std::array packet_buffer_t; -typedef std::shared_ptr packet_buffer_ptr_t; +typedef std::vector receive_buffer_t; typedef std::vector message_buffer_t; typedef std::shared_ptr message_buffer_ptr_t; diff --git a/implementation/endpoints/include/client_endpoint_impl.hpp b/implementation/endpoints/include/client_endpoint_impl.hpp index 0be6616..29f42a3 100644 --- a/implementation/endpoints/include/client_endpoint_impl.hpp +++ b/implementation/endpoints/include/client_endpoint_impl.hpp @@ -6,6 +6,7 @@ #ifndef VSOMEIP_CLIENT_ENDPOINT_IMPL_HPP #define VSOMEIP_CLIENT_ENDPOINT_IMPL_HPP +#include #include #include #include @@ -32,7 +33,8 @@ public: typedef typename Protocol::endpoint endpoint_type; client_endpoint_impl(std::shared_ptr _host, - endpoint_type _remote, boost::asio::io_service &_io); + endpoint_type _remote, boost::asio::io_service &_io, + std::uint32_t _max_message_size); virtual ~client_endpoint_impl(); bool send(const uint8_t *_data, uint32_t _size, bool _flush);bool send_to( @@ -49,8 +51,7 @@ public: public: void connect_cbk(boost::system::error_code const &_error); void wait_connect_cbk(boost::system::error_code const &_error); - void send_cbk(message_buffer_ptr_t _buffer, - boost::system::error_code const &_error, std::size_t _bytes); + void send_cbk(boost::system::error_code const &_error, std::size_t _bytes); void flush_cbk(boost::system::error_code const &_error); public: @@ -58,24 +59,21 @@ public: virtual void receive() = 0; protected: - virtual void send_queued(message_buffer_ptr_t) = 0; + virtual void send_queued() = 0; socket_type socket_; endpoint_type remote_; boost::asio::system_timer flush_timer_; boost::asio::system_timer connect_timer_; - uint32_t connect_timeout_;bool is_connected_; + uint32_t connect_timeout_; + bool is_connected_; // send data message_buffer_ptr_t packetizer_; - - // receive data - message_buffer_t message_; + std::deque queue_; std::mutex mutex_; - - uint32_t queued_; }; } // namespace vsomeip diff --git a/implementation/endpoints/include/endpoint.hpp b/implementation/endpoints/include/endpoint.hpp index 49688ef..6acf164 100644 --- a/implementation/endpoints/include/endpoint.hpp +++ b/implementation/endpoints/include/endpoint.hpp @@ -42,6 +42,10 @@ public: virtual unsigned short get_remote_port() const = 0; virtual bool is_reliable() const = 0; virtual bool is_local() const = 0; + + virtual void increment_use_count() = 0; + virtual void decrement_use_count() = 0; + virtual uint32_t get_use_count() = 0; }; } // namespace vsomeip diff --git a/implementation/endpoints/include/endpoint_definition.hpp b/implementation/endpoints/include/endpoint_definition.hpp index 30f53fd..d7fb3a2 100644 --- a/implementation/endpoints/include/endpoint_definition.hpp +++ b/implementation/endpoints/include/endpoint_definition.hpp @@ -6,6 +6,9 @@ #ifndef VSOMEIP_ENDPOINT_DEFINITION_HPP #define VSOMEIP_ENDPOINT_DEFINITION_HPP +#include +#include + #include #include @@ -14,8 +17,7 @@ namespace vsomeip { class endpoint_definition { public: - VSOMEIP_EXPORT endpoint_definition(); - VSOMEIP_EXPORT endpoint_definition( + VSOMEIP_EXPORT static std::shared_ptr get( const boost::asio::ip::address &_address, uint16_t _port, bool _is_reliable); @@ -31,11 +33,19 @@ public: VSOMEIP_EXPORT bool is_reliable() const; VSOMEIP_EXPORT void set_reliable(bool _is_reliable); + VSOMEIP_EXPORT endpoint_definition( + const boost::asio::ip::address &_address, + uint16_t _port, bool _is_reliable); private: boost::asio::ip::address address_; uint16_t port_; uint16_t remote_port_; bool is_reliable_; + + static std::map > > > definitions_; }; } // namespace vsomeip diff --git a/implementation/endpoints/include/endpoint_host.hpp b/implementation/endpoints/include/endpoint_host.hpp index af0c9b1..d526ab4 100644 --- a/implementation/endpoints/include/endpoint_host.hpp +++ b/implementation/endpoints/include/endpoint_host.hpp @@ -22,6 +22,8 @@ public: virtual void on_disconnect(std::shared_ptr _endpoint) = 0; virtual void on_message(const byte_t *_data, length_t _length, endpoint *_receiver) = 0; + virtual void on_error(const byte_t *_data, length_t _length, + endpoint *_receiver) = 0; }; } // namespace vsomeip diff --git a/implementation/endpoints/include/endpoint_impl.hpp b/implementation/endpoints/include/endpoint_impl.hpp index 5c6fe39..5d8350a 100644 --- a/implementation/endpoints/include/endpoint_impl.hpp +++ b/implementation/endpoints/include/endpoint_impl.hpp @@ -23,7 +23,8 @@ template class endpoint_impl: public endpoint { public: endpoint_impl(std::shared_ptr _adapter, - boost::asio::io_service &_io); + boost::asio::io_service &_io, + std::uint32_t _max_message_size); virtual ~endpoint_impl(); void enable_magic_cookies(); @@ -45,6 +46,10 @@ public: unsigned short get_remote_port() const; bool is_reliable() const; + void increment_use_count(); + void decrement_use_count(); + uint32_t get_use_count(); + public: // required virtual bool is_client() const = 0; @@ -53,7 +58,7 @@ public: protected: virtual bool is_magic_cookie() const; - uint32_t find_magic_cookie(message_buffer_t &_buffer); + uint32_t find_magic_cookie(byte_t *_buffer, size_t _size); protected: // Reference to service context @@ -62,10 +67,15 @@ protected: // Reference to host std::weak_ptr host_; - bool is_supporting_magic_cookies_;bool has_enabled_magic_cookies_; + bool is_supporting_magic_cookies_; + bool has_enabled_magic_cookies_; // Filter configuration std::map opened_; + + std::uint32_t max_message_size_; + + uint32_t use_count_; }; } // namespace vsomeip diff --git a/implementation/endpoints/include/local_client_endpoint_impl.hpp b/implementation/endpoints/include/local_client_endpoint_impl.hpp index 9891ae4..97f01ce 100644 --- a/implementation/endpoints/include/local_client_endpoint_impl.hpp +++ b/implementation/endpoints/include/local_client_endpoint_impl.hpp @@ -1,59 +1,65 @@ -// Copyright (C) 2014-2015 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_LOCAL_CLIENT_ENDPOINT_IMPL_HPP -#define VSOMEIP_LOCAL_CLIENT_ENDPOINT_IMPL_HPP - -#include -#include - -#ifdef WIN32 -#include -#endif - -#include - -#include "client_endpoint_impl.hpp" - -namespace vsomeip { - -#ifdef WIN32 -typedef client_endpoint_impl local_client_endpoint_base_impl; -#else -typedef client_endpoint_impl local_client_endpoint_base_impl; -#endif - -class local_client_endpoint_impl: public local_client_endpoint_base_impl { -public: - local_client_endpoint_impl(std::shared_ptr _host, - endpoint_type _local, - boost::asio::io_service &_io); - - virtual ~local_client_endpoint_impl(); - - void start(); - - void send_queued(message_buffer_ptr_t _data); - - bool is_local() const; - -private: - void send_magic_cookie(); - - void connect(); - void receive(); - - void send_tag_cbk(boost::system::error_code const &_error, - std::size_t _bytes); - void receive_cbk(packet_buffer_ptr_t _buffer, - boost::system::error_code const &_error, - std::size_t _bytes); -}; - -} // namespace vsomeip - -#endif // VSOMEIP_LOCAL_CLIENT_ENDPOINT_IMPL_HPP +// Copyright (C) 2014-2015 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_LOCAL_CLIENT_ENDPOINT_IMPL_HPP +#define VSOMEIP_LOCAL_CLIENT_ENDPOINT_IMPL_HPP + +#include +#include + +#ifdef WIN32 +#include +#endif + +#include + +#include "client_endpoint_impl.hpp" + +namespace vsomeip { + +#ifdef WIN32 +typedef client_endpoint_impl local_client_endpoint_base_impl; +#else +typedef client_endpoint_impl local_client_endpoint_base_impl; +#endif + +class local_client_endpoint_impl: public local_client_endpoint_base_impl { +public: + local_client_endpoint_impl(std::shared_ptr _host, + endpoint_type _local, + boost::asio::io_service &_io, + std::uint32_t _max_message_size); + + virtual ~local_client_endpoint_impl(); + + void start(); + + bool is_local() const; + +private: + void send_queued(); + + void send_start_tag(); + void send_queued_data(); + void send_end_tag(); + + void send_magic_cookie(); + + void connect(); + void receive(); + + void send_start_tag_cbk(boost::system::error_code const &_error, + std::size_t _bytes); + void send_queued_data_cbk(boost::system::error_code const &_error, + std::size_t _bytes); + void receive_cbk(boost::system::error_code const &_error, + std::size_t _bytes); +}; + +} // namespace vsomeip + +#endif // VSOMEIP_LOCAL_CLIENT_ENDPOINT_IMPL_HPP diff --git a/implementation/endpoints/include/local_server_endpoint_impl.hpp b/implementation/endpoints/include/local_server_endpoint_impl.hpp index a47858a..626b30e 100644 --- a/implementation/endpoints/include/local_server_endpoint_impl.hpp +++ b/implementation/endpoints/include/local_server_endpoint_impl.hpp @@ -1,104 +1,107 @@ -// Copyright (C) 2014-2015 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_LOCAL_SERVER_ENDPOINT_IMPL_HPP -#define VSOMEIP_LOCAL_SERVER_ENDPOINT_IMPL_HPP - -#include - -#include -#include -#include - -#ifdef WIN32 -#include -#endif - -#include - -#include "buffer.hpp" -#include "server_endpoint_impl.hpp" - -namespace vsomeip { - -#ifdef WIN32 -typedef server_endpoint_impl local_server_endpoint_base_impl; -#else -typedef server_endpoint_impl local_server_endpoint_base_impl; -#endif - -class local_server_endpoint_impl: public local_server_endpoint_base_impl { - -public: - local_server_endpoint_impl(std::shared_ptr _host, - endpoint_type _local, - boost::asio::io_service &_io); - virtual ~local_server_endpoint_impl(); - - void start(); - void stop(); - - void restart(); - void receive(); - - bool send_to(const std::shared_ptr, - const byte_t *_data, uint32_t _size, bool _flush); - void send_queued(endpoint_type _target, message_buffer_ptr_t _data); - - endpoint_type get_remote() const; - bool get_multicast(service_t, event_t, endpoint_type &) const; - - bool is_local() const; - -private: - class connection: public boost::enable_shared_from_this { - - public: - typedef boost::shared_ptr ptr; - - static ptr create(local_server_endpoint_impl *_server); - socket_type & get_socket(); - - void start(); - - void send_queued(message_buffer_ptr_t _data); - - private: - connection(local_server_endpoint_impl *_owner); - - void send_magic_cookie(); - - local_server_endpoint_impl::socket_type socket_; - local_server_endpoint_impl *server_; - - // the current message - message_buffer_t message_; - - private: - void receive_cbk(packet_buffer_ptr_t _buffer, - boost::system::error_code const &_error, - std::size_t _bytes); - }; - -#ifdef WIN32 - boost::asio::ip::tcp::acceptor acceptor_; -#else - boost::asio::local::stream_protocol::acceptor acceptor_; -#endif - - std::map connections_; - connection *current_; - -private: - void remove_connection(connection *_connection); - void accept_cbk(connection::ptr _connection, - boost::system::error_code const &_error); -}; - -} // namespace vsomeip - -#endif // VSOMEIP_LOCAL_SERVER_ENDPOINT_IMPL_HPP +// Copyright (C) 2014-2015 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_LOCAL_SERVER_ENDPOINT_IMPL_HPP +#define VSOMEIP_LOCAL_SERVER_ENDPOINT_IMPL_HPP + +#include + +#include +#include +#include + +#ifdef WIN32 +#include +#endif + +#include + +#include "buffer.hpp" +#include "server_endpoint_impl.hpp" + +namespace vsomeip { + +#ifdef WIN32 +typedef server_endpoint_impl local_server_endpoint_base_impl; +#else +typedef server_endpoint_impl local_server_endpoint_base_impl; +#endif + +class local_server_endpoint_impl: public local_server_endpoint_base_impl { + +public: + local_server_endpoint_impl(std::shared_ptr _host, + endpoint_type _local, + boost::asio::io_service &_io, + std::uint32_t _max_message_size); + virtual ~local_server_endpoint_impl(); + + void start(); + void stop(); + + void restart(); + void receive(); + + bool send_to(const std::shared_ptr, + const byte_t *_data, uint32_t _size, bool _flush); + void send_queued(queue_iterator_type _queue_iterator); + + endpoint_type get_remote() const; + bool get_multicast(service_t, event_t, endpoint_type &) const; + + bool is_local() const; + +private: + class connection: public boost::enable_shared_from_this { + + public: + typedef boost::shared_ptr ptr; + + static ptr create(local_server_endpoint_impl *_server, + std::uint32_t _max_message_size); + socket_type & get_socket(); + + void start(); + + void send_queued(queue_iterator_type _queue_iterator); + + private: + connection(local_server_endpoint_impl *_owner, std::uint32_t _max_message_size); + + void send_magic_cookie(); + + local_server_endpoint_impl::socket_type socket_; + local_server_endpoint_impl *server_; + + uint32_t max_message_size_; + + receive_buffer_t recv_buffer_; + size_t recv_buffer_size_; + + private: + void receive_cbk(boost::system::error_code const &_error, + std::size_t _bytes); + }; + +#ifdef WIN32 + boost::asio::ip::tcp::acceptor acceptor_; +#else + boost::asio::local::stream_protocol::acceptor acceptor_; +#endif + + std::map connections_; + connection *current_; + +private: + void remove_connection(connection *_connection); + void accept_cbk(connection::ptr _connection, + boost::system::error_code const &_error); +}; + +} // namespace vsomeip + +#endif // VSOMEIP_LOCAL_SERVER_ENDPOINT_IMPL_HPP diff --git a/implementation/endpoints/include/server_endpoint_impl.hpp b/implementation/endpoints/include/server_endpoint_impl.hpp index eca9c5a..c51cb49 100644 --- a/implementation/endpoints/include/server_endpoint_impl.hpp +++ b/implementation/endpoints/include/server_endpoint_impl.hpp @@ -6,6 +6,7 @@ #ifndef VSOMEIP_SERVER_IMPL_HPP #define VSOMEIP_SERVER_IMPL_HPP +#include #include #include #include @@ -28,9 +29,12 @@ public: typedef typename Protocol::socket socket_type; typedef typename Protocol::endpoint endpoint_type; typedef boost::array buffer_type; + typedef typename std::map > queue_type; + typedef typename queue_type::iterator queue_iterator_type; server_endpoint_impl(std::shared_ptr _host, - endpoint_type _local, boost::asio::io_service &_io); + endpoint_type _local, boost::asio::io_service &_io, + std::uint32_t _max_message_size); bool is_client() const; bool is_connected() const; @@ -40,7 +44,7 @@ public: public: void connect_cbk(boost::system::error_code const &_error); - void send_cbk(message_buffer_ptr_t _buffer, + void send_cbk(queue_iterator_type _queue_iterator, boost::system::error_code const &_error, std::size_t _bytes); void flush_cbk(endpoint_type _target, const boost::system::error_code &_error); @@ -48,8 +52,7 @@ public: public: virtual bool send_intern(endpoint_type _target, const byte_t *_data, uint32_t _port, bool _flush); - virtual void send_queued(endpoint_type _target, - message_buffer_ptr_t _buffer) = 0; + virtual void send_queued(queue_iterator_type _queue_iterator) = 0; virtual endpoint_type get_remote() const = 0; virtual bool get_multicast(service_t _service, event_t _event, @@ -57,6 +60,8 @@ public: protected: std::map packetizer_; + queue_type queues_; + std::map > clients_; boost::asio::system_timer flush_timer_; diff --git a/implementation/endpoints/include/tcp_client_endpoint_impl.hpp b/implementation/endpoints/include/tcp_client_endpoint_impl.hpp index 3bb7f26..e5bf987 100644 --- a/implementation/endpoints/include/tcp_client_endpoint_impl.hpp +++ b/implementation/endpoints/include/tcp_client_endpoint_impl.hpp @@ -20,11 +20,11 @@ class tcp_client_endpoint_impl: public tcp_client_endpoint_base_impl { public: tcp_client_endpoint_impl(std::shared_ptr _host, endpoint_type _local, - boost::asio::io_service &_io); + boost::asio::io_service &_io, + std::uint32_t _max_message_size); virtual ~tcp_client_endpoint_impl(); void start(); - void send_queued(message_buffer_ptr_t _buffer); bool get_remote_address(boost::asio::ip::address &_address) const; unsigned short get_local_port() const; @@ -33,15 +33,18 @@ public: bool is_local() const; private: - bool is_magic_cookie() const; + void send_queued(); + bool is_magic_cookie(size_t _offset) const; void send_magic_cookie(message_buffer_ptr_t &_buffer); - void receive_cbk(packet_buffer_ptr_t _buffer, - boost::system::error_code const &_error, + void receive_cbk(boost::system::error_code const &_error, std::size_t _bytes); void connect(); void receive(); + + receive_buffer_t recv_buffer_; + size_t recv_buffer_size_; }; } // namespace vsomeip diff --git a/implementation/endpoints/include/tcp_server_endpoint_impl.hpp b/implementation/endpoints/include/tcp_server_endpoint_impl.hpp index 10d52e6..57f0566 100644 --- a/implementation/endpoints/include/tcp_server_endpoint_impl.hpp +++ b/implementation/endpoints/include/tcp_server_endpoint_impl.hpp @@ -24,7 +24,8 @@ class tcp_server_endpoint_impl: public tcp_server_endpoint_base_impl { public: tcp_server_endpoint_impl(std::shared_ptr _host, endpoint_type _local, - boost::asio::io_service &_io); + boost::asio::io_service &_io, + std::uint32_t _max_message_size); virtual ~tcp_server_endpoint_impl(); void start(); @@ -32,7 +33,7 @@ public: bool send_to(const std::shared_ptr _target, const byte_t *_data, uint32_t _size, bool _flush); - void send_queued(endpoint_type _target, message_buffer_ptr_t _buffer); + void send_queued(queue_iterator_type _queue_iterator); endpoint_type get_remote() const; bool get_multicast(service_t, event_t, endpoint_type &) const; @@ -54,30 +55,35 @@ private: public: typedef boost::shared_ptr ptr; - static ptr create(tcp_server_endpoint_impl *_server); + static ptr create(tcp_server_endpoint_impl *_server, + std::uint32_t _max_message_size); socket_type & get_socket(); void start(); void stop(); + void receive(); client_t get_client(endpoint_type _endpoint_type); - void send_queued(message_buffer_ptr_t _buffer); + void send_queued(queue_iterator_type _queue_iterator); private: - connection(tcp_server_endpoint_impl *_owner); + connection(tcp_server_endpoint_impl *_owner, std::uint32_t _max_message_size); void send_magic_cookie(message_buffer_ptr_t &_buffer); tcp_server_endpoint_impl::socket_type socket_; tcp_server_endpoint_impl *server_; - message_buffer_t message_; + uint32_t max_message_size_; + + receive_buffer_t recv_buffer_; + size_t recv_buffer_size_; private: - bool is_magic_cookie() const; - void receive_cbk(packet_buffer_ptr_t _buffer, - boost::system::error_code const &_error, + bool is_magic_cookie(size_t _offset) const; + void receive_cbk(boost::system::error_code const &_error, std::size_t _bytes); + std::mutex stop_mutex_; }; boost::asio::ip::tcp::acceptor acceptor_; diff --git a/implementation/endpoints/include/udp_client_endpoint_impl.hpp b/implementation/endpoints/include/udp_client_endpoint_impl.hpp index 0b20600..4a51db6 100644 --- a/implementation/endpoints/include/udp_client_endpoint_impl.hpp +++ b/implementation/endpoints/include/udp_client_endpoint_impl.hpp @@ -31,13 +31,8 @@ public: virtual ~udp_client_endpoint_impl(); void start(); - void send_queued(message_buffer_ptr_t _buffer); - void join(const std::string &_address); - void leave(const std::string &_address); - - void receive_cbk(packet_buffer_ptr_t _buffer, - boost::system::error_code const &_error, + void receive_cbk(boost::system::error_code const &_error, std::size_t _bytes); bool get_remote_address(boost::asio::ip::address &_address) const; @@ -46,8 +41,12 @@ public: bool is_local() const; private: + void send_queued(); void connect(); void receive(); + + receive_buffer_t recv_buffer_; + size_t recv_buffer_size_; }; } // namespace vsomeip diff --git a/implementation/endpoints/include/udp_server_endpoint_impl.hpp b/implementation/endpoints/include/udp_server_endpoint_impl.hpp index 4c7beaf..d7e2b62 100644 --- a/implementation/endpoints/include/udp_server_endpoint_impl.hpp +++ b/implementation/endpoints/include/udp_server_endpoint_impl.hpp @@ -33,7 +33,7 @@ public: bool send_to(const std::shared_ptr _target, const byte_t *_data, uint32_t _size, bool _flush); - void send_queued(endpoint_type _target, message_buffer_ptr_t _buffer); + void send_queued(queue_iterator_type _queue_iterator); endpoint_type get_remote() const; bool get_multicast(service_t _service, event_t _event, @@ -51,8 +51,7 @@ public: client_t get_client(std::shared_ptr _endpoint); public: - void receive_cbk(packet_buffer_ptr_t _buffer, - boost::system::error_code const &_error, + void receive_cbk(boost::system::error_code const &_error, std::size_t _size); private: @@ -62,7 +61,10 @@ private: socket_type socket_; endpoint_type remote_; std::map > multicasts_; - message_buffer_t message_; + + receive_buffer_t recv_buffer_; + size_t recv_buffer_size_; + std::mutex stop_mutex_; }; } // namespace vsomeip diff --git a/implementation/endpoints/include/virtual_server_endpoint_impl.hpp b/implementation/endpoints/include/virtual_server_endpoint_impl.hpp new file mode 100644 index 0000000..12484f5 --- /dev/null +++ b/implementation/endpoints/include/virtual_server_endpoint_impl.hpp @@ -0,0 +1,62 @@ +// Copyright (C) 2014-2015 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_VIRTUAL_SERVER_ENDPOINT_IMPL_HPP +#define VSOMEIP_VIRTUAL_SERVER_ENDPOINT_IMPL_HPP + +#include + +#include "../include/endpoint.hpp" + +namespace vsomeip { + +class virtual_server_endpoint_impl : public endpoint { +public: + virtual_server_endpoint_impl( + const std::string &_address, + uint16_t _port, + bool _reliable); + + virtual ~virtual_server_endpoint_impl(); + + void start(); + void stop(); + + bool is_connected() const; + + bool send(const byte_t *_data, uint32_t _size, bool _flush); + bool send_to(const std::shared_ptr _target, + const byte_t *_data, uint32_t _size, bool _flush); + void enable_magic_cookies(); + void receive(); + + void join(const std::string &_address); + void leave(const std::string &_address); + + void add_multicast(service_t _service, event_t _event, + const std::string &_address, uint16_t _port); + void remove_multicast(service_t _service, event_t _event); + + bool get_remote_address(boost::asio::ip::address &_address) const; + unsigned short get_local_port() const; + unsigned short get_remote_port() const; + bool is_reliable() const; + bool is_local() const; + + void increment_use_count(); + void decrement_use_count(); + uint32_t get_use_count(); + +private: + std::string address_; + uint16_t port_; + bool reliable_; + + uint32_t use_count_; +}; + +} // namespace vsomeip + +#endif // VSOMEIP_VIRTUAL_SERVER_ENDPOINT_IMPL_HPP diff --git a/implementation/endpoints/src/client_endpoint_impl.cpp b/implementation/endpoints/src/client_endpoint_impl.cpp index 5c2e399..6ed812a 100644 --- a/implementation/endpoints/src/client_endpoint_impl.cpp +++ b/implementation/endpoints/src/client_endpoint_impl.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include @@ -13,11 +14,11 @@ #include #include -#include #include "../include/client_endpoint_impl.hpp" #include "../include/endpoint_host.hpp" #include "../../configuration/include/internal.hpp" +#include "../../logging/include/logger.hpp" #include "../../utility/include/utility.hpp" namespace vsomeip { @@ -25,12 +26,13 @@ namespace vsomeip { template client_endpoint_impl::client_endpoint_impl( std::shared_ptr _host, endpoint_type _remote, - boost::asio::io_service &_io) - : endpoint_impl(_host, _io), socket_(_io), - connect_timer_(_io), flush_timer_(_io), remote_(_remote), - packetizer_(std::make_shared()), + boost::asio::io_service &_io, std::uint32_t _max_message_size) + : endpoint_impl(_host, _io, _max_message_size), + socket_(_io), remote_(_remote), + flush_timer_(_io), connect_timer_(_io), connect_timeout_(VSOMEIP_DEFAULT_CONNECT_TIMEOUT), // TODO: use config variable - is_connected_(false) { + is_connected_(false), + packetizer_(std::make_shared()) { } template @@ -63,6 +65,11 @@ template bool client_endpoint_impl::send_to( const std::shared_ptr _target, const byte_t *_data, uint32_t _size, bool _flush) { + (void)_target; + (void)_data; + (void)_size; + (void)_flush; + VSOMEIP_ERROR<< "Clients endpoints must not be used to " << "send to explicitely specified targets"; return false; @@ -72,6 +79,7 @@ template bool client_endpoint_impl::send(const uint8_t *_data, uint32_t _size, bool _flush) { std::lock_guard its_lock(mutex_); + bool is_flushing(false); #if 0 std::stringstream msg; msg << "cei::send: "; @@ -80,8 +88,10 @@ bool client_endpoint_impl::send(const uint8_t *_data, << (int)_data[i] << " "; VSOMEIP_DEBUG << msg.str(); #endif - if (packetizer_->size() + _size > MaxBufferSize) { - send_queued(packetizer_); + + if (packetizer_->size() + _size > endpoint_impl::max_message_size_) { + queue_.push_back(packetizer_); + is_flushing = true; packetizer_ = std::make_shared(); } @@ -89,15 +99,22 @@ bool client_endpoint_impl::send(const uint8_t *_data, if (_flush) { flush_timer_.cancel(); - send_queued(packetizer_); + queue_.push_back(packetizer_); + is_flushing = true; packetizer_ = std::make_shared(); } else { 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::flush_cbk, - this->shared_from_this(), std::placeholders::_1)); + std::bind( + &client_endpoint_impl< + Protocol, MaxBufferSize>::flush_cbk, + this->shared_from_this(), + std::placeholders::_1)); + } + + if (is_flushing && queue_.size() == 1) { // no writing in progress + send_queued(); } return (true); @@ -108,8 +125,12 @@ bool client_endpoint_impl::flush() { bool is_successful(true); if (!packetizer_->empty()) { - send_queued(packetizer_); + std::lock_guard its_lock(mutex_); + queue_.push_back(packetizer_); packetizer_ = std::make_shared(); + if (queue_.size() == 1) { // no writing in progress + send_queued(); + } } else { is_successful = false; } @@ -163,17 +184,15 @@ void client_endpoint_impl::wait_connect_cbk( template void client_endpoint_impl::send_cbk( - message_buffer_ptr_t _buffer, boost::system::error_code const &_error, - std::size_t _bytes) { -#if 0 - std::stringstream msg; - msg << "cei<" << this << ">::scb (" << _error.message() << "): "; - for (std::size_t i = 0; i < _data->size(); ++i) - msg << std::hex << std::setw(2) << std::setfill('0') - << (int)(*_buffer)[i] << " "; - VSOMEIP_DEBUG << msg.str(); -#endif - if (_error == boost::asio::error::broken_pipe) { + boost::system::error_code const &_error, std::size_t _bytes) { + (void)_bytes; + if (!_error) { + std::lock_guard its_lock(mutex_); + queue_.pop_front(); + if (queue_.size() > 0) { + send_queued(); + } + } else if (_error == boost::asio::error::broken_pipe) { is_connected_ = false; socket_.close(); connect(); diff --git a/implementation/endpoints/src/endpoint_definition.cpp b/implementation/endpoints/src/endpoint_definition.cpp index 9a4caea..d748aa3 100644 --- a/implementation/endpoints/src/endpoint_definition.cpp +++ b/implementation/endpoints/src/endpoint_definition.cpp @@ -9,14 +9,41 @@ namespace vsomeip { -endpoint_definition::endpoint_definition() - : port_(ILLEGAL_PORT) { +std::map > > > +endpoint_definition::definitions_; + +std::shared_ptr +endpoint_definition::get(const boost::asio::ip::address &_address, + uint16_t _port, bool _is_reliable) { + + std::shared_ptr its_result; + + auto find_address = definitions_.find(_address); + if (find_address != definitions_.end()) { + auto find_port = find_address->second.find(_port); + if (find_port != find_address->second.end()) { + auto found_reliable = find_port->second.find(_is_reliable); + if (found_reliable != find_port->second.end()) { + its_result = found_reliable->second; + } + } + } + + if (!its_result) { + its_result = std::make_shared( + _address, _port, _is_reliable); + definitions_[_address][_port][_is_reliable] = its_result; + } + return its_result; } endpoint_definition::endpoint_definition( const boost::asio::ip::address &_address, uint16_t _port, bool _is_reliable) - : address_(_address), port_(_port), is_reliable_(_is_reliable), remote_port_(_port) { + : address_(_address), port_(_port), remote_port_(_port), + is_reliable_(_is_reliable) { } const boost::asio::ip::address & endpoint_definition::get_address() const { diff --git a/implementation/endpoints/src/endpoint_impl.cpp b/implementation/endpoints/src/endpoint_impl.cpp index e7ffffa..5b0e088 100644 --- a/implementation/endpoints/src/endpoint_impl.cpp +++ b/implementation/endpoints/src/endpoint_impl.cpp @@ -5,20 +5,22 @@ #include #include -#include #include "../include/endpoint_host.hpp" #include "../include/endpoint_impl.hpp" +#include "../../logging/include/logger.hpp" namespace vsomeip { template endpoint_impl::endpoint_impl( - std::shared_ptr _host, boost::asio::io_service &_io) - : host_(_host), - service_(_io), + std::shared_ptr _host, boost::asio::io_service &_io, + std::uint32_t _max_message_size) + : service_(_io), + host_(_host), is_supporting_magic_cookies_(false), - has_enabled_magic_cookies_(false) { + has_enabled_magic_cookies_(false), + max_message_size_(_max_message_size) { } template @@ -37,7 +39,7 @@ bool endpoint_impl::is_magic_cookie() const { template uint32_t endpoint_impl::find_magic_cookie( - message_buffer_t &_buffer) { + byte_t *_buffer, size_t _size) { bool is_found(false); uint32_t its_offset = 0xFFFFFFFF; if (has_enabled_magic_cookies_) { @@ -57,7 +59,7 @@ uint32_t endpoint_impl::find_magic_cookie( do { its_offset++; // --> first loop has "its_offset = 0" - if (_buffer.size() > its_offset + 16) { + if (_size > its_offset + 16) { is_found = (_buffer[its_offset] == 0xFF && _buffer[its_offset + 1] == 0xFF && _buffer[its_offset + 2] == its_cookie_identifier @@ -104,6 +106,7 @@ void endpoint_impl::remove_multicast(service_t, event_t) { template bool endpoint_impl::get_remote_address( boost::asio::ip::address &_address) const { + (void)_address; return false; } @@ -122,6 +125,22 @@ bool endpoint_impl::is_reliable() const { return false; } +template +void endpoint_impl::increment_use_count() { + use_count_++; +} + +template +void endpoint_impl::decrement_use_count() { + if (use_count_ > 0) + use_count_--; +} + +template +uint32_t endpoint_impl::get_use_count() { + return use_count_; +} + // Instantiate template template class endpoint_impl< VSOMEIP_MAX_LOCAL_MESSAGE_SIZE> ; template class endpoint_impl< VSOMEIP_MAX_TCP_MESSAGE_SIZE> ; diff --git a/implementation/endpoints/src/local_client_endpoint_impl.cpp b/implementation/endpoints/src/local_client_endpoint_impl.cpp index b465baa..323c414 100644 --- a/implementation/endpoints/src/local_client_endpoint_impl.cpp +++ b/implementation/endpoints/src/local_client_endpoint_impl.cpp @@ -9,17 +9,17 @@ #include #include -#include #include "../include/endpoint_host.hpp" #include "../include/local_client_endpoint_impl.hpp" +#include "../../logging/include/logger.hpp" namespace vsomeip { local_client_endpoint_impl::local_client_endpoint_impl( std::shared_ptr< endpoint_host > _host, endpoint_type _remote, - boost::asio::io_service &_io) - : local_client_endpoint_base_impl(_host, _remote, _io) { + boost::asio::io_service &_io, std::uint32_t _max_message_size) + : local_client_endpoint_base_impl(_host, _remote, _io, _max_message_size) { is_supporting_magic_cookies_ = false; } @@ -49,34 +49,22 @@ void local_client_endpoint_impl::connect() { } void local_client_endpoint_impl::receive() { - packet_buffer_ptr_t its_buffer - = std::make_shared< packet_buffer_t >(); + receive_buffer_t its_buffer(VSOMEIP_MAX_LOCAL_MESSAGE_SIZE , 0); socket_.async_receive( - boost::asio::buffer(*its_buffer), + boost::asio::buffer(its_buffer), std::bind( &local_client_endpoint_impl::receive_cbk, std::dynamic_pointer_cast< local_client_endpoint_impl >(shared_from_this()), - its_buffer, std::placeholders::_1, std::placeholders::_2 ) ); } -void local_client_endpoint_impl::send_queued(message_buffer_ptr_t _buffer) { -#if 0 - std::stringstream msg; - msg << "lce<" << this << ">::sq: "; - for (std::size_t i = 0; i < _buffer->size(); i++) - msg << std::setw(2) << std::setfill('0') << std::hex - << (int)(*_buffer)[i] << " "; - VSOMEIP_DEBUG << msg.str(); -#endif - +void local_client_endpoint_impl::send_queued() { static byte_t its_start_tag[] = { 0x67, 0x37, 0x6D, 0x07 }; - static byte_t its_end_tag[] = { 0x07, 0x6D, 0x37, 0x67 }; boost::asio::async_write( socket_, @@ -85,7 +73,7 @@ void local_client_endpoint_impl::send_queued(message_buffer_ptr_t _buffer) { sizeof(its_start_tag) ), std::bind( - &local_client_endpoint_impl::send_tag_cbk, + &local_client_endpoint_impl::send_start_tag_cbk, std::dynamic_pointer_cast< local_client_endpoint_impl >(shared_from_this()), @@ -93,18 +81,36 @@ void local_client_endpoint_impl::send_queued(message_buffer_ptr_t _buffer) { std::placeholders::_2 ) ); +} + +void local_client_endpoint_impl::send_queued_data() { + std::lock_guard its_lock(mutex_); + message_buffer_ptr_t its_buffer = queue_.front(); + #if 0 + std::stringstream msg; + msg << "lce<" << this << ">::sq: "; + for (std::size_t i = 0; i < its_buffer->size(); i++) + msg << std::setw(2) << std::setfill('0') << std::hex + << (int)(*its_buffer)[i] << " "; + VSOMEIP_DEBUG << msg.str(); + #endif boost::asio::async_write( socket_, - boost::asio::buffer(*_buffer), + boost::asio::buffer(*its_buffer), std::bind( - &client_endpoint_impl::send_cbk, - this->shared_from_this(), - _buffer, + &local_client_endpoint_impl::send_queued_data_cbk, + std::dynamic_pointer_cast< + local_client_endpoint_impl + >(shared_from_this()), std::placeholders::_1, std::placeholders::_2 ) ); +} + +void local_client_endpoint_impl::send_end_tag() { + static byte_t its_end_tag[] = { 0x07, 0x6D, 0x37, 0x67 }; boost::asio::async_write( socket_, @@ -113,10 +119,8 @@ void local_client_endpoint_impl::send_queued(message_buffer_ptr_t _buffer) { sizeof(its_end_tag) ), std::bind( - &local_client_endpoint_impl::send_tag_cbk, - std::dynamic_pointer_cast< - local_client_endpoint_impl - >(shared_from_this()), + &client_endpoint_impl::send_cbk, + shared_from_this(), std::placeholders::_1, std::placeholders::_2 ) @@ -126,13 +130,28 @@ void local_client_endpoint_impl::send_queued(message_buffer_ptr_t _buffer) { void local_client_endpoint_impl::send_magic_cookie() { } -void local_client_endpoint_impl::send_tag_cbk( +void local_client_endpoint_impl::send_start_tag_cbk( boost::system::error_code const &_error, std::size_t _bytes) { + (void)_bytes; + if (_error) + send_cbk(_error, 0); + + send_queued_data(); +} + +void local_client_endpoint_impl::send_queued_data_cbk( + boost::system::error_code const &_error, std::size_t _bytes) { + (void)_bytes; + if (_error) + send_cbk(_error, 0); + + send_end_tag(); } void local_client_endpoint_impl::receive_cbk( - packet_buffer_ptr_t _buffer, boost::system::error_code const &_error, std::size_t _bytes) { + (void)_error; + (void)_bytes; VSOMEIP_ERROR << "Local endpoint received message (" << _error.message() << ")"; } diff --git a/implementation/endpoints/src/local_server_endpoint_impl.cpp b/implementation/endpoints/src/local_server_endpoint_impl.cpp index 3a237c6..b392cec 100644 --- a/implementation/endpoints/src/local_server_endpoint_impl.cpp +++ b/implementation/endpoints/src/local_server_endpoint_impl.cpp @@ -1,252 +1,276 @@ -// Copyright (C) 2014-2015 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 -#include -#include - -#include - -#include - -#include "../include/endpoint_host.hpp" -#include "../include/local_server_endpoint_impl.hpp" - -namespace vsomeip { - -local_server_endpoint_impl::local_server_endpoint_impl( - std::shared_ptr< endpoint_host > _host, - endpoint_type _local, boost::asio::io_service &_io) - : local_server_endpoint_base_impl(_host, _local, _io), - acceptor_(_io, _local) { - is_supporting_magic_cookies_ = false; -} - -local_server_endpoint_impl::~local_server_endpoint_impl() { -} - -bool local_server_endpoint_impl::is_local() const { - return true; -} - -void local_server_endpoint_impl::start() { - connection::ptr new_connection = connection::create(this); - - acceptor_.async_accept( - new_connection->get_socket(), - std::bind( - &local_server_endpoint_impl::accept_cbk, - std::dynamic_pointer_cast< - local_server_endpoint_impl - >(shared_from_this()), - new_connection, - std::placeholders::_1 - ) - ); -} - -void local_server_endpoint_impl::stop() { -} - -bool local_server_endpoint_impl::send_to( - const std::shared_ptr _target, - const byte_t *_data, uint32_t _size, bool _flush) { - return false; -} - -void local_server_endpoint_impl::send_queued( - endpoint_type _target, message_buffer_ptr_t _buffer) { - auto connection_iterator = connections_.find(_target); - if (connection_iterator != connections_.end()) - connection_iterator->second->send_queued(_buffer); -} - -void local_server_endpoint_impl::receive() { - // intentionally left empty -} - -void local_server_endpoint_impl::restart() { - current_->start(); -} - -local_server_endpoint_impl::endpoint_type -local_server_endpoint_impl::get_remote() const { - return current_->get_socket().remote_endpoint(); -} - -bool local_server_endpoint_impl::get_multicast( - service_t, event_t, - local_server_endpoint_impl::endpoint_type &) const { - return false; -} - -void local_server_endpoint_impl::remove_connection( - local_server_endpoint_impl::connection *_connection) { - std::map< endpoint_type, connection::ptr >::iterator i - = connections_.end(); - for (i = connections_.begin(); i != connections_.end(); i++) { - if (i->second.get() == _connection) - break; - } - - if (i != connections_.end()) { - connections_.erase(i); - } -} - -void local_server_endpoint_impl::accept_cbk( - connection::ptr _connection, boost::system::error_code const &_error) { - - if (!_error) { - socket_type &new_connection_socket = _connection->get_socket(); - endpoint_type remote = new_connection_socket.remote_endpoint(); - - connections_[remote] = _connection; - _connection->start(); - } - - start(); -} - -/////////////////////////////////////////////////////////////////////////////// -// class local_service_impl::connection -/////////////////////////////////////////////////////////////////////////////// -local_server_endpoint_impl::connection::connection( - local_server_endpoint_impl *_server) - : socket_(_server->service_), server_(_server) { -} - -local_server_endpoint_impl::connection::ptr -local_server_endpoint_impl::connection::create( - local_server_endpoint_impl *_server) { - return ptr(new connection(_server)); -} - -local_server_endpoint_impl::socket_type & -local_server_endpoint_impl::connection::get_socket() { - return socket_; -} - -void local_server_endpoint_impl::connection::start() { - packet_buffer_ptr_t its_buffer - = std::make_shared< packet_buffer_t >(); - socket_.async_receive( - boost::asio::buffer(*its_buffer), - std::bind( - &local_server_endpoint_impl::connection::receive_cbk, - shared_from_this(), - its_buffer, - std::placeholders::_1, - std::placeholders::_2 - ) - ); -} - -void local_server_endpoint_impl::connection::send_queued( - message_buffer_ptr_t _buffer) { -#if 0 - std::stringstream msg; - msg << "lse::sq: "; - for (std::size_t i = 0; i < _buffer->size(); i++) - msg << std::setw(2) << std::setfill('0') << std::hex - << (int)(*_buffer)[i] << " "; - VSOMEIP_DEBUG << msg.str(); -#endif - boost::asio::async_write( - socket_, - boost::asio::buffer(*_buffer), - std::bind( - &local_server_endpoint_base_impl::send_cbk, - server_->shared_from_this(), - _buffer, - std::placeholders::_1, - std::placeholders::_2 - ) - ); -} - -void local_server_endpoint_impl::connection::send_magic_cookie() { -} - -void local_server_endpoint_impl::connection::receive_cbk( - packet_buffer_ptr_t _buffer, - boost::system::error_code const &_error, std::size_t _bytes) { - - std::shared_ptr its_host = server_->host_.lock(); - if (its_host) { - std::size_t its_start; - std::size_t its_end; - - if (!_error && 0 < _bytes) { - #if 0 - std::stringstream msg; - msg << "lse::c<" << this << ">rcb: "; - for (std::size_t i = 0; i < _bytes; i++) - msg << std::setw(2) << std::setfill('0') << std::hex - << (int)(*_buffer)[i] << " "; - VSOMEIP_DEBUG << msg.str(); - #endif - - message_.insert(message_.end(), _buffer->begin(), - _buffer->begin() + _bytes); - - #define MESSAGE_IS_EMPTY (-1) - #define FOUND_MESSAGE (-2) - - do { - its_start = 0; - while (its_start + 3 < message_.size() && - (message_[its_start] != 0x67 || - message_[its_start+1] != 0x37 || - message_[its_start+2] != 0x6d || - message_[its_start+3] != 0x07)) { - its_start ++; - } - - its_start = (its_start + 3 == message_.size() ? - MESSAGE_IS_EMPTY : its_start+4); - - if (its_start != MESSAGE_IS_EMPTY) { - its_end = its_start; - while (its_end + 3 < message_.size() && - (message_[its_end] != 0x07 || - message_[its_end+1] != 0x6d || - message_[its_end+2] != 0x37 || - message_[its_end+3] != 0x67)) { - its_end ++; - } - } - - if (its_start != MESSAGE_IS_EMPTY && - its_end+3 < message_.size()) { - its_host->on_message(&message_[its_start], - its_end - its_start, server_); - - #if 0 - std::stringstream local_msg; - local_msg << "lse::c<" << this << ">rcb::thunk: "; - for (std::size_t i = its_start; i < its_end; i++) - local_msg << std::setw(2) << std::setfill('0') << std::hex - << (int)(message_)[i] << " "; - VSOMEIP_DEBUG << local_msg.str(); - #endif - - message_.erase(message_.begin(), - message_.begin() + its_end + 4); - its_start = FOUND_MESSAGE; - } - } while (message_.size() > 0 && its_start == FOUND_MESSAGE); - } - - if (_error == boost::asio::error::misc_errors::eof) { - server_->remove_connection(this); - } else { - start(); - } - } -} - -} // namespace vsomeip +// Copyright (C) 2014-2015 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 +#include +#include + +#include + +#include "../include/endpoint_host.hpp" +#include "../include/local_server_endpoint_impl.hpp" + +#include "../../logging/include/logger.hpp" + +namespace vsomeip { + +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) + : local_server_endpoint_base_impl(_host, _local, _io, _max_message_size), + acceptor_(_io, _local) { + is_supporting_magic_cookies_ = false; +} + +local_server_endpoint_impl::~local_server_endpoint_impl() { +} + +bool local_server_endpoint_impl::is_local() const { + return true; +} + +void local_server_endpoint_impl::start() { + connection::ptr new_connection = connection::create(this, max_message_size_); + + acceptor_.async_accept( + new_connection->get_socket(), + std::bind( + &local_server_endpoint_impl::accept_cbk, + std::dynamic_pointer_cast< + local_server_endpoint_impl + >(shared_from_this()), + new_connection, + std::placeholders::_1 + ) + ); +} + +void local_server_endpoint_impl::stop() { +} + +bool local_server_endpoint_impl::send_to( + const std::shared_ptr _target, + const byte_t *_data, uint32_t _size, bool _flush) { + (void)_target; + (void)_data; + (void)_size; + (void)_flush; + return false; +} + +void local_server_endpoint_impl::send_queued( + queue_iterator_type _queue_iterator) { + auto connection_iterator = connections_.find(_queue_iterator->first); + if (connection_iterator != connections_.end()) + connection_iterator->second->send_queued(_queue_iterator); +} + +void local_server_endpoint_impl::receive() { + // intentionally left empty +} + +void local_server_endpoint_impl::restart() { + current_->start(); +} + +local_server_endpoint_impl::endpoint_type +local_server_endpoint_impl::get_remote() const { + return current_->get_socket().remote_endpoint(); +} + +bool local_server_endpoint_impl::get_multicast( + service_t, event_t, + local_server_endpoint_impl::endpoint_type &) const { + return false; +} + +void local_server_endpoint_impl::remove_connection( + local_server_endpoint_impl::connection *_connection) { + std::map< endpoint_type, connection::ptr >::iterator i + = connections_.end(); + for (i = connections_.begin(); i != connections_.end(); i++) { + if (i->second.get() == _connection) + break; + } + + if (i != connections_.end()) { + connections_.erase(i); + } +} + +void local_server_endpoint_impl::accept_cbk( + connection::ptr _connection, boost::system::error_code const &_error) { + + if (!_error) { + socket_type &new_connection_socket = _connection->get_socket(); + endpoint_type remote = new_connection_socket.remote_endpoint(); + + connections_[remote] = _connection; + _connection->start(); + } + + start(); +} + +/////////////////////////////////////////////////////////////////////////////// +// class local_service_impl::connection +/////////////////////////////////////////////////////////////////////////////// + +local_server_endpoint_impl::connection::connection( + local_server_endpoint_impl *_server, std::uint32_t _max_message_size) + : socket_(_server->service_), server_(_server), + max_message_size_(_max_message_size + 8), + recv_buffer_(max_message_size_, 0), + recv_buffer_size_(0) { +} + +local_server_endpoint_impl::connection::ptr +local_server_endpoint_impl::connection::create( + local_server_endpoint_impl *_server, std::uint32_t _max_message_size) { + return ptr(new connection(_server, _max_message_size)); +} + +local_server_endpoint_impl::socket_type & +local_server_endpoint_impl::connection::get_socket() { + return socket_; +} + +void local_server_endpoint_impl::connection::start() { + if (recv_buffer_size_ == max_message_size_) { + // Overrun -> Reset buffer + recv_buffer_size_ = 0; + } + size_t buffer_size = max_message_size_ - recv_buffer_size_; + socket_.async_receive( + boost::asio::buffer(&recv_buffer_[recv_buffer_size_], buffer_size), + std::bind( + &local_server_endpoint_impl::connection::receive_cbk, + shared_from_this(), + std::placeholders::_1, + std::placeholders::_2 + ) + ); +} + +void local_server_endpoint_impl::connection::send_queued( + queue_iterator_type _queue_iterator) { + + // TODO: We currently do _not_ use the send method of the local server + // endpoints. If we ever need it, we need to add the "start tag", "data", + // "end tag" sequence here. + + message_buffer_ptr_t its_buffer = _queue_iterator->second.front(); +#if 0 + std::stringstream msg; + msg << "lse::sq: "; + for (std::size_t i = 0; i < its_buffer->size(); i++) + msg << std::setw(2) << std::setfill('0') << std::hex + << (int)(*its_buffer)[i] << " "; + VSOMEIP_DEBUG << msg.str(); +#endif + boost::asio::async_write( + socket_, + boost::asio::buffer(*its_buffer), + std::bind( + &local_server_endpoint_base_impl::send_cbk, + server_->shared_from_this(), + _queue_iterator, + std::placeholders::_1, + std::placeholders::_2 + ) + ); +} + +void local_server_endpoint_impl::connection::send_magic_cookie() { +} + +void local_server_endpoint_impl::connection::receive_cbk( + boost::system::error_code const &_error, std::size_t _bytes) { + + std::shared_ptr its_host = server_->host_.lock(); + if (its_host) { + std::size_t its_start; + std::size_t its_end; + std::size_t its_iteration_gap = 0; + + if (!_error && 0 < _bytes) { + #if 0 + std::stringstream msg; + msg << "lse::c<" << this << ">rcb: "; + for (std::size_t i = 0; i < _bytes + recv_buffer_size_; i++) + msg << std::setw(2) << std::setfill('0') << std::hex + << (int) (recv_buffer_[i]) << " "; + VSOMEIP_DEBUG << msg.str(); + #endif + + recv_buffer_size_ += _bytes; + + #define MESSAGE_IS_EMPTY std::size_t(-1) + #define FOUND_MESSAGE std::size_t(-2) + + do { + its_start = 0 + its_iteration_gap; + while (its_start + 3 < recv_buffer_size_ + its_iteration_gap && + (recv_buffer_[its_start] != 0x67 || + recv_buffer_[its_start+1] != 0x37 || + recv_buffer_[its_start+2] != 0x6d || + recv_buffer_[its_start+3] != 0x07)) { + its_start ++; + } + + its_start = (its_start + 3 == recv_buffer_size_ + its_iteration_gap ? + MESSAGE_IS_EMPTY : its_start+4); + + if (its_start != MESSAGE_IS_EMPTY) { + its_end = its_start; + while (its_end + 3 < recv_buffer_size_ + its_iteration_gap && + (recv_buffer_[its_end] != 0x07 || + recv_buffer_[its_end+1] != 0x6d || + recv_buffer_[its_end+2] != 0x37 || + recv_buffer_[its_end+3] != 0x67)) { + its_end ++; + } + } + + 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), server_); + + #if 0 + std::stringstream local_msg; + local_msg << "lse::c<" << this << ">rcb::thunk: "; + for (std::size_t i = its_start; i < its_end; i++) + local_msg << std::setw(2) << std::setfill('0') << std::hex + << (int) recv_buffer_[i] << " "; + VSOMEIP_DEBUG << local_msg.str(); + #endif + + recv_buffer_size_ -= (its_end + 4 - its_iteration_gap); + its_start = FOUND_MESSAGE; + its_iteration_gap = its_end + 4; + } else { + if (its_start != MESSAGE_IS_EMPTY && its_iteration_gap) { + // Message not complete and not in front of the buffer! + // Copy last part to front for consume in future receive_cbk call! + for (size_t i = 0; i < recv_buffer_size_; ++i) { + recv_buffer_[i] = recv_buffer_[i + its_iteration_gap]; + } + } + } + } while (recv_buffer_size_ > 0 && its_start == FOUND_MESSAGE); + } + + if (_error == boost::asio::error::misc_errors::eof) { + server_->remove_connection(this); + } else { + start(); + } + } +} + +} // namespace vsomeip diff --git a/implementation/endpoints/src/server_endpoint_impl.cpp b/implementation/endpoints/src/server_endpoint_impl.cpp index 0158cf6..b67ecec 100644 --- a/implementation/endpoints/src/server_endpoint_impl.cpp +++ b/implementation/endpoints/src/server_endpoint_impl.cpp @@ -12,10 +12,10 @@ #include #include -#include #include "../include/server_endpoint_impl.hpp" #include "../../configuration/include/internal.hpp" +#include "../../logging/include/logger.hpp" #include "../../utility/include/byteorder.hpp" #include "../../utility/include/utility.hpp" @@ -24,8 +24,9 @@ namespace vsomeip { template server_endpoint_impl::server_endpoint_impl( std::shared_ptr _host, endpoint_type _local, - boost::asio::io_service &_io) - : endpoint_impl(_host, _io), flush_timer_(_io) { + boost::asio::io_service &_io, std::uint32_t _max_message_size) + : endpoint_impl(_host, _io, _max_message_size), + flush_timer_(_io), local_(_local) { } template @@ -92,7 +93,10 @@ bool server_endpoint_impl::send_intern( endpoint_type _target, const byte_t *_data, uint32_t _size, bool _flush) { - std::shared_ptr > target_packetizer; + bool is_flushing(false); + message_buffer_ptr_t target_packetizer; + queue_iterator_type target_queue_iterator; + auto found_packetizer = packetizer_.find(_target); if (found_packetizer != packetizer_.end()) { target_packetizer = found_packetizer->second; @@ -101,8 +105,19 @@ bool server_endpoint_impl::send_intern( packetizer_.insert(std::make_pair(_target, target_packetizer)); } - if (target_packetizer->size() + _size > MaxBufferSize) { - send_queued(_target, target_packetizer); + target_queue_iterator = queues_.find(_target); + if (target_queue_iterator == queues_.end()) { + target_queue_iterator = queues_.insert(queues_.begin(), + std::make_pair( + _target, + std::deque() + )); + } + + // TODO compare against value from configuration here + if (target_packetizer->size() + _size > endpoint_impl::max_message_size_) { + target_queue_iterator->second.push_back(target_packetizer); + is_flushing = true; packetizer_[_target] = std::make_shared(); } @@ -110,7 +125,8 @@ bool server_endpoint_impl::send_intern( if (_flush) { flush_timer_.cancel(); - send_queued(_target, target_packetizer); + target_queue_iterator->second.push_back(target_packetizer); + is_flushing = true; packetizer_[_target] = std::make_shared(); } else { std::chrono::milliseconds flush_timeout(VSOMEIP_DEFAULT_FLUSH_TIMEOUT); @@ -123,6 +139,11 @@ bool server_endpoint_impl::send_intern( _target, std::placeholders::_1)); } + + if (is_flushing && target_queue_iterator->second.size() == 1) { // no writing in progress + send_queued(target_queue_iterator); + } + return true; } @@ -131,10 +152,9 @@ bool server_endpoint_impl::flush( endpoint_type _target) { bool is_flushed = false; std::lock_guard its_lock(mutex_); - auto i = packetizer_.find(_target); - if (i != packetizer_.end() && !i->second->empty()) { - send_queued(_target, i->second); - i->second = std::make_shared(); + auto queue_iterator = queues_.find(_target); + if (queue_iterator != queues_.end() && !queue_iterator->second.empty()) { + send_queued(queue_iterator); is_flushed = true; } @@ -144,20 +164,22 @@ bool server_endpoint_impl::flush( template void server_endpoint_impl::connect_cbk( boost::system::error_code const &_error) { + (void)_error; } template void server_endpoint_impl::send_cbk( - message_buffer_ptr_t _buffer, boost::system::error_code const &_error, + queue_iterator_type _queue_iterator, boost::system::error_code const &_error, std::size_t _bytes) { -#if 0 - std::stringstream msg; - msg << "sei::scb (" << _error.message() << "): "; - for (std::size_t i = 0; i < _buffer->size(); ++i) - msg << std::hex << std::setw(2) << std::setfill('0') - << (int)(*_buffer)[i] << " "; - VSOMEIP_DEBUG << msg.str(); -#endif + (void)_bytes; + + if (!_error) { + std::lock_guard its_lock(mutex_); + _queue_iterator->second.pop_front(); + if (_queue_iterator->second.size() > 0) { + send_queued(_queue_iterator); + } + } } template @@ -170,16 +192,15 @@ void server_endpoint_impl::flush_cbk( // Instantiate template #ifndef WIN32 -template class server_endpoint_impl ; -#else -// TODO: put instantiation for windows here! -//template class server_endpoint_impl; +template class server_endpoint_impl< + boost::asio::local::stream_protocol, + VSOMEIP_MAX_LOCAL_MESSAGE_SIZE> ; #endif -template class server_endpoint_impl ; -template class server_endpoint_impl ; +template class server_endpoint_impl< + boost::asio::ip::tcp, + VSOMEIP_MAX_TCP_MESSAGE_SIZE> ; +template class server_endpoint_impl< + boost::asio::ip::udp, + VSOMEIP_MAX_UDP_MESSAGE_SIZE> ; } // namespace vsomeip diff --git a/implementation/endpoints/src/tcp_client_endpoint_impl.cpp b/implementation/endpoints/src/tcp_client_endpoint_impl.cpp index cf91fa7..26c7424 100644 --- a/implementation/endpoints/src/tcp_client_endpoint_impl.cpp +++ b/implementation/endpoints/src/tcp_client_endpoint_impl.cpp @@ -9,10 +9,10 @@ #include #include -#include #include "../include/endpoint_host.hpp" #include "../include/tcp_client_endpoint_impl.hpp" +#include "../../logging/include/logger.hpp" #include "../../utility/include/utility.hpp" namespace ip = boost::asio::ip; @@ -20,8 +20,11 @@ namespace ip = boost::asio::ip; namespace vsomeip { tcp_client_endpoint_impl::tcp_client_endpoint_impl( - std::shared_ptr< endpoint_host > _host, endpoint_type _remote, boost::asio::io_service &_io) - : tcp_client_endpoint_base_impl(_host, _remote, _io) { + std::shared_ptr< endpoint_host > _host, endpoint_type _remote, + boost::asio::io_service &_io, std::uint32_t _max_message_size) + : tcp_client_endpoint_base_impl(_host, _remote, _io, _max_message_size), + recv_buffer_(_max_message_size, 0), + recv_buffer_size_(0) { is_supporting_magic_cookies_ = true; } @@ -40,8 +43,7 @@ void tcp_client_endpoint_impl::connect() { socket_.open(remote_.protocol()); // Nagle algorithm off - ip::tcp::no_delay option; - socket_.set_option(option); + socket_.set_option(ip::tcp::no_delay(true)); socket_.async_connect( remote_, @@ -54,31 +56,44 @@ void tcp_client_endpoint_impl::connect() { } void tcp_client_endpoint_impl::receive() { - packet_buffer_ptr_t its_buffer - = std::make_shared< packet_buffer_t >(); + if (recv_buffer_size_ == max_message_size_) { + // Overrun -> Reset buffer + recv_buffer_size_ = 0; + } + size_t buffer_size = max_message_size_ - recv_buffer_size_; socket_.async_receive( - boost::asio::buffer(*its_buffer), + boost::asio::buffer(&recv_buffer_[recv_buffer_size_], buffer_size), std::bind( &tcp_client_endpoint_impl::receive_cbk, std::dynamic_pointer_cast< tcp_client_endpoint_impl >(shared_from_this()), - its_buffer, std::placeholders::_1, std::placeholders::_2 ) ); } -void tcp_client_endpoint_impl::send_queued(message_buffer_ptr_t _buffer) { +void tcp_client_endpoint_impl::send_queued() { + message_buffer_ptr_t its_buffer = queue_.front(); + if (has_enabled_magic_cookies_) - send_magic_cookie(_buffer); + send_magic_cookie(its_buffer); + +#if 0 + std::stringstream msg; + msg << "tcei<" << remote_.address() << ":" + << std::dec << remote_.port() << ">::sq: "; + for (std::size_t i = 0; i < its_buffer->size(); i++) + msg << std::hex << std::setw(2) << std::setfill('0') + << (int)(*its_buffer)[i] << " "; + VSOMEIP_DEBUG << msg.str(); +#endif boost::asio::async_write( socket_, - boost::asio::buffer(*_buffer), + boost::asio::buffer(*its_buffer), std::bind( &tcp_client_endpoint_base_impl::send_cbk, shared_from_this(), - _buffer, std::placeholders::_1, std::placeholders::_2 ) @@ -103,8 +118,8 @@ bool tcp_client_endpoint_impl::is_reliable() const { return true; } -bool tcp_client_endpoint_impl::is_magic_cookie() const { - return (0 == std::memcmp(SERVICE_COOKIE, &message_[0], sizeof(SERVICE_COOKIE))); +bool tcp_client_endpoint_impl::is_magic_cookie(size_t _offset) const { + return (0 == std::memcmp(SERVICE_COOKIE, &recv_buffer_[_offset], sizeof(SERVICE_COOKIE))); } void tcp_client_endpoint_impl::send_magic_cookie(message_buffer_ptr_t &_buffer) { @@ -121,35 +136,36 @@ void tcp_client_endpoint_impl::send_magic_cookie(message_buffer_ptr_t &_buffer) } void tcp_client_endpoint_impl::receive_cbk( - packet_buffer_ptr_t _buffer, boost::system::error_code const &_error, std::size_t _bytes) { #if 0 std::stringstream msg; msg << "cei::rcb (" << _error.message() << "): "; - for (std::size_t i = 0; i < _bytes; ++i) + for (std::size_t i = 0; i < _bytes + recv_buffer_size_; ++i) msg << std::hex << std::setw(2) << std::setfill('0') - << (int)(*_buffer)[i] << " "; + << (int) recv_buffer_[i] << " "; VSOMEIP_DEBUG << msg.str(); #endif std::shared_ptr its_host = host_.lock(); if (its_host) { if (!_error && 0 < _bytes) { - this->message_.insert(this->message_.end(), _buffer->begin(), - _buffer->begin() + _bytes); + recv_buffer_size_ += _bytes; + size_t its_iteration_gap = 0; bool has_full_message; do { uint32_t current_message_size - = utility::get_message_size(message_); + = utility::get_message_size(&recv_buffer_[its_iteration_gap], + (uint32_t) recv_buffer_size_); has_full_message = (current_message_size > 0 - && current_message_size <= message_.size()); + && current_message_size <= recv_buffer_size_); if (has_full_message) { bool needs_forwarding(true); - if (is_magic_cookie()) { + if (is_magic_cookie(its_iteration_gap)) { has_enabled_magic_cookies_ = true; } else { if (has_enabled_magic_cookies_) { - uint32_t its_offset = find_magic_cookie(message_); + uint32_t its_offset = find_magic_cookie(&recv_buffer_[its_iteration_gap], + (uint32_t) recv_buffer_size_); if (its_offset < current_message_size) { VSOMEIP_ERROR << "Message includes Magic Cookie. Ignoring it."; current_message_size = its_offset; @@ -157,27 +173,44 @@ void tcp_client_endpoint_impl::receive_cbk( } } } - if (needs_forwarding) - its_host->on_message(&message_[0], - current_message_size, this); - message_.erase(message_.begin(), - message_.begin() + current_message_size); - } else if (has_enabled_magic_cookies_ && message_.size() > 0){ - uint32_t its_offset = find_magic_cookie(message_); - if (its_offset < message_.size()) { - message_.erase(message_.begin(), - message_.begin() + its_offset); + if (needs_forwarding) { + if (!has_enabled_magic_cookies_) { + its_host->on_message(&recv_buffer_[its_iteration_gap], + current_message_size, this); + } else { + // Only call on_message without a magic cookie in front of the buffer! + if (!is_magic_cookie(its_iteration_gap)) { + its_host->on_message(&recv_buffer_[its_iteration_gap], + current_message_size, this); + } + } + } + recv_buffer_size_ -= current_message_size; + its_iteration_gap += current_message_size; + } else if (has_enabled_magic_cookies_ && recv_buffer_size_ > 0){ + uint32_t its_offset = find_magic_cookie(&recv_buffer_[its_iteration_gap], recv_buffer_size_); + if (its_offset < recv_buffer_size_) { + recv_buffer_size_ -= its_offset; + its_iteration_gap += its_offset; has_full_message = true; // trigger next loop } - } else if (message_.size() > VSOMEIP_MAX_TCP_MESSAGE_SIZE) { + } else if (current_message_size > max_message_size_) { VSOMEIP_ERROR << "Message exceeds maximum message size. " << "Resetting receiver."; - message_.clear(); + recv_buffer_size_ = 0; + } + } while (has_full_message && recv_buffer_size_); + if (its_iteration_gap) { + // Copy incomplete message to front for next receive_cbk iteration + for (size_t i = 0; i < recv_buffer_size_; ++i) { + recv_buffer_[i] = recv_buffer_[i + its_iteration_gap]; } - } while (has_full_message); + } restart(); } else { - receive(); + if (socket_.is_open()) { + receive(); + } } } } diff --git a/implementation/endpoints/src/tcp_server_endpoint_impl.cpp b/implementation/endpoints/src/tcp_server_endpoint_impl.cpp index be4ac5f..20391a0 100644 --- a/implementation/endpoints/src/tcp_server_endpoint_impl.cpp +++ b/implementation/endpoints/src/tcp_server_endpoint_impl.cpp @@ -1,263 +1,322 @@ -// Copyright (C) 2014-2015 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 - -#include -#include - -#include "../include/endpoint_definition.hpp" -#include "../include/endpoint_host.hpp" -#include "../include/tcp_server_endpoint_impl.hpp" -#include "../../utility/include/utility.hpp" - -namespace ip = boost::asio::ip; - -namespace vsomeip { - -tcp_server_endpoint_impl::tcp_server_endpoint_impl( - std::shared_ptr _host, endpoint_type _local, - boost::asio::io_service &_io) - : tcp_server_endpoint_base_impl(_host, _local, _io), - acceptor_(_io, _local), - current_(0) { - is_supporting_magic_cookies_ = true; -} - -tcp_server_endpoint_impl::~tcp_server_endpoint_impl() { -} - -bool tcp_server_endpoint_impl::is_local() const { - return false; -} - -void tcp_server_endpoint_impl::start() { - connection::ptr new_connection = connection::create(this); - - acceptor_.async_accept(new_connection->get_socket(), - std::bind(&tcp_server_endpoint_impl::accept_cbk, - std::dynamic_pointer_cast( - shared_from_this()), new_connection, - std::placeholders::_1)); -} - -void tcp_server_endpoint_impl::stop() { - for (auto& i : connections_) - i.second->stop(); - acceptor_.close(); -} - -bool tcp_server_endpoint_impl::send_to( - const std::shared_ptr _target, - const byte_t *_data, - uint32_t _size, bool _flush) { - endpoint_type its_target(_target->get_address(), _target->get_port()); - return send_intern(its_target, _data, _size, _flush); -} - -void tcp_server_endpoint_impl::send_queued(endpoint_type _target, - message_buffer_ptr_t _buffer) { - auto connection_iterator = connections_.find(_target); - if (connection_iterator != connections_.end()) - connection_iterator->second->send_queued(_buffer); -} - -tcp_server_endpoint_impl::endpoint_type -tcp_server_endpoint_impl::get_remote() const { - return current_->get_socket().remote_endpoint(); -} - -bool tcp_server_endpoint_impl::get_multicast(service_t, event_t, - tcp_server_endpoint_impl::endpoint_type &) const { - return false; -} - -void tcp_server_endpoint_impl::accept_cbk(connection::ptr _connection, - boost::system::error_code const &_error) { - - if (!_error) { - socket_type &new_connection_socket = _connection->get_socket(); - endpoint_type remote = new_connection_socket.remote_endpoint(); - - connections_[remote] = _connection; - _connection->start(); - } - - start(); -} - -unsigned short tcp_server_endpoint_impl::get_local_port() const { - return acceptor_.local_endpoint().port(); -} - -bool tcp_server_endpoint_impl::is_reliable() const { - return true; -} - -/////////////////////////////////////////////////////////////////////////////// -// class tcp_service_impl::connection -/////////////////////////////////////////////////////////////////////////////// -tcp_server_endpoint_impl::connection::connection( - tcp_server_endpoint_impl *_server) : - socket_(_server->service_), server_(_server) { -} - -tcp_server_endpoint_impl::connection::ptr -tcp_server_endpoint_impl::connection::create( - tcp_server_endpoint_impl *_server) { - return ptr(new connection(_server)); -} - -tcp_server_endpoint_impl::socket_type & -tcp_server_endpoint_impl::connection::get_socket() { - return socket_; -} - -void tcp_server_endpoint_impl::connection::start() { - packet_buffer_ptr_t its_buffer = std::make_shared(); - socket_.async_receive(boost::asio::buffer(*its_buffer), - std::bind(&tcp_server_endpoint_impl::connection::receive_cbk, - shared_from_this(), its_buffer, std::placeholders::_1, - std::placeholders::_2)); -} - -void tcp_server_endpoint_impl::connection::stop() { - socket_.close(); -} - -void tcp_server_endpoint_impl::connection::send_queued( - message_buffer_ptr_t _buffer) { - if (server_->has_enabled_magic_cookies_) - send_magic_cookie(_buffer); - - boost::asio::async_write(socket_, boost::asio::buffer(*_buffer), - std::bind(&tcp_server_endpoint_base_impl::send_cbk, - server_->shared_from_this(), - _buffer, std::placeholders::_1, - std::placeholders::_2)); -} - -void tcp_server_endpoint_impl::connection::send_magic_cookie( - message_buffer_ptr_t &_buffer) { - if (VSOMEIP_MAX_TCP_MESSAGE_SIZE - _buffer->size() >= - VSOMEIP_SOMEIP_HEADER_SIZE + VSOMEIP_SOMEIP_MAGIC_COOKIE_SIZE) { - _buffer->insert(_buffer->begin(), SERVICE_COOKIE, - SERVICE_COOKIE + sizeof(SERVICE_COOKIE)); - } -} - -bool tcp_server_endpoint_impl::connection::is_magic_cookie() const { - return (0 == std::memcmp(CLIENT_COOKIE, &message_[0], - sizeof(CLIENT_COOKIE))); -} - -void tcp_server_endpoint_impl::connection::receive_cbk( - packet_buffer_ptr_t _buffer, boost::system::error_code const &_error, - std::size_t _bytes) { -#if 0 - std::stringstream msg; - for (std::size_t i = 0; i < _bytes; ++i) - msg << std::hex << std::setw(2) << std::setfill('0') - << (int) (*_buffer)[i] << " "; - VSOMEIP_DEBUG<< msg.str(); -#endif - std::shared_ptr its_host = server_->host_.lock(); - if (its_host) { - if (!_error && 0 < _bytes) { - message_.insert(message_.end(), _buffer->begin(), - _buffer->begin() + _bytes); - - static int i = 1; - - bool has_full_message; - do { - uint32_t current_message_size - = utility::get_message_size(message_); - has_full_message = (current_message_size > 0 - && current_message_size <= message_.size()); - if (has_full_message) { - bool needs_forwarding(true); - if (is_magic_cookie()) { - server_->has_enabled_magic_cookies_ = true; - } else { - if (server_->has_enabled_magic_cookies_) { - uint32_t its_offset - = server_->find_magic_cookie(message_); - if (its_offset < current_message_size) { - VSOMEIP_ERROR << "Detected Magic Cookie within message data. Resyncing."; - current_message_size = its_offset; - needs_forwarding = false; - } - } - } - if (needs_forwarding) { - if (utility::is_request(message_[VSOMEIP_MESSAGE_TYPE_POS])) { - client_t its_client; - std::memcpy(&its_client, - &message_[VSOMEIP_CLIENT_POS_MIN], - sizeof(client_t)); - session_t its_session; - std::memcpy(&its_session, - &message_[VSOMEIP_SESSION_POS_MIN], - sizeof(session_t)); - server_->clients_[its_client][its_session] = - socket_.remote_endpoint(); - } - its_host->on_message(&message_[0], current_message_size, server_); - } - message_.erase(message_.begin(), message_.begin() + current_message_size); - } else if (server_->has_enabled_magic_cookies_ && message_.size() > 0){ - uint32_t its_offset = server_->find_magic_cookie(message_); - if (its_offset < message_.size()) { - VSOMEIP_ERROR << "Detected Magic Cookie within message data. Resyncing."; - message_.erase(message_.begin(), message_.begin() + its_offset); - has_full_message = true; // trigger next loop - } - } else if (message_.size() > VSOMEIP_MAX_TCP_MESSAGE_SIZE) { - VSOMEIP_ERROR << "Message exceeds maximum message size. Resetting receiver."; - message_.clear(); - } - } while (has_full_message); - - start(); - } - } -} - -client_t tcp_server_endpoint_impl::get_client(std::shared_ptr _endpoint) { - endpoint_type endpoint(_endpoint->get_address(), _endpoint->get_port()); - auto its_remote = connections_.find(endpoint); - if (its_remote != connections_.end()) { - return its_remote->second->get_client(endpoint); - } - return 0; -} - -client_t tcp_server_endpoint_impl::connection::get_client(endpoint_type _endpoint_type) { - for (auto its_client : server_->clients_) { - for (auto its_session : server_->clients_[its_client.first]) { - auto endpoint = its_session.second; - if (endpoint == _endpoint_type) { - // TODO: Check system byte order before convert! - client_t client = its_client.first << 8 | its_client.first >> 8; - return client; - } - } - } - return 0; -} - -// Dummies -void tcp_server_endpoint_impl::receive() { - // intentionally left empty -} - -void tcp_server_endpoint_impl::restart() { - // intentionally left empty -} - -} // namespace vsomeip +// Copyright (C) 2014-2015 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 + +#include + +#include "../include/endpoint_definition.hpp" +#include "../include/endpoint_host.hpp" +#include "../include/tcp_server_endpoint_impl.hpp" +#include "../../logging/include/logger.hpp" +#include "../../utility/include/utility.hpp" + +namespace ip = boost::asio::ip; + +namespace vsomeip { + +tcp_server_endpoint_impl::tcp_server_endpoint_impl( + std::shared_ptr _host, endpoint_type _local, + boost::asio::io_service &_io, std::uint32_t _max_message_size) + : tcp_server_endpoint_base_impl(_host, _local, _io, _max_message_size), + acceptor_(_io, _local), + current_(0) { + is_supporting_magic_cookies_ = true; +} + +tcp_server_endpoint_impl::~tcp_server_endpoint_impl() { +} + +bool tcp_server_endpoint_impl::is_local() const { + return false; +} + +void tcp_server_endpoint_impl::start() { + connection::ptr new_connection = connection::create(this, max_message_size_); + + acceptor_.async_accept(new_connection->get_socket(), + std::bind(&tcp_server_endpoint_impl::accept_cbk, + std::dynamic_pointer_cast( + shared_from_this()), new_connection, + std::placeholders::_1)); +} + +void tcp_server_endpoint_impl::stop() { + for (auto& i : connections_) + i.second->stop(); + acceptor_.close(); +} + +bool tcp_server_endpoint_impl::send_to( + const std::shared_ptr _target, + const byte_t *_data, + uint32_t _size, bool _flush) { + endpoint_type its_target(_target->get_address(), _target->get_port()); + return send_intern(its_target, _data, _size, _flush); +} + +void tcp_server_endpoint_impl::send_queued(queue_iterator_type _queue_iterator) { + auto connection_iterator = connections_.find(_queue_iterator->first); + if (connection_iterator != connections_.end()) + connection_iterator->second->send_queued(_queue_iterator); +} + +tcp_server_endpoint_impl::endpoint_type +tcp_server_endpoint_impl::get_remote() const { + return current_->get_socket().remote_endpoint(); +} + +bool tcp_server_endpoint_impl::get_multicast(service_t, event_t, + tcp_server_endpoint_impl::endpoint_type &) const { + return false; +} + +void tcp_server_endpoint_impl::accept_cbk(connection::ptr _connection, + boost::system::error_code const &_error) { + + if (!_error) { + socket_type &new_connection_socket = _connection->get_socket(); + endpoint_type remote = new_connection_socket.remote_endpoint(); + + connections_[remote] = _connection; + _connection->start(); + + start(); + } +} + +unsigned short tcp_server_endpoint_impl::get_local_port() const { + return acceptor_.local_endpoint().port(); +} + +bool tcp_server_endpoint_impl::is_reliable() const { + return true; +} + +/////////////////////////////////////////////////////////////////////////////// +// class tcp_service_impl::connection +/////////////////////////////////////////////////////////////////////////////// +tcp_server_endpoint_impl::connection::connection( + tcp_server_endpoint_impl *_server, std::uint32_t _max_message_size) : + socket_(_server->service_), server_(_server), + max_message_size_(_max_message_size), + recv_buffer_(_max_message_size, 0), + recv_buffer_size_(0) { +} + +tcp_server_endpoint_impl::connection::ptr +tcp_server_endpoint_impl::connection::create( + tcp_server_endpoint_impl *_server, std::uint32_t _max_message_size) { + return ptr(new connection(_server, _max_message_size)); +} + +tcp_server_endpoint_impl::socket_type & +tcp_server_endpoint_impl::connection::get_socket() { + return socket_; +} + +void tcp_server_endpoint_impl::connection::start() { + receive(); + // Nagle algorithm off + socket_.set_option(ip::tcp::no_delay(true)); +} + +void tcp_server_endpoint_impl::connection::receive() { + if (recv_buffer_size_ == max_message_size_) { + // Overrun -> Reset buffer + recv_buffer_size_ = 0; + } + std::lock_guard its_lock(stop_mutex_); + if(socket_.is_open()) { + size_t buffer_size = max_message_size_ - recv_buffer_size_; + socket_.async_receive(boost::asio::buffer(&recv_buffer_[recv_buffer_size_], buffer_size), + std::bind(&tcp_server_endpoint_impl::connection::receive_cbk, + shared_from_this(), std::placeholders::_1, + std::placeholders::_2)); + } +} + +void tcp_server_endpoint_impl::connection::stop() { + std::lock_guard its_lock(stop_mutex_); + if(socket_.is_open()) { + socket_.shutdown(socket_.shutdown_both); + socket_.close(); + } +} + +void tcp_server_endpoint_impl::connection::send_queued( + queue_iterator_type _queue_iterator) { + message_buffer_ptr_t its_buffer = _queue_iterator->second.front(); + + if (server_->has_enabled_magic_cookies_) + send_magic_cookie(its_buffer); + + boost::asio::async_write(socket_, boost::asio::buffer(*its_buffer), + std::bind(&tcp_server_endpoint_base_impl::send_cbk, + server_->shared_from_this(), + _queue_iterator, std::placeholders::_1, + std::placeholders::_2)); +} + +void tcp_server_endpoint_impl::connection::send_magic_cookie( + message_buffer_ptr_t &_buffer) { + if (VSOMEIP_MAX_TCP_MESSAGE_SIZE - _buffer->size() >= + VSOMEIP_SOMEIP_HEADER_SIZE + VSOMEIP_SOMEIP_MAGIC_COOKIE_SIZE) { + _buffer->insert(_buffer->begin(), SERVICE_COOKIE, + SERVICE_COOKIE + sizeof(SERVICE_COOKIE)); + } +} + +bool tcp_server_endpoint_impl::connection::is_magic_cookie(size_t _offset) const { + return (0 == std::memcmp(CLIENT_COOKIE, &recv_buffer_[_offset], + sizeof(CLIENT_COOKIE))); +} + +void tcp_server_endpoint_impl::connection::receive_cbk( + boost::system::error_code const &_error, + std::size_t _bytes) { +#if 0 + std::stringstream msg; + for (std::size_t i = 0; i < _bytes + recv_buffer_size_; ++i) + msg << std::hex << std::setw(2) << std::setfill('0') + << (int) recv_buffer_[i] << " "; + VSOMEIP_DEBUG<< msg.str(); +#endif + std::shared_ptr its_host = server_->host_.lock(); + if (its_host) { + if (!_error && 0 < _bytes) { + recv_buffer_size_ += _bytes; + + size_t its_iteration_gap = 0; + bool has_full_message; + do { + uint32_t current_message_size + = utility::get_message_size(&recv_buffer_[its_iteration_gap], + (uint32_t) recv_buffer_size_); + has_full_message = (current_message_size > VSOMEIP_SOMEIP_HEADER_SIZE + && current_message_size <= recv_buffer_size_); + if (has_full_message) { + bool needs_forwarding(true); + if (is_magic_cookie(its_iteration_gap)) { + server_->has_enabled_magic_cookies_ = true; + } else { + if (server_->has_enabled_magic_cookies_) { + uint32_t its_offset + = server_->find_magic_cookie(&recv_buffer_[its_iteration_gap], + recv_buffer_size_); + if (its_offset < current_message_size) { + VSOMEIP_ERROR << "Detected Magic Cookie within message data. Resyncing."; + if (!is_magic_cookie(its_iteration_gap)) { + its_host->on_error(&recv_buffer_[its_iteration_gap], + static_cast(recv_buffer_size_), server_); + } + current_message_size = its_offset; + needs_forwarding = false; + } + } + } + if (needs_forwarding) { + if (utility::is_request(recv_buffer_[VSOMEIP_MESSAGE_TYPE_POS])) { + client_t its_client; + std::memcpy(&its_client, + &recv_buffer_[VSOMEIP_CLIENT_POS_MIN], + sizeof(client_t)); + session_t its_session; + std::memcpy(&its_session, + &recv_buffer_[VSOMEIP_SESSION_POS_MIN], + sizeof(session_t)); + { + std::lock_guard its_lock(stop_mutex_); + if (socket_.is_open()) { + server_->clients_[its_client][its_session] = + socket_.remote_endpoint(); + server_->current_ = this; + } + } + } + if (!server_->has_enabled_magic_cookies_) { + its_host->on_message(&recv_buffer_[its_iteration_gap], + current_message_size, server_); + } else { + // Only call on_message without a magic cookie in front of the buffer! + if (!is_magic_cookie(its_iteration_gap)) { + its_host->on_message(&recv_buffer_[its_iteration_gap], + current_message_size, server_); + } + } + } + recv_buffer_size_ -= current_message_size; + its_iteration_gap += current_message_size; + } else if (server_->has_enabled_magic_cookies_ && recv_buffer_size_ > 0){ + uint32_t its_offset = + server_->find_magic_cookie(&recv_buffer_[its_iteration_gap], + recv_buffer_size_); + if (its_offset < recv_buffer_size_) { + VSOMEIP_ERROR << "Detected Magic Cookie within message data. Resyncing."; + if (!is_magic_cookie(its_iteration_gap)) { + its_host->on_error(&recv_buffer_[its_iteration_gap], + static_cast(recv_buffer_size_), server_); + } + recv_buffer_size_ -= its_offset; + its_iteration_gap += its_offset; + has_full_message = true; // trigger next loop + if (!is_magic_cookie(its_iteration_gap)) { + its_host->on_error(&recv_buffer_[its_iteration_gap], + static_cast(recv_buffer_size_), server_); + } + } + } else if (current_message_size > max_message_size_) { + VSOMEIP_ERROR << "Message exceeds maximum message size (" + << std::dec << current_message_size + << "). Resetting receiver."; + recv_buffer_size_ = 0; + } + } while (has_full_message && recv_buffer_size_); + if (its_iteration_gap) { + // Copy incomplete message to front for next receive_cbk iteration + for (size_t i = 0; i < recv_buffer_size_; ++i) { + recv_buffer_[i] = recv_buffer_[i + its_iteration_gap]; + } + } + receive(); + } + } +} + +client_t tcp_server_endpoint_impl::get_client(std::shared_ptr _endpoint) { + endpoint_type endpoint(_endpoint->get_address(), _endpoint->get_port()); + auto its_remote = connections_.find(endpoint); + if (its_remote != connections_.end()) { + return its_remote->second->get_client(endpoint); + } + return 0; +} + +client_t tcp_server_endpoint_impl::connection::get_client(endpoint_type _endpoint_type) { + for (auto its_client : server_->clients_) { + for (auto its_session : server_->clients_[its_client.first]) { + auto endpoint = its_session.second; + if (endpoint == _endpoint_type) { + // TODO: Check system byte order before convert! + client_t client = client_t(its_client.first << 8 | its_client.first >> 8); + return client; + } + } + } + return 0; +} + +// Dummies +void tcp_server_endpoint_impl::receive() { + // intentionally left empty +} + +void tcp_server_endpoint_impl::restart() { + // intentionally left empty +} + +} // namespace vsomeip diff --git a/implementation/endpoints/src/udp_client_endpoint_impl.cpp b/implementation/endpoints/src/udp_client_endpoint_impl.cpp index 95f12c3..a5a90cc 100644 --- a/implementation/endpoints/src/udp_client_endpoint_impl.cpp +++ b/implementation/endpoints/src/udp_client_endpoint_impl.cpp @@ -8,10 +8,9 @@ #include -#include - #include "../include/endpoint_host.hpp" #include "../include/udp_client_endpoint_impl.hpp" +#include "../../logging/include/logger.hpp" #include "../../utility/include/utility.hpp" namespace vsomeip { @@ -19,7 +18,9 @@ namespace vsomeip { udp_client_endpoint_impl::udp_client_endpoint_impl( std::shared_ptr< endpoint_host > _host, endpoint_type _remote, boost::asio::io_service &_io) - : udp_client_endpoint_base_impl(_host, _remote, _io) { + : udp_client_endpoint_base_impl(_host, _remote, _io, VSOMEIP_MAX_UDP_MESSAGE_SIZE), + recv_buffer_(VSOMEIP_MAX_UDP_MESSAGE_SIZE, 0), + recv_buffer_size_(0) { } udp_client_endpoint_impl::~udp_client_endpoint_impl() { @@ -43,44 +44,44 @@ void udp_client_endpoint_impl::connect() { void udp_client_endpoint_impl::start() { socket_.open(remote_.protocol()); connect(); - receive(); } -void udp_client_endpoint_impl::send_queued(message_buffer_ptr_t _buffer) { +void udp_client_endpoint_impl::send_queued() { + message_buffer_ptr_t its_buffer = queue_.front(); #if 0 std::stringstream msg; msg << "ucei<" << remote_.address() << ":" << std::dec << remote_.port() << ">::sq: "; - for (std::size_t i = 0; i < _buffer->size(); i++) + for (std::size_t i = 0; i < its_buffer->size(); i++) msg << std::hex << std::setw(2) << std::setfill('0') - << (int)(*_buffer)[i] << " "; + << (int)(*its_buffer)[i] << " "; VSOMEIP_DEBUG << msg.str(); #endif socket_.async_send( - boost::asio::buffer(*_buffer), + boost::asio::buffer(*its_buffer), std::bind( &udp_client_endpoint_base_impl::send_cbk, shared_from_this(), - _buffer, std::placeholders::_1, std::placeholders::_2 ) ); - receive(); } void udp_client_endpoint_impl::receive() { - packet_buffer_ptr_t its_buffer - = std::make_shared< packet_buffer_t >(); + if (recv_buffer_size_ == max_message_size_) { + // Overrun -> Reset buffer + recv_buffer_size_ = 0; + } + size_t buffer_size = max_message_size_ - recv_buffer_size_; socket_.async_receive_from( - boost::asio::buffer(*its_buffer), + boost::asio::buffer(&recv_buffer_[recv_buffer_size_], buffer_size), remote_, std::bind( &udp_client_endpoint_impl::receive_cbk, std::dynamic_pointer_cast< udp_client_endpoint_impl >(shared_from_this()), - its_buffer, std::placeholders::_1, std::placeholders::_2 ) @@ -101,69 +102,37 @@ unsigned short udp_client_endpoint_impl::get_remote_port() const { return socket_.remote_endpoint().port(); } -void udp_client_endpoint_impl::join(const std::string &_address) { - - if (remote_.address().is_v4()) { - try { - socket_.set_option( - boost::asio::ip::udp::socket::reuse_address(true)); - socket_.set_option(boost::asio::ip::multicast::join_group( - boost::asio::ip::address::from_string(_address))); - } - catch (...) { - } - } else { - // TODO: support multicast for IPv6 - } -} - -void udp_client_endpoint_impl::leave(const std::string &_address) { - if (remote_.address().is_v4()) { - try { - socket_.set_option( - boost::asio::ip::udp::socket::reuse_address(true)); - socket_.set_option(boost::asio::ip::multicast::leave_group( - boost::asio::ip::address::from_string(_address))); - } - catch (...) { - } - } else { - // TODO: support multicast for IPv6 - } -} - void udp_client_endpoint_impl::receive_cbk( - packet_buffer_ptr_t _buffer, boost::system::error_code const &_error, std::size_t _bytes) { std::shared_ptr its_host = host_.lock(); if (!_error && 0 < _bytes && its_host) { #if 0 std::stringstream msg; msg << "ucei::rcb(" << _error.message() << "): "; - for (std::size_t i = 0; i < _bytes; ++i) + for (std::size_t i = 0; i < _bytes + recv_buffer_size_; ++i) msg << std::hex << std::setw(2) << std::setfill('0') - << (int)(*_buffer)[i] << " "; + << (int) recv_buffer_[i] << " "; VSOMEIP_DEBUG << msg.str(); #endif - this->message_.insert(this->message_.end(), _buffer->begin(), - _buffer->begin() + _bytes); - - bool has_full_message; - do { - uint32_t current_message_size - = utility::get_message_size(this->message_); - - has_full_message = (current_message_size > 0 - && current_message_size <= this->message_.size()); - if (has_full_message) { - its_host->on_message(&message_[0], current_message_size, this); - this->message_.erase(this->message_.begin(), - this->message_.begin() + current_message_size); - } - } while (has_full_message); + recv_buffer_size_ += _bytes; + uint32_t current_message_size + = utility::get_message_size(&this->recv_buffer_[0], + (uint32_t) recv_buffer_size_); + if (current_message_size > VSOMEIP_SOMEIP_HEADER_SIZE && + current_message_size <= _bytes) { + its_host->on_message(&recv_buffer_[0], current_message_size, this); + } else { + VSOMEIP_ERROR << "Received a unreliable vSomeIP message with bad length field"; + } + recv_buffer_size_ = 0; + } + if (!_error) { + receive(); + } else { + if (socket_.is_open()) { + receive(); + } } - - receive(); } } // namespace vsomeip diff --git a/implementation/endpoints/src/udp_server_endpoint_impl.cpp b/implementation/endpoints/src/udp_server_endpoint_impl.cpp index f0fee37..f29dfba 100644 --- a/implementation/endpoints/src/udp_server_endpoint_impl.cpp +++ b/implementation/endpoints/src/udp_server_endpoint_impl.cpp @@ -1,251 +1,264 @@ -// Copyright (C) 2014-2015 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 - -#include - -#include - -#include "../include/endpoint_definition.hpp" -#include "../include/endpoint_host.hpp" -#include "../include/udp_server_endpoint_impl.hpp" -#include "../../utility/include/byteorder.hpp" -#include "../../utility/include/utility.hpp" - -namespace ip = boost::asio::ip; - -namespace vsomeip { - -udp_server_endpoint_impl::udp_server_endpoint_impl( - std::shared_ptr< endpoint_host > _host, - endpoint_type _local, - boost::asio::io_service &_io) - : server_endpoint_impl< - ip::udp, VSOMEIP_MAX_UDP_MESSAGE_SIZE - >(_host, _local, _io), - socket_(_io, _local.protocol()) { +// Copyright (C) 2014-2015 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 + +#include + +#include "../include/endpoint_definition.hpp" +#include "../include/endpoint_host.hpp" +#include "../include/udp_server_endpoint_impl.hpp" +#include "../../logging/include/logger.hpp" +#include "../../utility/include/byteorder.hpp" +#include "../../utility/include/utility.hpp" +#include "../../service_discovery/include/defines.hpp" + +namespace ip = boost::asio::ip; + +namespace vsomeip { + +udp_server_endpoint_impl::udp_server_endpoint_impl( + std::shared_ptr< endpoint_host > _host, + endpoint_type _local, + boost::asio::io_service &_io) + : server_endpoint_impl< + ip::udp, VSOMEIP_MAX_UDP_MESSAGE_SIZE + >(_host, _local, _io, VSOMEIP_MAX_UDP_MESSAGE_SIZE), + socket_(_io, _local.protocol()), + recv_buffer_(VSOMEIP_MAX_UDP_MESSAGE_SIZE, 0), + recv_buffer_size_(0) { boost::system::error_code ec; - boost::asio::socket_base::reuse_address optionReuseAddress(true); + boost::asio::socket_base::reuse_address optionReuseAddress(true); socket_.set_option(optionReuseAddress); socket_.bind(_local, ec); - boost::asio::detail::throw_error(ec, "bind"); - - boost::asio::socket_base::broadcast option(true); - socket_.set_option(option); -} - -udp_server_endpoint_impl::~udp_server_endpoint_impl() { -} - -bool udp_server_endpoint_impl::is_local() const { - return false; -} - -void udp_server_endpoint_impl::start() { - receive(); -} - -void udp_server_endpoint_impl::stop() { - if (socket_.is_open()) - socket_.close(); -} - -void udp_server_endpoint_impl::receive() { - packet_buffer_ptr_t its_buffer - = std::make_shared< packet_buffer_t >(); - socket_.async_receive_from( - boost::asio::buffer(*its_buffer), - remote_, - std::bind( - &udp_server_endpoint_impl::receive_cbk, - std::dynamic_pointer_cast< - udp_server_endpoint_impl >(shared_from_this()), - its_buffer, - std::placeholders::_1, - std::placeholders::_2 - ) - ); -} - -void udp_server_endpoint_impl::restart() { - receive(); -} - -bool udp_server_endpoint_impl::send_to( - const std::shared_ptr _target, - const byte_t *_data, uint32_t _size, bool _flush) { - endpoint_type its_target(_target->get_address(), _target->get_port()); - return send_intern(its_target, _data, _size, _flush); -} - -void udp_server_endpoint_impl::send_queued( - endpoint_type _target, message_buffer_ptr_t _buffer) { -#if 0 - std::stringstream msg; - msg << "usei::sq(" << _target.address().to_string() << ":" - << _target.port() << "): "; - for (std::size_t i = 0; i < _buffer->size(); ++i) - msg << std::hex << std::setw(2) << std::setfill('0') - << (int)(*_buffer)[i] << " "; - VSOMEIP_DEBUG << msg.str(); -#endif - socket_.async_send_to( - boost::asio::buffer(*_buffer), - _target, - std::bind( - &udp_server_endpoint_base_impl::send_cbk, - shared_from_this(), - _buffer, - std::placeholders::_1, - std::placeholders::_2 - ) - ); -} - -udp_server_endpoint_impl::endpoint_type -udp_server_endpoint_impl::get_remote() const { - return remote_; -} - -bool udp_server_endpoint_impl::get_multicast(service_t _service, event_t _event, - udp_server_endpoint_impl::endpoint_type &_target) const { - bool is_valid(false); - auto find_service = multicasts_.find(_service); - if (find_service != multicasts_.end()) { - auto find_event = find_service->second.find(_event); - if (find_event != find_service->second.end()) { - _target = find_event->second; - is_valid = true; - } - } - return is_valid; -} - -void udp_server_endpoint_impl::join(const std::string &_address) { - if (local_.address().is_v4()) { - try { - socket_.set_option( - boost::asio::ip::udp::socket::reuse_address(true)); - socket_.set_option( - boost::asio::ip::multicast::enable_loopback(false)); - socket_.set_option(boost::asio::ip::multicast::join_group( - boost::asio::ip::address::from_string(_address).to_v4())); - } - catch (const std::exception &e) { - VSOMEIP_ERROR << e.what(); - } - } else { - // TODO: support multicast for IPv6 - } -} - -void udp_server_endpoint_impl::leave(const std::string &_address) { - if (local_.address().is_v4()) { - try { - socket_.set_option(boost::asio::ip::multicast::leave_group( - boost::asio::ip::address::from_string(_address))); - } - catch (...) { - - } - } else { - // TODO: support multicast for IPv6 - } -} - -void udp_server_endpoint_impl::add_multicast( - service_t _service, instance_t _instance, - const std::string &_address, uint16_t _port) { - endpoint_type its_endpoint( - boost::asio::ip::address::from_string(_address), _port); - multicasts_[_service][_instance] = its_endpoint; -} - -void udp_server_endpoint_impl::remove_multicast( - service_t _service, instance_t _instance) { - auto found_service = multicasts_.find(_service); - if (found_service != multicasts_.end()) { - auto found_instance = found_service->second.find(_instance); - if (found_instance != found_service->second.end()) { - found_service->second.erase(_instance); - } - } -} - -unsigned short udp_server_endpoint_impl::get_local_port() const { - return socket_.local_endpoint().port(); -} - -// TODO: find a better way to structure the receive functions -void udp_server_endpoint_impl::receive_cbk( - packet_buffer_ptr_t _buffer, - boost::system::error_code const &_error, std::size_t _bytes) { -#if 0 - std::stringstream msg; - msg << "usei::rcb(" << _error.message() << "): "; - for (std::size_t i = 0; i < _bytes; ++i) - msg << std::hex << std::setw(2) << std::setfill('0') - << (int)(*_buffer)[i] << " "; - VSOMEIP_DEBUG << msg.str(); -#endif - std::shared_ptr its_host = this->host_.lock(); - if (its_host) { - if (!_error && 0 < _bytes) { - message_.insert(message_.end(), _buffer->begin(), - _buffer->begin() + _bytes); - - bool has_full_message; - do { - uint32_t current_message_size - = utility::get_message_size(message_); - has_full_message = (current_message_size > 0 - && current_message_size <= message_.size()); - if (has_full_message) { - if (utility::is_request( - message_[VSOMEIP_MESSAGE_TYPE_POS])) { - client_t its_client; - std::memcpy(&its_client, - &message_[VSOMEIP_CLIENT_POS_MIN], - sizeof(client_t)); - session_t its_session; - std::memcpy(&its_session, - &message_[VSOMEIP_SESSION_POS_MIN], - sizeof(session_t)); - clients_[its_client][its_session] = remote_; - } - - its_host->on_message(&message_[0], - current_message_size, this); - message_.erase(message_.begin(), - message_.begin() + current_message_size); - } - } while (has_full_message); - - restart(); - } else { - receive(); - } - } -} - -client_t udp_server_endpoint_impl::get_client(std::shared_ptr _endpoint) { - endpoint_type endpoint(_endpoint->get_address(), _endpoint->get_port()); - for (auto its_client : clients_) { - for (auto its_session : clients_[its_client.first]) { - if (endpoint == its_session.second) { - // TODO: Check system byte order before convert! - client_t client = its_client.first << 8 | its_client.first >> 8; - return client; - } - } - } - return 0; -} - -} // namespace vsomeip + boost::asio::detail::throw_error(ec, "bind"); + + boost::asio::socket_base::broadcast option(true); + socket_.set_option(option); +} + +udp_server_endpoint_impl::~udp_server_endpoint_impl() { +} + +bool udp_server_endpoint_impl::is_local() const { + return false; +} + +void udp_server_endpoint_impl::start() { + receive(); +} + +void udp_server_endpoint_impl::stop() { + std::lock_guard its_lock(stop_mutex_); + if (socket_.is_open()) { + socket_.close(); + } +} + +void udp_server_endpoint_impl::receive() { + if (recv_buffer_size_ == max_message_size_) { + // Overrun -> Reset buffer + recv_buffer_size_ = 0; + } + std::lock_guard its_lock(stop_mutex_); + if(socket_.is_open()) { + size_t buffer_size = max_message_size_ - recv_buffer_size_; + socket_.async_receive_from( + boost::asio::buffer(&recv_buffer_[recv_buffer_size_], buffer_size), + remote_, + std::bind( + &udp_server_endpoint_impl::receive_cbk, + std::dynamic_pointer_cast< + udp_server_endpoint_impl >(shared_from_this()), + std::placeholders::_1, + std::placeholders::_2 + ) + ); + } +} + +void udp_server_endpoint_impl::restart() { + receive(); +} + +bool udp_server_endpoint_impl::send_to( + const std::shared_ptr _target, + const byte_t *_data, uint32_t _size, bool _flush) { + endpoint_type its_target(_target->get_address(), _target->get_port()); + return send_intern(its_target, _data, _size, _flush); +} + +void udp_server_endpoint_impl::send_queued( + queue_iterator_type _queue_iterator) { + message_buffer_ptr_t its_buffer = _queue_iterator->second.front(); +#if 0 + std::stringstream msg; + msg << "usei::sq(" << _queue_iterator->first.address().to_string() << ":" + << _queue_iterator->first.port() << "): "; + for (std::size_t i = 0; i < its_buffer->size(); ++i) + msg << std::hex << std::setw(2) << std::setfill('0') + << (int)(*its_buffer)[i] << " "; + VSOMEIP_DEBUG << msg.str(); +#endif + socket_.async_send_to( + boost::asio::buffer(*its_buffer), + _queue_iterator->first, + std::bind( + &udp_server_endpoint_base_impl::send_cbk, + shared_from_this(), + _queue_iterator, + std::placeholders::_1, + std::placeholders::_2 + ) + ); +} + +udp_server_endpoint_impl::endpoint_type +udp_server_endpoint_impl::get_remote() const { + return remote_; +} + +bool udp_server_endpoint_impl::get_multicast(service_t _service, event_t _event, + udp_server_endpoint_impl::endpoint_type &_target) const { + bool is_valid(false); + auto find_service = multicasts_.find(_service); + if (find_service != multicasts_.end()) { + auto find_event = find_service->second.find(_event); + if (find_event != find_service->second.end()) { + _target = find_event->second; + is_valid = true; + } + } + return is_valid; +} + +void udp_server_endpoint_impl::join(const std::string &_address) { + try { + if (local_.address().is_v4()) { + socket_.set_option( + boost::asio::ip::udp::socket::reuse_address(true)); + socket_.set_option( + boost::asio::ip::multicast::enable_loopback(false)); + socket_.set_option(boost::asio::ip::multicast::join_group( + boost::asio::ip::address::from_string(_address).to_v4())); + } else if (local_.address().is_v6()) { + socket_.set_option( + boost::asio::ip::udp::socket::reuse_address(true)); + socket_.set_option( + boost::asio::ip::multicast::enable_loopback(false)); + socket_.set_option(boost::asio::ip::multicast::join_group( + boost::asio::ip::address::from_string(_address).to_v6())); + } + } + catch (const std::exception &e) { + VSOMEIP_ERROR << e.what(); + } +} + +void udp_server_endpoint_impl::leave(const std::string &_address) { + try { + if (local_.address().is_v4()) { + socket_.set_option(boost::asio::ip::multicast::leave_group( + boost::asio::ip::address::from_string(_address))); + } else if (local_.address().is_v6()) { + socket_.set_option(boost::asio::ip::multicast::leave_group( + boost::asio::ip::address::from_string(_address))); + } + } + catch (const std::exception &e) { + VSOMEIP_ERROR << e.what(); + } +} + +void udp_server_endpoint_impl::add_multicast( + service_t _service, instance_t _instance, + const std::string &_address, uint16_t _port) { + endpoint_type its_endpoint( + boost::asio::ip::address::from_string(_address), _port); + multicasts_[_service][_instance] = its_endpoint; +} + +void udp_server_endpoint_impl::remove_multicast( + service_t _service, instance_t _instance) { + auto found_service = multicasts_.find(_service); + if (found_service != multicasts_.end()) { + auto found_instance = found_service->second.find(_instance); + if (found_instance != found_service->second.end()) { + found_service->second.erase(_instance); + } + } +} + +unsigned short udp_server_endpoint_impl::get_local_port() const { + return socket_.local_endpoint().port(); +} + +// TODO: find a better way to structure the receive functions +void udp_server_endpoint_impl::receive_cbk( + boost::system::error_code const &_error, std::size_t _bytes) { +#if 0 + std::stringstream msg; + msg << "usei::rcb(" << _error.message() << "): "; + for (std::size_t i = 0; i < _bytes + recv_buffer_size_; ++i) + msg << std::hex << std::setw(2) << std::setfill('0') + << (int) recv_buffer_[i] << " "; + VSOMEIP_DEBUG << msg.str(); +#endif + std::shared_ptr its_host = this->host_.lock(); + if (its_host) { + if (!_error && 0 < _bytes) { + recv_buffer_size_ += _bytes; + uint32_t current_message_size + = utility::get_message_size(&this->recv_buffer_[0], + (uint32_t) recv_buffer_size_); + if (current_message_size > VSOMEIP_SOMEIP_HEADER_SIZE && + current_message_size <= _bytes) { + if (utility::is_request( + recv_buffer_[VSOMEIP_MESSAGE_TYPE_POS])) { + client_t its_client; + std::memcpy(&its_client, + &recv_buffer_[VSOMEIP_CLIENT_POS_MIN], + sizeof(client_t)); + session_t its_session; + std::memcpy(&its_session, + &recv_buffer_[VSOMEIP_SESSION_POS_MIN], + sizeof(session_t)); + clients_[its_client][its_session] = remote_; + } + its_host->on_message(&recv_buffer_[0], current_message_size, this); + } else { + VSOMEIP_ERROR << "Received a unreliable vSomeIP message with bad length field"; + service_t its_service = VSOMEIP_BYTES_TO_WORD(recv_buffer_[VSOMEIP_SERVICE_POS_MIN], + recv_buffer_[VSOMEIP_SERVICE_POS_MAX]); + if (its_service != VSOMEIP_SD_SERVICE) { + its_host->on_error(&recv_buffer_[0], (uint32_t)_bytes, this); + } + } + recv_buffer_size_ = 0; + restart(); + } else { + receive(); + } + } +} + +client_t udp_server_endpoint_impl::get_client(std::shared_ptr _endpoint) { + endpoint_type endpoint(_endpoint->get_address(), _endpoint->get_port()); + for (auto its_client : clients_) { + for (auto its_session : clients_[its_client.first]) { + if (endpoint == its_session.second) { + // TODO: Check system byte order before convert! + client_t client = client_t(its_client.first << 8 | its_client.first >> 8); + return client; + } + } + } + return 0; +} + +} // namespace vsomeip diff --git a/implementation/endpoints/src/virtual_server_endpoint_impl.cpp b/implementation/endpoints/src/virtual_server_endpoint_impl.cpp new file mode 100644 index 0000000..7700874 --- /dev/null +++ b/implementation/endpoints/src/virtual_server_endpoint_impl.cpp @@ -0,0 +1,114 @@ +// Copyright (C) 2014-2015 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 "../include/virtual_server_endpoint_impl.hpp" +#include "../../logging/include/logger.hpp" + +namespace vsomeip { + +virtual_server_endpoint_impl::virtual_server_endpoint_impl( + const std::string &_address, uint16_t _port, bool _reliable) + : address_(_address), port_(_port), reliable_(_reliable), use_count_(0) { +} + +virtual_server_endpoint_impl::~virtual_server_endpoint_impl() { +} + +void virtual_server_endpoint_impl::start() { +} + +void virtual_server_endpoint_impl::stop() { +} + +bool virtual_server_endpoint_impl::is_connected() const { + return false; +} + +bool virtual_server_endpoint_impl::send(const byte_t *_data, uint32_t _size, + bool _flush) { + (void)_data; + (void)_size; + (void)_flush; + return false; +} + +bool virtual_server_endpoint_impl::send_to( + const std::shared_ptr _target, + const byte_t *_data, uint32_t _size, bool _flush) { + (void)_target; + (void)_data; + (void)_size; + (void)_flush; + return false; +} + +void virtual_server_endpoint_impl::enable_magic_cookies() { +} + +void virtual_server_endpoint_impl::receive() { +} + +void virtual_server_endpoint_impl::join(const std::string &_address) { + (void)_address; +} + +void virtual_server_endpoint_impl::leave(const std::string &_address) { + (void)_address; +} + +void virtual_server_endpoint_impl::add_multicast( + service_t _service, event_t _event, + const std::string &_address, uint16_t _port) { + (void)_service; + (void)_event; + (void)_address; + (void)_port; +} + +void virtual_server_endpoint_impl::remove_multicast( + service_t _service, event_t _event) { + (void)_service; + (void)_event; +} + +bool virtual_server_endpoint_impl::get_remote_address( + boost::asio::ip::address &_address) const { + (void)_address; + return false; +} + +unsigned short virtual_server_endpoint_impl::get_local_port() const { + return port_; +} + +unsigned short virtual_server_endpoint_impl::get_remote_port() const { + return ILLEGAL_PORT; +} + +bool virtual_server_endpoint_impl::is_reliable() const { + return reliable_; +} + +bool virtual_server_endpoint_impl::is_local() const { + return true; +} + + +void virtual_server_endpoint_impl::increment_use_count() { + use_count_++; +} + +void virtual_server_endpoint_impl::decrement_use_count() { + if (use_count_ > 0) + use_count_--; +} + +uint32_t virtual_server_endpoint_impl::get_use_count() { + return use_count_; +} + +} // namespace vsomeip diff --git a/implementation/logging/include/logger.hpp b/implementation/logging/include/logger.hpp new file mode 100644 index 0000000..555f15e --- /dev/null +++ b/implementation/logging/include/logger.hpp @@ -0,0 +1,48 @@ +// Copyright (C) 2014-2015 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_LOGGER_HPP +#define VSOMEIP_LOGGER_HPP + +#include + +#ifdef WIN32 +#include +#endif + +#include + +#include +#include + +namespace vsomeip { + +class VSOMEIP_EXPORT logger { +public: + static std::shared_ptr get(); + + virtual ~logger() { + } + + virtual boost::log::sources::severity_logger< + boost::log::trivial::severity_level> & get_internal() = 0; +}; + +#define VSOMEIP_FATAL BOOST_LOG_SEV(vsomeip::logger::get()->get_internal(), \ + boost::log::trivial::severity_level::fatal) +#define VSOMEIP_ERROR BOOST_LOG_SEV(vsomeip::logger::get()->get_internal(), \ + boost::log::trivial::severity_level::error) +#define VSOMEIP_WARNING BOOST_LOG_SEV(vsomeip::logger::get()->get_internal(), \ + boost::log::trivial::severity_level::warning) +#define VSOMEIP_INFO BOOST_LOG_SEV(vsomeip::logger::get()->get_internal(), \ + boost::log::trivial::severity_level::info) +#define VSOMEIP_DEBUG BOOST_LOG_SEV(vsomeip::logger::get()->get_internal(), \ + boost::log::trivial::severity_level::debug) +#define VSOMEIP_TRACE BOOST_LOG_SEV(vsomeip::logger::get()->get_internal(), \ + boost::log::trivial::severity_level::trace) + +} // namespace vsomeip + +#endif // VSOMEIP_LOGGER_HPP diff --git a/implementation/logging/include/logger_impl.hpp b/implementation/logging/include/logger_impl.hpp index de98f25..56c2397 100644 --- a/implementation/logging/include/logger_impl.hpp +++ b/implementation/logging/include/logger_impl.hpp @@ -14,10 +14,12 @@ #include #include -#include +#include "logger.hpp" namespace vsomeip { +class configuration; + BOOST_LOG_ATTRIBUTE_KEYWORD(channel, "Channel", std::string) BOOST_LOG_ATTRIBUTE_KEYWORD(severity, "Severity", boost::log::trivial::severity_level) @@ -28,7 +30,7 @@ typedef boost::log::sinks::synchronous_sink< class logger_impl: public logger { public: static std::shared_ptr & get(); - static void init(const std::string &_path); + static void init(const std::shared_ptr &_configuration); logger_impl(); diff --git a/implementation/logging/src/logger_impl.cpp b/implementation/logging/src/logger_impl.cpp index f354a40..ef98749 100644 --- a/implementation/logging/src/logger_impl.cpp +++ b/implementation/logging/src/logger_impl.cpp @@ -29,8 +29,8 @@ #include #endif -#include #include "../include/logger_impl.hpp" +#include "../../configuration/include/configuration.hpp" namespace logging = boost::log; namespace sources = boost::log::sources; @@ -59,19 +59,19 @@ logger_impl::get_internal() { return logger_; } -void logger_impl::init(const std::string &_path) { - configuration *its_configuration = configuration::get(_path); - get()->loglevel_ = its_configuration->get_loglevel(); +void logger_impl::init(const std::shared_ptr &_configuration) { + get()->loglevel_ = _configuration->get_loglevel(); + logging::core::get()->set_filter( logging::trivial::severity >= get()->loglevel_); - if (its_configuration->has_console_log()) + if (_configuration->has_console_log()) get()->enable_console(); - if (its_configuration->has_file_log()) - get()->enable_file(its_configuration->get_logfile()); + if (_configuration->has_file_log()) + get()->enable_file(_configuration->get_logfile()); - if (its_configuration->has_dlt_log()) + if (_configuration->has_dlt_log()) get()->enable_dlt(); } diff --git a/implementation/message/include/message_header_impl.hpp b/implementation/message/include/message_header_impl.hpp index 1d3e70b..b233d75 100644 --- a/implementation/message/include/message_header_impl.hpp +++ b/implementation/message/include/message_header_impl.hpp @@ -9,7 +9,7 @@ #include #include #include -#include +#include namespace vsomeip { @@ -20,8 +20,8 @@ public: VSOMEIP_EXPORT message_header_impl(); VSOMEIP_EXPORT message_header_impl(const message_header_impl& header); - VSOMEIP_EXPORT virtual bool serialize(serializer *_to) const; - VSOMEIP_EXPORT virtual bool deserialize(deserializer *_from); + VSOMEIP_EXPORT bool serialize(serializer *_to) const; + VSOMEIP_EXPORT bool deserialize(deserializer *_from); // internal VSOMEIP_EXPORT message_base * get_owner() const; diff --git a/implementation/message/src/deserializer.cpp b/implementation/message/src/deserializer.cpp index fb9cde6..6017d5a 100644 --- a/implementation/message/src/deserializer.cpp +++ b/implementation/message/src/deserializer.cpp @@ -9,7 +9,7 @@ #include #include -#include +#include "../../logging/include/logger.hpp" #endif #include "../include/message_impl.hpp" @@ -19,186 +19,186 @@ namespace vsomeip { deserializer::deserializer() - : position_(data_.begin()), - remaining_(0) { + : position_(data_.begin()), + remaining_(0) { } deserializer::deserializer(byte_t *_data, std::size_t _length) - : data_(_data, _data + _length), - position_(data_.begin()), - remaining_(_length) { + : data_(_data, _data + _length), + position_(data_.begin()), + remaining_(_length) { } deserializer::deserializer(const deserializer &_other) - : data_(_other.data_), - position_(_other.position_){ + : data_(_other.data_), + position_(_other.position_){ } deserializer::~deserializer() { } std::size_t deserializer::get_available() const { - return data_.size(); + return data_.size(); } std::size_t deserializer::get_remaining() const { - return remaining_; + return remaining_; } void deserializer::set_remaining(std::size_t _remaining) { - remaining_ = _remaining; + remaining_ = _remaining; } bool deserializer::deserialize(uint8_t& _value) { - if (0 == remaining_) - return false; + if (0 == remaining_) + return false; - _value = *position_++; + _value = *position_++; - remaining_--; - return true; + remaining_--; + return true; } bool deserializer::deserialize(uint16_t& _value) { - if (2 > remaining_) - return false; + if (2 > remaining_) + return false; - uint8_t byte0, byte1; - byte0 = *position_++; - byte1 = *position_++; - remaining_ -= 2; + uint8_t byte0, byte1; + byte0 = *position_++; + byte1 = *position_++; + remaining_ -= 2; - _value = VSOMEIP_BYTES_TO_WORD(byte0, byte1); + _value = VSOMEIP_BYTES_TO_WORD(byte0, byte1); - return true; + return true; } bool deserializer::deserialize(uint32_t &_value, bool _omit_last_byte) { - if (3 > remaining_ || (!_omit_last_byte && 4 > remaining_)) - return false; + if (3 > remaining_ || (!_omit_last_byte && 4 > remaining_)) + return false; - uint8_t byte0 = 0, byte1, byte2, byte3; - if (!_omit_last_byte) { - byte0 = *position_++; - remaining_--; - } - byte1 = *position_++; - byte2 = *position_++; - byte3 = *position_++; - remaining_ -= 3; + uint8_t byte0 = 0, byte1, byte2, byte3; + if (!_omit_last_byte) { + byte0 = *position_++; + remaining_--; + } + byte1 = *position_++; + byte2 = *position_++; + byte3 = *position_++; + remaining_ -= 3; - _value = VSOMEIP_BYTES_TO_LONG( - byte0, byte1, byte2, byte3); + _value = VSOMEIP_BYTES_TO_LONG( + byte0, byte1, byte2, byte3); - return true; + return true; } bool deserializer::deserialize(uint8_t *_data, std::size_t _length) { - if (_length > remaining_) - return false; + if (_length > remaining_) + return false; - std::memcpy(_data, &data_[position_ - data_.begin()], _length); - position_ += _length; - remaining_ -= _length; + std::memcpy(_data, &data_[position_ - data_.begin()], _length); + position_ += _length; + remaining_ -= _length; - return true; + return true; } bool deserializer::deserialize(std::vector< uint8_t >& _value) { - if (_value.capacity() > remaining_) - return false; + if (_value.capacity() > remaining_) + return false; - _value.assign(position_, position_ + _value.capacity()); - position_ += _value.capacity(); - remaining_ -= _value.capacity(); + _value.assign(position_, position_ + _value.capacity()); + position_ += _value.capacity(); + remaining_ -= _value.capacity(); - return true; + return true; } bool deserializer::look_ahead(std::size_t _index, uint8_t &_value) const { - if (_index >= data_.size()) - return false; + if (_index >= data_.size()) + return false; - _value = *(position_ + _index); + _value = *(position_ + _index); - return true; + return true; } bool deserializer::look_ahead(std::size_t _index, uint16_t &_value) const { - if (_index+1 >= data_.size()) - return false; + if (_index+1 >= data_.size()) + return false; - std::vector< uint8_t >::iterator i = position_ + _index; - _value = VSOMEIP_BYTES_TO_WORD(*i, *(i+1)); + std::vector< uint8_t >::iterator i = position_ + _index; + _value = VSOMEIP_BYTES_TO_WORD(*i, *(i+1)); - return true; + return true; } bool deserializer::look_ahead(std::size_t _index, uint32_t &_value) const { - if (_index+3 >= data_.size()) - return false; + if (_index+3 >= data_.size()) + return false; - std::vector< uint8_t >::const_iterator i = position_ + _index; - _value = VSOMEIP_BYTES_TO_LONG(*i, *(i+1), *(i+2), *(i+3)); + std::vector< uint8_t >::const_iterator i = position_ + _index; + _value = VSOMEIP_BYTES_TO_LONG(*i, *(i+1), *(i+2), *(i+3)); - return true; + return true; } message * deserializer::deserialize_message() { - message_impl* deserialized_message = new message_impl; - if (0 != deserialized_message) { - if (false == deserialized_message->deserialize(this)) { - delete deserialized_message; - deserialized_message = 0; - } - } + message_impl* deserialized_message = new message_impl; + if (0 != deserialized_message) { + if (false == deserialized_message->deserialize(this)) { + delete deserialized_message; + deserialized_message = 0; + } + } - return deserialized_message; + return deserialized_message; } void deserializer::set_data(const byte_t *_data, std::size_t _length) { - if (0 != _data) { - data_.assign(_data, _data + _length); - position_ = data_.begin(); - remaining_ = data_.end() - position_; - } else { - data_.clear(); - position_ = data_.end(); - remaining_ = 0; - } + if (0 != _data) { + data_.assign(_data, _data + _length); + position_ = data_.begin(); + remaining_ = data_.end() - position_; + } else { + data_.clear(); + position_ = data_.end(); + remaining_ = 0; + } } void deserializer::append_data(const byte_t *_data, std::size_t _length) { - std::size_t offset = (position_ - data_.begin()); - data_.insert(data_.end(), _data, _data + _length); - position_ = data_.begin() + offset; - remaining_ += _length; + std::size_t offset = (position_ - data_.begin()); + data_.insert(data_.end(), _data, _data + _length); + position_ = data_.begin() + offset; + remaining_ += _length; } void deserializer::drop_data(std::size_t _length) { - if (position_ + _length < data_.end()) - position_ += _length; - else - position_ = data_.end(); + if (position_ + _length < data_.end()) + position_ += _length; + else + position_ = data_.end(); } void deserializer::reset() { - data_.erase(data_.begin(), position_); - position_ = data_.begin(); - remaining_ = data_.size(); + data_.erase(data_.begin(), position_); + position_ = data_.begin(); + remaining_ = data_.size(); } #ifdef VSOMEIP_DEBUGGING void deserializer::show() const { - std::stringstream its_message; - its_message << "(" - << std::hex << std::setw(2) << std::setfill('0') - << (int)*position_ << ", " - << std:: dec << remaining_ << ") "; - for (int i = 0; i < data_.size(); ++i) - its_message << std::hex << std::setw(2) << std::setfill('0') - << (int)data_[i] << " "; - VSOMEIP_DEBUG << its_message; + std::stringstream its_message; + its_message << "(" + << std::hex << std::setw(2) << std::setfill('0') + << (int)*position_ << ", " + << std:: dec << remaining_ << ") "; + for (int i = 0; i < data_.size(); ++i) + its_message << std::hex << std::setw(2) << std::setfill('0') + << (int)data_[i] << " "; + VSOMEIP_DEBUG << its_message; } #endif diff --git a/implementation/message/src/message_base_impl.cpp b/implementation/message/src/message_base_impl.cpp index c5ab95a..616ed63 100644 --- a/implementation/message/src/message_base_impl.cpp +++ b/implementation/message/src/message_base_impl.cpp @@ -10,7 +10,7 @@ namespace vsomeip { message_base_impl::message_base_impl() : is_reliable_(false) { - header_.set_owner(this); + header_.set_owner(this); } message_base_impl::~message_base_impl() { @@ -18,88 +18,88 @@ message_base_impl::~message_base_impl() { // header interface message_t message_base_impl::get_message() const { - return VSOMEIP_WORDS_TO_LONG(header_.service_, header_.method_); + return VSOMEIP_WORDS_TO_LONG(header_.service_, header_.method_); } void message_base_impl::set_message(message_t _message) { - header_.service_ = VSOMEIP_LONG_WORD0(_message); - header_.method_ = VSOMEIP_LONG_WORD1(_message); + header_.service_ = VSOMEIP_LONG_WORD0(_message); + header_.method_ = VSOMEIP_LONG_WORD1(_message); } service_t message_base_impl::get_service() const { - return header_.service_; + return header_.service_; } void message_base_impl::set_service(service_t _service) { - header_.service_ = _service; + header_.service_ = _service; } instance_t message_base_impl::get_instance() const { - return header_.instance_; + return header_.instance_; } void message_base_impl::set_instance(instance_t _instance) { - header_.instance_ = _instance; + header_.instance_ = _instance; } method_t message_base_impl::get_method() const { - return header_.method_; + return header_.method_; } void message_base_impl::set_method(method_t _method) { - header_.method_ = _method; + header_.method_ = _method; } request_t message_base_impl::get_request() const { - return VSOMEIP_WORDS_TO_LONG(header_.client_, header_.session_); + return VSOMEIP_WORDS_TO_LONG(header_.client_, header_.session_); } client_t message_base_impl::get_client() const { - return header_.client_; + return header_.client_; } void message_base_impl::set_client(client_t _client) { - header_.client_ = _client; + header_.client_ = _client; } session_t message_base_impl::get_session() const { - return header_.session_; + return header_.session_; } void message_base_impl::set_session(session_t _session) { - header_.session_ = _session; + header_.session_ = _session; } protocol_version_t message_base_impl::get_protocol_version() const { - return header_.protocol_version_; + return header_.protocol_version_; } void message_base_impl::set_protocol_version(protocol_version_t _protocol_version) { - header_.protocol_version_ = _protocol_version; + header_.protocol_version_ = _protocol_version; } interface_version_t message_base_impl::get_interface_version() const { - return header_.interface_version_; + return header_.interface_version_; } void message_base_impl::set_interface_version(interface_version_t _interface_version) { - header_.interface_version_ = _interface_version; + header_.interface_version_ = _interface_version; } message_type_e message_base_impl::get_message_type() const { - return header_.type_; + return header_.type_; } void message_base_impl::set_message_type(message_type_e _type) { - header_.type_ = _type; + header_.type_ = _type; } return_code_e message_base_impl::get_return_code() const { - return header_.code_; + return header_.code_; } void message_base_impl::set_return_code(return_code_e _code) { - header_.code_ = _code; + header_.code_ = _code; } bool message_base_impl::is_reliable() const { diff --git a/implementation/message/src/message_header_impl.cpp b/implementation/message/src/message_header_impl.cpp index 1bde36c..39446b7 100644 --- a/implementation/message/src/message_header_impl.cpp +++ b/implementation/message/src/message_header_impl.cpp @@ -13,66 +13,69 @@ namespace vsomeip { message_header_impl::message_header_impl() - : service_(0x0), instance_(0x0), method_(0x0), - client_(0x0), session_(0x0), - protocol_version_(0x1), interface_version_(0x0), - type_(message_type_e::MT_UNKNOWN), - code_(return_code_e::E_UNKNOWN) { + : service_(0x0), method_(0x0), + client_(0x0), session_(0x0), + protocol_version_(0x1), interface_version_(0x0), + type_(message_type_e::MT_UNKNOWN), + code_(return_code_e::E_UNKNOWN), + instance_(0x0) { }; -message_header_impl::message_header_impl(const message_header_impl& _header) - : service_(_header.service_), instance_(_header.instance_), method_(_header.method_), - client_(_header.client_), session_(_header.session_), - protocol_version_(_header.protocol_version_), interface_version_(_header.interface_version_), - type_(_header.type_), - code_(_header.code_) { +message_header_impl::message_header_impl(const message_header_impl &_header) + : service_(_header.service_), method_(_header.method_), + client_(_header.client_), session_(_header.session_), + protocol_version_(_header.protocol_version_), + interface_version_(_header.interface_version_), + type_(_header.type_), + code_(_header.code_), + instance_(_header.instance_) { }; bool message_header_impl::serialize(serializer *_to) const { - return (0 != _to - && _to->serialize(service_) - && _to->serialize(method_) - && _to->serialize(owner_->get_length()) - && _to->serialize(client_) - && _to->serialize(session_) - && _to->serialize(protocol_version_) - && _to->serialize(interface_version_) - && _to->serialize(static_cast(type_)) - && _to->serialize(static_cast(code_))); + return (0 != _to + && _to->serialize(service_) + && _to->serialize(method_) + && _to->serialize(owner_->get_length()) + && _to->serialize(client_) + && _to->serialize(session_) + && _to->serialize(protocol_version_) + && _to->serialize(interface_version_) + && _to->serialize(static_cast(type_)) + && _to->serialize(static_cast(code_))); }; bool message_header_impl::deserialize(deserializer *_from) { - bool is_successful; + bool is_successful; - uint8_t tmp_message_type, tmp_return_code; - uint32_t tmp_length; + uint8_t tmp_message_type, tmp_return_code; + uint32_t tmp_length; - is_successful = (0 != _from - && _from->deserialize(service_) - && _from->deserialize(method_) - && _from->deserialize(tmp_length) - && _from->deserialize(client_) - && _from->deserialize(session_) - && _from->deserialize(protocol_version_) - && _from->deserialize(interface_version_) - && _from->deserialize(tmp_message_type) - && _from->deserialize(tmp_return_code)); + is_successful = (0 != _from + && _from->deserialize(service_) + && _from->deserialize(method_) + && _from->deserialize(tmp_length) + && _from->deserialize(client_) + && _from->deserialize(session_) + && _from->deserialize(protocol_version_) + && _from->deserialize(interface_version_) + && _from->deserialize(tmp_message_type) + && _from->deserialize(tmp_return_code)); - if (is_successful) { - type_ = static_cast< message_type_e >(tmp_message_type); - code_ = static_cast< return_code_e >(tmp_return_code); - length_ = static_cast< length_t >(tmp_length - VSOMEIP_SOMEIP_HEADER_SIZE); - } + if (is_successful) { + type_ = static_cast< message_type_e >(tmp_message_type); + code_ = static_cast< return_code_e >(tmp_return_code); + length_ = static_cast< length_t >(tmp_length - VSOMEIP_SOMEIP_HEADER_SIZE); + } - return is_successful; + return is_successful; }; message_base * message_header_impl::get_owner() const { - return owner_; + return owner_; } void message_header_impl::set_owner(message_base *_owner) { - owner_ = _owner; + owner_ = _owner; } } // namespace vsomeip diff --git a/implementation/message/src/message_impl.cpp b/implementation/message/src/message_impl.cpp index 51596a0..c19ae76 100644 --- a/implementation/message/src/message_impl.cpp +++ b/implementation/message/src/message_impl.cpp @@ -20,31 +20,31 @@ message_impl::~message_impl() { } length_t message_impl::get_length() const { - return (VSOMEIP_SOMEIP_HEADER_SIZE - + (payload_ ? payload_->get_length() : 0)); + return (VSOMEIP_SOMEIP_HEADER_SIZE + + (payload_ ? payload_->get_length() : 0)); } std::shared_ptr< payload > message_impl::get_payload() const { - return payload_; + return payload_; } void message_impl::set_payload(std::shared_ptr< payload > _payload) { - payload_ = _payload; + payload_ = _payload; } bool message_impl::serialize(serializer *_to) const { - return (header_.serialize(_to) - && (payload_ ? payload_->serialize(_to) : true)); + return (header_.serialize(_to) + && (payload_ ? payload_->serialize(_to) : true)); } bool message_impl::deserialize(deserializer *_from) { - payload_ = runtime::get()->create_payload(); - bool is_successful = header_.deserialize(_from); - if (is_successful) { - payload_->set_capacity(header_.length_); - is_successful = payload_->deserialize(_from); - } - return is_successful; + payload_ = runtime::get()->create_payload(); + bool is_successful = header_.deserialize(_from); + if (is_successful) { + payload_->set_capacity(header_.length_); + is_successful = payload_->deserialize(_from); + } + return is_successful; } } // namespace vsomeip diff --git a/implementation/message/src/payload_impl.cpp b/implementation/message/src/payload_impl.cpp index 62e48e0..3355788 100644 --- a/implementation/message/src/payload_impl.cpp +++ b/implementation/message/src/payload_impl.cpp @@ -10,66 +10,66 @@ namespace vsomeip { payload_impl::payload_impl() - : data_() { + : data_() { } payload_impl::payload_impl(const byte_t *_data, uint32_t _size) { - data_.assign(_data, _data + _size); + data_.assign(_data, _data + _size); } payload_impl::payload_impl(const std::vector &_data) - : data_(_data) { + : data_(_data) { } payload_impl::payload_impl(const payload_impl& _payload) - : data_(_payload.data_) { + : data_(_payload.data_) { } payload_impl::~payload_impl() { } bool payload_impl::operator==(const payload &_other) { - bool is_equal(true); - try { - const payload_impl &other = dynamic_cast< const payload_impl & >(_other); - is_equal = (data_ == other.data_); - } - catch (...) { - is_equal = false; - } - return is_equal; + bool is_equal(true); + try { + const payload_impl &other = dynamic_cast< const payload_impl & >(_other); + is_equal = (data_ == other.data_); + } + catch (...) { + is_equal = false; + } + return is_equal; } byte_t * payload_impl::get_data() { - return data_.data(); + return data_.data(); } const byte_t * payload_impl::get_data() const { - return data_.data(); + return data_.data(); } length_t payload_impl::get_length() const { - return data_.size(); + return length_t(data_.size()); } void payload_impl::set_capacity(length_t _capacity) { - data_.reserve(_capacity); + data_.reserve(_capacity); } void payload_impl::set_data(const byte_t *_data, const length_t _length) { - data_.assign(_data, _data + _length); + data_.assign(_data, _data + _length); } void payload_impl::set_data(const std::vector< byte_t > &_data) { - data_ = _data; + data_ = _data; } bool payload_impl::serialize(serializer *_to) const { - return (0 != _to && _to->serialize(data_.data(), data_.size())); + return (0 != _to && _to->serialize(data_.data(), uint32_t(data_.size()))); } bool payload_impl::deserialize(deserializer *_from) { - return (0 != _from && _from->deserialize(data_)); + return (0 != _from && _from->deserialize(data_)); } } // namespace vsomeip diff --git a/implementation/message/src/serializer.cpp b/implementation/message/src/serializer.cpp index cfa32ec..6c064ab 100644 --- a/implementation/message/src/serializer.cpp +++ b/implementation/message/src/serializer.cpp @@ -9,10 +9,10 @@ #include #include -#include +#include "../../logging/include/logger.hpp" #endif -#include +#include #include "../include/serializer.hpp" #include "../../utility/include/byteorder.hpp" @@ -20,115 +20,117 @@ namespace vsomeip { serializer::serializer() - : data_(0), capacity_(0), position_(0), remaining_(0) { + : data_(0), capacity_(0), position_(0), remaining_(0) { } serializer::~serializer() { + if (0 != data_) + delete [] data_; }; bool serializer::serialize(const serializable *_from) { - return (_from && _from->serialize(this)); + return (_from && _from->serialize(this)); } bool serializer::serialize(const uint8_t _value) { - if (1 > remaining_) - return false; + if (1 > remaining_) + return false; - *position_++ = _value; - remaining_--; + *position_++ = _value; + remaining_--; - return true; + return true; } bool serializer::serialize(const uint16_t _value) { - if (2 > remaining_) - return false; + if (2 > remaining_) + return false; - *position_++ = VSOMEIP_WORD_BYTE1(_value); - *position_++ = VSOMEIP_WORD_BYTE0(_value); - remaining_ -= 2; + *position_++ = VSOMEIP_WORD_BYTE1(_value); + *position_++ = VSOMEIP_WORD_BYTE0(_value); + remaining_ -= 2; - return true; + return true; } bool serializer::serialize(const uint32_t _value, bool _omit_last_byte) { - if (3 > remaining_ || (!_omit_last_byte && 4 > remaining_)) - return false; - - if (!_omit_last_byte) { - *position_++ = VSOMEIP_LONG_BYTE3(_value); - remaining_--; - } - *position_++ = VSOMEIP_LONG_BYTE2(_value); - *position_++ = VSOMEIP_LONG_BYTE1(_value); - *position_++ = VSOMEIP_LONG_BYTE0(_value); - remaining_ -= 3; - - return true; + if (3 > remaining_ || (!_omit_last_byte && 4 > remaining_)) + return false; + + if (!_omit_last_byte) { + *position_++ = VSOMEIP_LONG_BYTE3(_value); + remaining_--; + } + *position_++ = VSOMEIP_LONG_BYTE2(_value); + *position_++ = VSOMEIP_LONG_BYTE1(_value); + *position_++ = VSOMEIP_LONG_BYTE0(_value); + remaining_ -= 3; + + return true; } bool serializer::serialize(const uint8_t *_data, uint32_t _length) { - if (_length > remaining_) - return false; + if (_length > remaining_) + return false; - ::memcpy(position_, _data, _length); - position_ += _length; - remaining_ -= _length; + ::memcpy(position_, _data, _length); + position_ += _length; + remaining_ -= _length; - return true; + return true; } byte_t * serializer::get_data() const { - return data_; + return data_; } uint32_t serializer::get_capacity() const { - return capacity_; + return capacity_; } uint32_t serializer::get_size() const { - return capacity_ - remaining_; + return capacity_ - remaining_; } void serializer::create_data(uint32_t _capacity) { - if (0 != data_) - delete [] data_; - - data_ = new byte_t[_capacity]; - position_ = data_; - if (0 != data_) { - capacity_ = remaining_ = _capacity; - } else { - capacity_ = remaining_ = 0; - } + if (0 != data_) + delete [] data_; + + data_ = new byte_t[_capacity]; + position_ = data_; + if (0 != data_) { + capacity_ = remaining_ = _capacity; + } else { + capacity_ = remaining_ = 0; + } } void serializer::set_data(byte_t *_data, uint32_t _capacity) { - delete [] data_; + delete [] data_; - data_ = _data; - position_ = _data; + data_ = _data; + position_ = _data; - if (0 != data_) { - capacity_ = remaining_ = _capacity; - } else { - capacity_ = remaining_ = 0; - } + if (0 != data_) { + capacity_ = remaining_ = _capacity; + } else { + capacity_ = remaining_ = 0; + } } void serializer::reset() { - position_ = data_; - remaining_ = capacity_; + position_ = data_; + remaining_ = capacity_; } #ifdef VSOMEIP_DEBUGGING void serializer::show() { - std::stringstream its_data; - its_data << "SERIALIZED: "; - for (int i = 0; i < position_ - data_; ++i) - its_data << std::setw(2) << std::setfill('0') - << std::hex << (int)data_[i]; - VSOMEIP_DEBUG << its_data.str(); + std::stringstream its_data; + its_data << "SERIALIZED: "; + for (int i = 0; i < position_ - data_; ++i) + its_data << std::setw(2) << std::setfill('0') + << std::hex << (int)data_[i]; + VSOMEIP_DEBUG << its_data.str(); } #endif diff --git a/implementation/routing/include/event.hpp b/implementation/routing/include/event.hpp index 7332c9a..89153ad 100644 --- a/implementation/routing/include/event.hpp +++ b/implementation/routing/include/event.hpp @@ -54,6 +54,9 @@ public: bool is_reliable() const; void set_reliable(bool _is_reliable); + bool is_provided() const; + void set_provided(bool _is_provided); + // SIP_RPC_357 void set_update_cycle(std::chrono::milliseconds &_cycle); @@ -69,6 +72,9 @@ public: void notify_one(const std::shared_ptr &_target); void notify_one(client_t _client); + void add_ref(); + uint32_t remove_ref(); + private: void update_cbk(boost::system::error_code const &_error); void notify(); @@ -91,6 +97,9 @@ private: std::set eventgroups_; bool is_set_; + bool is_provided_; + + uint32_t ref_; }; } // namespace vsomeip diff --git a/implementation/routing/include/eventgroupinfo.hpp b/implementation/routing/include/eventgroupinfo.hpp index 558c3b9..08536e0 100644 --- a/implementation/routing/include/eventgroupinfo.hpp +++ b/implementation/routing/include/eventgroupinfo.hpp @@ -39,11 +39,12 @@ public: VSOMEIP_EXPORT const std::set > get_events() const; VSOMEIP_EXPORT void add_event(std::shared_ptr _event); + VSOMEIP_EXPORT void remove_event(std::shared_ptr _event); VSOMEIP_EXPORT const std::set< std::shared_ptr > get_targets() const; - VSOMEIP_EXPORT void add_target(std::shared_ptr _target); - VSOMEIP_EXPORT void del_target(std::shared_ptr _target); + VSOMEIP_EXPORT bool add_target(std::shared_ptr _target); + VSOMEIP_EXPORT bool remove_target(std::shared_ptr _target); VSOMEIP_EXPORT void clear_targets(); private: diff --git a/implementation/routing/include/routing_manager.hpp b/implementation/routing/include/routing_manager.hpp index 44a63ac..7791add 100644 --- a/implementation/routing/include/routing_manager.hpp +++ b/implementation/routing/include/routing_manager.hpp @@ -36,21 +36,21 @@ public: virtual void offer_service(client_t _client, service_t _service, instance_t _instance, major_version_t _major, - minor_version_t _minor, ttl_t _ttl) = 0; + minor_version_t _minor) = 0; virtual void stop_offer_service(client_t _client, service_t _service, instance_t _instance) = 0; virtual void request_service(client_t _client, service_t _service, instance_t _instance, major_version_t _major, - minor_version_t _minor, ttl_t _ttl, bool _has_selective) = 0; + minor_version_t _minor, bool _use_exclusive_proxy) = 0; virtual void release_service(client_t _client, service_t _service, instance_t _instance) = 0; virtual void subscribe(client_t _client, service_t _service, instance_t _instance, eventgroup_t _eventgroup, - major_version_t _major, ttl_t _ttl) = 0; + major_version_t _major) = 0; virtual void unsubscribe(client_t _client, service_t _service, instance_t _instance, eventgroup_t _eventgroup) = 0; @@ -67,6 +67,13 @@ public: virtual bool send_to(const std::shared_ptr &_target, const byte_t *_data, uint32_t _size) = 0; + virtual void register_event(client_t _client, service_t _service, instance_t _instance, + event_t _event, std::set _eventgroups, + bool _is_field, bool _is_provided) = 0; + + virtual void unregister_event(client_t _client, service_t _service, instance_t _instance, + event_t _event, bool _is_provided) = 0; + virtual void notify(service_t _service, instance_t _instance, event_t _event, std::shared_ptr _payload) = 0; diff --git a/implementation/routing/include/routing_manager_host.hpp b/implementation/routing/include/routing_manager_host.hpp index a80b86d..7b96be0 100644 --- a/implementation/routing/include/routing_manager_host.hpp +++ b/implementation/routing/include/routing_manager_host.hpp @@ -29,7 +29,7 @@ public: virtual void on_availability(service_t _service, instance_t _instance, bool _is_available) const = 0; - virtual void on_event(event_type_e _event) = 0; + virtual void on_state(state_type_e _state) = 0; virtual void on_message(std::shared_ptr _message) = 0; virtual void on_error(error_code_e _error) = 0; virtual bool on_subscription(service_t _service, instance_t _instance, eventgroup_t _eventgroup, diff --git a/implementation/routing/include/routing_manager_impl.hpp b/implementation/routing/include/routing_manager_impl.hpp index b2d5200..a0d692c 100644 --- a/implementation/routing/include/routing_manager_impl.hpp +++ b/implementation/routing/include/routing_manager_impl.hpp @@ -63,20 +63,20 @@ public: void offer_service(client_t _client, service_t _service, instance_t _instance, major_version_t _major, - minor_version_t _minor, ttl_t _ttl); + minor_version_t _minor); void stop_offer_service(client_t _client, service_t _service, instance_t _instance); void request_service(client_t _client, service_t _service, instance_t _instance, major_version_t _major, - minor_version_t _minor, ttl_t _ttl, bool _has_selective); + minor_version_t _minor, bool _use_exclusive_proxy); void release_service(client_t _client, service_t _service, instance_t _instance); void subscribe(client_t _client, service_t _service, instance_t _instance, - eventgroup_t _eventgroup, major_version_t _major, ttl_t _ttl); + eventgroup_t _eventgroup, major_version_t _major); void unsubscribe(client_t _client, service_t _service, instance_t _instance, eventgroup_t _eventgroup); @@ -92,6 +92,15 @@ public: bool send_to(const std::shared_ptr &_target, const byte_t *_data, uint32_t _size); + void register_event(client_t _client, service_t _service, + instance_t _instance, event_t _event, + std::set _eventgroups, + bool _is_field, bool _is_provided); + + void unregister_event(client_t _client, service_t _service, + instance_t _instance, event_t _event, + bool _is_provided); + void notify(service_t _service, instance_t _instance, event_t _event, std::shared_ptr _payload); @@ -113,25 +122,31 @@ public: bool _reliable, client_t _client); void on_connect(std::shared_ptr _endpoint); void on_disconnect(std::shared_ptr _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); 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, + instance_t _instance, const byte_t *_data, length_t _size); // interface "service_discovery_host" typedef std::map > servicegroups_t; const servicegroups_t & get_servicegroups() const; std::shared_ptr find_eventgroup(service_t _service, instance_t _instance, eventgroup_t _eventgroup) const; - services_t get_offered_services(const std::string &_name) const; - void create_service_discovery_endpoint(const std::string &_address, + services_t get_offered_services() const; + std::shared_ptr create_service_discovery_endpoint(const std::string &_address, uint16_t _port, bool _reliable); void init_routing_info(); void add_routing_info(service_t _service, instance_t _instance, major_version_t _major, minor_version_t _minor, ttl_t _ttl, - const boost::asio::ip::address &_address, uint16_t _port, - bool _reliable); + const boost::asio::ip::address &_reliable_address, + uint16_t _reliable_port, + const boost::asio::ip::address &_unreliable_address, + uint16_t _unreliable_port); void del_routing_info(service_t _service, instance_t _instance, - bool _reliable); + bool _has_reliable, bool _has_unreliable); + ttl_t update_routing_info(ttl_t _elapsed); void on_subscribe(service_t _service, instance_t _instance, eventgroup_t _eventgroup, @@ -143,11 +158,11 @@ public: void on_subscribe_ack(service_t _service, instance_t _instance, const boost::asio::ip::address &_address, uint16_t _port); - void init_event_routing_info(); - private: bool deliver_message(const byte_t *_data, length_t _length, instance_t _instance, bool _reliable); + bool deliver_notification(service_t _service, instance_t _instance, + const byte_t *_data, length_t _length, bool _reliable); bool send_local( std::shared_ptr &_target, client_t _client, const byte_t *_data, uint32_t _size, instance_t _instance, @@ -160,56 +175,71 @@ private: std::shared_ptr find_service(service_t _service, instance_t _instance) const; - std::shared_ptr create_service(service_t _service, + std::shared_ptr create_service_info(service_t _service, instance_t _instance, major_version_t _major, - minor_version_t _minor, ttl_t _ttl); + minor_version_t _minor, ttl_t _ttl, bool _is_local_service); std::shared_ptr create_client_endpoint( const boost::asio::ip::address &_address, uint16_t _port, - bool _reliable, client_t _client); - std::shared_ptr find_client_endpoint( - const boost::asio::ip::address &_address, uint16_t _port, - bool _reliable, client_t _client); - std::shared_ptr find_or_create_client_endpoint( - const boost::asio::ip::address &_address, uint16_t _port, - bool _reliable, client_t _client); + bool _reliable, client_t _client, bool _start); + + void remove_eventgroup_info(service_t _service, instance_t _instance, + eventgroup_t _eventgroup); std::shared_ptr create_server_endpoint(uint16_t _port, - bool _reliable); + bool _reliable, bool _start); std::shared_ptr find_server_endpoint(uint16_t _port, - bool _reliable); + bool _reliable); std::shared_ptr find_or_create_server_endpoint(uint16_t _port, - bool _reliable); + bool _reliable, bool _start); std::set > find_events(service_t _service, instance_t _instance, eventgroup_t _eventgroup); std::shared_ptr find_event(service_t _service, instance_t _instance, event_t _event) const; + bool is_field(service_t _service, instance_t _instance, + event_t _event) const; std::shared_ptr find_remote_client(service_t _service, - instance_t _instance, - bool _reliable, client_t _client); + instance_t _instance, bool _reliable, client_t _client); std::shared_ptr create_remote_client(service_t _service, - instance_t _instance, - bool _reliable, client_t _client); + instance_t _instance, bool _reliable, client_t _client); + + bool deliver_specific_endpoint_message(service_t _service, instance_t _instance, + const byte_t *_data, length_t _size, endpoint *_receiver); + + void clear_client_endpoints(service_t _service, instance_t _instance, bool _reliable); + void stop_and_delete_client_endpoint(std::shared_ptr _endpoint); + void clear_multicast_endpoints(service_t _service, instance_t _instance); + void clear_service_info(service_t _service, instance_t _instance, bool _reliable); private: void send_subscribe(client_t _client, service_t _service, instance_t _instance, eventgroup_t _eventgroup, - major_version_t _major, ttl_t _ttl); + major_version_t _major); void send_unsubscribe(client_t _client, service_t _service, instance_t _instance, eventgroup_t _eventgroup); - boost::asio::io_service &io_; - routing_manager_host *host_; + bool insert_subscription(service_t _service, instance_t _instance, + eventgroup_t _eventgroup, client_t _client); - std::shared_ptr configuration_; + return_code_e check_error(const byte_t *_data, length_t _size, + instance_t _instance); + + void send_error(return_code_e _return_code, const byte_t *_data, + length_t _size, instance_t _instance, bool _reliable, + endpoint *_receiver); + + routing_manager_host *host_; + boost::asio::io_service &io_; std::shared_ptr deserializer_; std::shared_ptr serializer_; + std::shared_ptr configuration_; + std::shared_ptr stub_; std::shared_ptr discovery_; @@ -223,15 +253,20 @@ private: std::map > > server_endpoints_; std::map > service_instances_; + // Multicast endpoint info (notifications) + std::map > > multicast_info; + // Client endpoints for remote services - std::map > > > > client_endpoints_; + std::map > > > remote_service_info_; + std::map > > > >remote_services_; + std::map > > > client_endpoints_by_ip_; - // Servicegroups - std::map > servicegroups_; - std::map > > services_; + // Services + services_t services_; // Eventgroups std::map> remote_subscriber_map_; diff --git a/implementation/routing/include/routing_manager_proxy.hpp b/implementation/routing/include/routing_manager_proxy.hpp index a142db8..852ca19 100644 --- a/implementation/routing/include/routing_manager_proxy.hpp +++ b/implementation/routing/include/routing_manager_proxy.hpp @@ -39,20 +39,20 @@ public: void offer_service(client_t _client, service_t _service, instance_t _instance, major_version_t _major, - minor_version_t _minor, ttl_t _ttl); + minor_version_t _minor); void stop_offer_service(client_t _client, service_t _service, instance_t _instance); void request_service(client_t _client, service_t _service, instance_t _instance, major_version_t _major, - minor_version_t _minor, ttl_t _ttl, bool _has_selective); + minor_version_t _minor, bool _use_exclusive_proxy); void release_service(client_t _client, service_t _service, instance_t _instance); void subscribe(client_t _client, service_t _service, instance_t _instance, - eventgroup_t _eventgroup, major_version_t _major, ttl_t _ttl); + eventgroup_t _eventgroup, major_version_t _major); void unsubscribe(client_t _client, service_t _service, instance_t _instance, eventgroup_t _eventgroup); @@ -68,15 +68,26 @@ public: bool send_to(const std::shared_ptr &_target, const byte_t *_data, uint32_t _size); + void register_event(client_t _client, service_t _service, + instance_t _instance, event_t _event, + std::set _eventgroups, + bool _is_field, bool _is_provided); + + void unregister_event(client_t _client, service_t _service, + instance_t _instance, event_t _event, + bool _is_provided); + void notify(service_t _service, instance_t _instance, event_t _event, std::shared_ptr _payload); void notify_one(service_t _service, instance_t _instance, - event_t _event, std::shared_ptr _payload, client_t _client); + event_t _event, std::shared_ptr _payload, + client_t _client); void on_connect(std::shared_ptr _endpoint); void on_disconnect(std::shared_ptr _endpoint); void on_message(const byte_t *_data, length_t _length, endpoint *_receiver); + void on_error(const byte_t *_data, length_t _length, endpoint *_receiver); void on_routing_info(const byte_t *_data, uint32_t _size); @@ -95,36 +106,47 @@ private: void send_pong() const; void send_offer_service(client_t _client, service_t _service, instance_t _instance, major_version_t _major, - minor_version_t _minor, ttl_t _ttl); + minor_version_t _minor); + void send_request_service(client_t _client, service_t _service, + instance_t _instance, major_version_t _major, + minor_version_t _minor, bool _use_exclusive_proxy); + void send_register_event(client_t _client, service_t _service, + instance_t _instance, event_t _event, + std::set _eventgroup, + bool _is_field, bool _is_provided); void send_subscribe(client_t _client, service_t _service, instance_t _instance, eventgroup_t _eventgroup, - major_version_t _major, ttl_t _ttl); + major_version_t _major); - void send_request_service(client_t _client, service_t _service, - instance_t _instance, major_version_t _major, - minor_version_t _minor, ttl_t _ttl, bool _is_selective); + bool is_field(service_t _service, instance_t _instance, + event_t _event) const; private: - boost::asio::io_service &io_;bool is_connected_;bool is_started_; - event_type_e state_; + boost::asio::io_service &io_; + bool is_connected_; + bool is_started_; + state_type_e state_; routing_manager_host *host_; client_t client_; // store locally as it is needed in each message + std::shared_ptr configuration_; + std::shared_ptr serializer_; std::shared_ptr deserializer_; - std::shared_ptr sender_; // --> stub + std::shared_ptr sender_; // --> stub std::shared_ptr receiver_; // --> from everybody std::map > local_endpoints_; std::map > local_services_; + std::mutex local_services_mutex_; struct service_data_t { service_t service_; instance_t instance_; major_version_t major_; minor_version_t minor_; - ttl_t ttl_; + bool use_exclusive_proxy_; // only used for requests! bool operator<(const service_data_t &_other) const { return (service_ < _other.service_ @@ -135,12 +157,30 @@ private: std::set pending_offers_; std::set pending_requests_; + struct event_data_t { + service_t service_; + instance_t instance_; + event_t event_; + bool is_field_; + bool is_provided_; + std::set eventgroups_; + + bool operator<(const event_data_t &_other) const { + return (service_ < _other.service_ + || (service_ == _other.service_ + && instance_ < _other.instance_) + || (service_ == _other.service_ + && instance_ == _other.instance_ + && event_ < _other.event_)); + } + }; + std::set pending_event_registrations_; + struct eventgroup_data_t { service_t service_; instance_t instance_; eventgroup_t eventgroup_; major_version_t major_; - ttl_t ttl_; bool operator<(const eventgroup_data_t &_other) const { return (service_ < _other.service_ @@ -163,7 +203,7 @@ private: std::mutex deserialize_mutex_; std::mutex pending_mutex_; - bool is_selective_; + std::map > > fields_; }; } // namespace vsomeip diff --git a/implementation/routing/include/routing_manager_stub.hpp b/implementation/routing/include/routing_manager_stub.hpp index c261303..6a1ec38 100644 --- a/implementation/routing/include/routing_manager_stub.hpp +++ b/implementation/routing/include/routing_manager_stub.hpp @@ -19,12 +19,15 @@ namespace vsomeip { +class configuration; class routing_manager_stub_host; class routing_manager_stub: public endpoint_host, public std::enable_shared_from_this { public: - routing_manager_stub(routing_manager_stub_host *_host); + routing_manager_stub( + routing_manager_stub_host *_host, + std::shared_ptr _configuration); virtual ~routing_manager_stub(); void init(); @@ -34,6 +37,7 @@ public: void on_connect(std::shared_ptr _endpoint); void on_disconnect(std::shared_ptr _endpoint); void on_message(const byte_t *_data, length_t _length, endpoint *_receiver); + void on_error(const byte_t *_data, length_t _length, endpoint *_receiver); void on_offer_service(client_t _client, service_t _service, instance_t _instance); @@ -56,17 +60,17 @@ private: void send_application_lost(std::list &_lost); private: + routing_manager_stub_host *host_; boost::asio::io_service &io_; boost::asio::system_timer watchdog_timer_; - routing_manager_stub_host *host_; - std::string endpoint_path_; std::shared_ptr endpoint_; std::map > > > routing_info_; mutable std::mutex routing_info_mutex_; + std::shared_ptr configuration_; }; } // namespace vsomeip diff --git a/implementation/routing/include/routing_manager_stub_host.hpp b/implementation/routing/include/routing_manager_stub_host.hpp index 049bc13..f25eef2 100644 --- a/implementation/routing/include/routing_manager_stub_host.hpp +++ b/implementation/routing/include/routing_manager_stub_host.hpp @@ -17,21 +17,29 @@ public: virtual void offer_service(client_t _client, service_t _service, instance_t _instance, major_version_t _major, - minor_version_t _minor, ttl_t _ttl) = 0; + minor_version_t _minor) = 0; virtual void stop_offer_service(client_t _client, service_t _service, instance_t _instance) = 0; virtual void request_service(client_t _client, service_t _service, instance_t _instance, major_version_t _major, - minor_version_t _minor, ttl_t _ttl, bool _has_selective) = 0; + minor_version_t _minor, bool _use_exclusive_proxy) = 0; virtual void release_service(client_t _client, service_t _service, instance_t _instance) = 0; + virtual void register_event(client_t _client, service_t _service, + instance_t _instance, event_t _event, + std::set _eventgroups, + bool _is_field, bool _is_provided) = 0; + + virtual void unregister_event(client_t _client, service_t _service, + instance_t _instance, event_t _event, bool _is_provided) = 0; + virtual void subscribe(client_t _client, service_t _service, instance_t _instance, eventgroup_t _eventgroup, - major_version_t _major, ttl_t _ttl) = 0; + major_version_t _major) = 0; virtual void unsubscribe(client_t _client, service_t _service, instance_t _instance, eventgroup_t _eventgroup) = 0; @@ -39,6 +47,10 @@ public: virtual void on_message(service_t _service, instance_t _instance, const byte_t *_data, length_t _size, bool _reliable) = 0; + virtual void on_notification(client_t _client, + service_t _service, instance_t _instance, + const byte_t *_data, length_t _size) = 0; + virtual void on_stop_offer_service(service_t _service, instance_t _instance) = 0; diff --git a/implementation/routing/include/servicegroup.hpp b/implementation/routing/include/servicegroup.hpp deleted file mode 100644 index 6014df1..0000000 --- a/implementation/routing/include/servicegroup.hpp +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright (C) 2014-2015 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_SERVICEGROUP_HPP -#define VSOMEIP_SERVICEGROUP_HPP - -#include -#include -#include - -#include "types.hpp" - -namespace vsomeip { - -class serviceinfo; - -class servicegroup { -public: - servicegroup(const std::string &_name, bool _is_local); - virtual ~servicegroup(); - - std::string get_name() const; - bool is_local() const; - - bool add_service(service_t _service, instance_t _instance, - std::shared_ptr _info); - bool remove_service(service_t _service, instance_t _instance); - - services_t get_services() const; - -private: - std::string name_; - bool is_local_; - services_t services_; -}; - -} // namespace vsomeip - -#endif // VSOMEIP_SERVICEGROUP_HPP diff --git a/implementation/routing/include/serviceinfo.hpp b/implementation/routing/include/serviceinfo.hpp index a98127e..af3a50c 100644 --- a/implementation/routing/include/serviceinfo.hpp +++ b/implementation/routing/include/serviceinfo.hpp @@ -21,7 +21,7 @@ class servicegroup; class serviceinfo { public: VSOMEIP_EXPORT serviceinfo(major_version_t _major, minor_version_t _minor, - ttl_t _ttl); + ttl_t _ttl, bool _is_local); VSOMEIP_EXPORT ~serviceinfo(); VSOMEIP_EXPORT servicegroup * get_group() const; @@ -49,6 +49,8 @@ public: VSOMEIP_EXPORT void add_client(client_t _client); VSOMEIP_EXPORT void remove_client(client_t _client); + VSOMEIP_EXPORT bool is_local() const; + private: servicegroup *group_; @@ -64,6 +66,8 @@ private: eventgroup_t multicast_group_; std::set requesters_; + + bool is_local_; }; } // namespace vsomeip diff --git a/implementation/routing/src/event.cpp b/implementation/routing/src/event.cpp index eb86a12..4572632 100644 --- a/implementation/routing/src/event.cpp +++ b/implementation/routing/src/event.cpp @@ -4,7 +4,6 @@ // file, You can obtain one at http://mozilla.org/MPL/2.0/. #include -#include #include #include #include @@ -12,6 +11,7 @@ #include "../include/event.hpp" #include "../include/routing_manager.hpp" #include "../../configuration/include/internal.hpp" +#include "../../logging/include/logger.hpp" #include "../../message/include/payload_impl.hpp" namespace vsomeip { @@ -21,7 +21,8 @@ event::event(routing_manager *_routing) : message_(runtime::get()->create_notification()), cycle_timer_(_routing->get_io()), is_updating_on_change_(true), - is_set_(false) { + is_set_(false), + ref_(0) { } service_t event::get_service() const { @@ -56,6 +57,14 @@ void event::set_field(bool _is_field) { is_field_ = _is_field; } +bool event::is_provided() const { + return (is_provided_); +} + +void event::set_provided(bool _is_provided) { + is_provided_ = _is_provided; +} + bool event::is_reliable() const { return message_->is_reliable(); } @@ -69,64 +78,76 @@ const std::shared_ptr event::get_payload() const { } void event::set_payload(std::shared_ptr _payload) { - if (set_payload_helper(_payload)) { - std::shared_ptr its_new_payload - = runtime::get()->create_payload( - _payload->get_data(), _payload->get_length()); - - message_->set_payload(its_new_payload); - if (is_updating_on_change_) { - notify(); - } - } + if (is_provided_) { + if (set_payload_helper(_payload)) { + std::shared_ptr its_new_payload + = runtime::get()->create_payload( + _payload->get_data(), _payload->get_length()); + + message_->set_payload(its_new_payload); + if (is_updating_on_change_) { + notify(); + } + } + } } void event::set_payload(std::shared_ptr _payload, client_t _client) { - set_payload_helper(_payload); - std::shared_ptr its_new_payload - = runtime::get()->create_payload( - _payload->get_data(), _payload->get_length()); - - message_->set_payload(its_new_payload); - if (is_updating_on_change_) { - notify_one(_client); - } + if (is_provided_) { + set_payload_helper(_payload); + std::shared_ptr its_new_payload + = runtime::get()->create_payload( + _payload->get_data(), _payload->get_length()); + + message_->set_payload(its_new_payload); + if (is_updating_on_change_) { + notify_one(_client); + } + } } void event::set_payload(std::shared_ptr _payload, const std::shared_ptr _target) { - - set_payload_helper(_payload); - std::shared_ptr its_new_payload - = runtime::get()->create_payload( - _payload->get_data(), _payload->get_length()); - - message_->set_payload(its_new_payload); - if (is_updating_on_change_) { - notify_one(_target); - } + if (is_provided_) { + if (set_payload_helper(_payload)) { + std::shared_ptr its_new_payload + = runtime::get()->create_payload( + _payload->get_data(), _payload->get_length()); + + message_->set_payload(its_new_payload); + if (is_updating_on_change_) { + notify_one(_target); + } + } + } } void event::unset_payload() { - is_set_ = false; - message_->set_payload(std::make_shared()); + if (is_provided_) { + is_set_ = false; + message_->set_payload(std::make_shared()); + } } void event::set_update_on_change(bool _is_active) { - is_updating_on_change_ = _is_active; + if (is_provided_) { + is_updating_on_change_ = _is_active; + } } void event::set_update_cycle(std::chrono::milliseconds &_cycle) { - cycle_ = _cycle; + if (is_provided_) { + cycle_ = _cycle; - cycle_timer_.cancel(); + cycle_timer_.cancel(); - if (std::chrono::milliseconds::zero() != _cycle) { - cycle_timer_.expires_from_now(cycle_); - std::function its_handler = - std::bind(&event::update_cbk, shared_from_this(), - std::placeholders::_1); - cycle_timer_.async_wait(its_handler); + if (std::chrono::milliseconds::zero() != _cycle) { + cycle_timer_.expires_from_now(cycle_); + std::function its_handler = + std::bind(&event::update_cbk, shared_from_this(), + std::placeholders::_1); + cycle_timer_.async_wait(its_handler); + } } } @@ -172,7 +193,7 @@ void event::notify_one(client_t _client) { bool event::set_payload_helper(std::shared_ptr _payload) { std::shared_ptr its_payload = message_->get_payload(); bool is_change(!is_field_); - if(is_field_) { + if (is_field_) { is_change = (its_payload->get_length() != _payload->get_length()); if (!is_change) { std::size_t its_pos = 0; @@ -189,4 +210,13 @@ bool event::set_payload_helper(std::shared_ptr _payload) { return is_change; } +void event::add_ref() { + ref_++; +} + +uint32_t event::remove_ref() { + ref_--; + return ref_; +} + } // namespace vsomeip diff --git a/implementation/routing/src/eventgroupinfo.cpp b/implementation/routing/src/eventgroupinfo.cpp index 64d9b6b..0d098e4 100644 --- a/implementation/routing/src/eventgroupinfo.cpp +++ b/implementation/routing/src/eventgroupinfo.cpp @@ -10,76 +10,83 @@ namespace vsomeip { eventgroupinfo::eventgroupinfo() - : major_(DEFAULT_MAJOR), - ttl_(DEFAULT_TTL), - is_multicast_(false) { + : major_(DEFAULT_MAJOR), ttl_(DEFAULT_TTL), is_multicast_(false) { } eventgroupinfo::eventgroupinfo(major_version_t _major, ttl_t _ttl) - : major_(_major), - ttl_(_ttl), - is_multicast_(false) { + : major_(_major), ttl_(_ttl), is_multicast_(false) { } eventgroupinfo::~eventgroupinfo() { } major_version_t eventgroupinfo::get_major() const { - return major_; + return major_; } void eventgroupinfo::set_major(major_version_t _major) { - major_ = _major; + major_ = _major; } ttl_t eventgroupinfo::get_ttl() const { - return ttl_; + return ttl_; } void eventgroupinfo::set_ttl(ttl_t _ttl) { - ttl_ = _ttl; + ttl_ = _ttl; } bool eventgroupinfo::is_multicast() const { - return is_multicast_; + return is_multicast_; } -bool eventgroupinfo::get_multicast(boost::asio::ip::address &_address, uint16_t &_port) const { - if (is_multicast_) { - _address = address_; - _port = port_; - } - return is_multicast_; +bool eventgroupinfo::get_multicast(boost::asio::ip::address &_address, + uint16_t &_port) const { + if (is_multicast_) { + _address = address_; + _port = port_; + } + return is_multicast_; } -void eventgroupinfo::set_multicast(const boost::asio::ip::address &_address, uint16_t _port) { - address_ = _address; - port_ = _port; - is_multicast_ = true; +void eventgroupinfo::set_multicast(const boost::asio::ip::address &_address, + uint16_t _port) { + address_ = _address; + port_ = _port; + is_multicast_ = true; } const std::set > eventgroupinfo::get_events() const { - return events_; + return events_; } void eventgroupinfo::add_event(std::shared_ptr _event) { - events_.insert(_event); + events_.insert(_event); +} + +void eventgroupinfo::remove_event(std::shared_ptr _event) { + events_.erase(_event); } const std::set > eventgroupinfo::get_targets() const { - return targets_; + return targets_; } -void eventgroupinfo::add_target(std::shared_ptr _target) { - targets_.insert(_target); +bool eventgroupinfo::add_target(std::shared_ptr _target) { + std::size_t its_size = targets_.size(); + targets_.insert(_target); + return (its_size != targets_.size()); } -void eventgroupinfo::del_target(std::shared_ptr _target) { - targets_.erase(_target); +bool eventgroupinfo::remove_target( + std::shared_ptr _target) { + std::size_t its_size = targets_.size(); + targets_.erase(_target); + return (its_size != targets_.size()); } void eventgroupinfo::clear_targets() { - targets_.clear(); + targets_.clear(); } } // namespace vsomeip diff --git a/implementation/routing/src/routing_manager_impl.cpp b/implementation/routing/src/routing_manager_impl.cpp index d22a76e..ff1c67e 100644 --- a/implementation/routing/src/routing_manager_impl.cpp +++ b/implementation/routing/src/routing_manager_impl.cpp @@ -7,9 +7,7 @@ #include #include -#include #include -#include #include #include #include @@ -19,8 +17,8 @@ #include "../include/routing_manager_host.hpp" #include "../include/routing_manager_impl.hpp" #include "../include/routing_manager_stub.hpp" -#include "../include/servicegroup.hpp" #include "../include/serviceinfo.hpp" +#include "../../configuration/include/configuration.hpp" #include "../../configuration/include/internal.hpp" #include "../../endpoints/include/endpoint_definition.hpp" #include "../../endpoints/include/local_client_endpoint_impl.hpp" @@ -28,6 +26,8 @@ #include "../../endpoints/include/tcp_server_endpoint_impl.hpp" #include "../../endpoints/include/udp_client_endpoint_impl.hpp" #include "../../endpoints/include/udp_server_endpoint_impl.hpp" +#include "../../endpoints/include/virtual_server_endpoint_impl.hpp" +#include "../../logging/include/logger.hpp" #include "../../message/include/deserializer.hpp" #include "../../message/include/serializer.hpp" #include "../../service_discovery/include/constants.hpp" @@ -40,10 +40,11 @@ namespace vsomeip { routing_manager_impl::routing_manager_impl(routing_manager_host *_host) : - host_(_host), io_(_host->get_io()), deserializer_( - std::make_shared()), serializer_( - std::make_shared()), configuration_( - host_->get_configuration()) { + host_(_host), + io_(_host->get_io()), + deserializer_(std::make_shared()), + serializer_(std::make_shared()), + configuration_(host_->get_configuration()) { } routing_manager_impl::~routing_manager_impl() { @@ -58,22 +59,16 @@ client_t routing_manager_impl::get_client() const { } void routing_manager_impl::init() { - uint32_t its_max_message_size = VSOMEIP_MAX_LOCAL_MESSAGE_SIZE; - if (VSOMEIP_MAX_TCP_MESSAGE_SIZE > its_max_message_size) - its_max_message_size = VSOMEIP_MAX_TCP_MESSAGE_SIZE; - if (VSOMEIP_MAX_UDP_MESSAGE_SIZE > its_max_message_size) - its_max_message_size = VSOMEIP_MAX_UDP_MESSAGE_SIZE; - - serializer_->create_data(its_max_message_size); + serializer_->create_data(configuration_->get_max_message_size_local()); // TODO: Only instantiate the stub if needed - stub_ = std::make_shared(this); + stub_ = std::make_shared(this, configuration_); stub_->init(); // We need to be able to send messages to ourself (for delivering events) (void)create_local(VSOMEIP_ROUTING_CLIENT); - if (configuration_->is_service_discovery_enabled()) { + if (configuration_->is_sd_enabled()) { VSOMEIP_INFO<< "Service Discovery enabled. Trying to load module."; std::shared_ptr *its_runtime = static_cast *>(utility::load_library( @@ -85,10 +80,8 @@ void routing_manager_impl::init() { discovery_ = (*its_runtime)->create_service_discovery(this); discovery_->init(); } - - init_event_routing_info(); } else { - init_routing_info(); + init_routing_info(); // Static routing } } @@ -97,11 +90,11 @@ void routing_manager_impl::start() { if (discovery_) discovery_->start(); - host_->on_event(event_type_e::ET_REGISTERED); + host_->on_state(state_type_e::ST_REGISTERED); } void routing_manager_impl::stop() { - host_->on_event(event_type_e::ET_DEREGISTERED); + host_->on_state(state_type_e::ST_DEREGISTERED); if (discovery_) discovery_->stop(); @@ -109,8 +102,7 @@ void routing_manager_impl::stop() { } void routing_manager_impl::offer_service(client_t _client, service_t _service, - instance_t _instance, major_version_t _major, minor_version_t _minor, - ttl_t _ttl) { + instance_t _instance, major_version_t _major, minor_version_t _minor) { std::shared_ptr its_info; { std::lock_guard its_lock(local_mutex_); @@ -121,20 +113,18 @@ void routing_manager_impl::offer_service(client_t _client, service_t _service, if (its_info) { if (its_info->get_major() == _major && its_info->get_minor() == _minor) { - its_info->set_ttl(_ttl); + its_info->set_ttl(DEFAULT_TTL); } else { host_->on_error(error_code_e::SERVICE_PROPERTY_MISMATCH); } } else { - its_info = create_service(_service, _instance, _major, _minor, _ttl); + its_info = create_service_info(_service, _instance, _major, _minor, + DEFAULT_TTL, true); } } if (discovery_ && its_info) { - std::string group_name("default"); - if (its_info->get_group()) - group_name = its_info->get_group()->get_name(); - discovery_->on_offer_change(group_name); + discovery_->on_offer_change(); } stub_->on_offer_service(_client, _service, _instance); @@ -149,26 +139,26 @@ void routing_manager_impl::stop_offer_service(client_t _client, void routing_manager_impl::request_service(client_t _client, service_t _service, instance_t _instance, major_version_t _major, minor_version_t _minor, - ttl_t _ttl, bool _has_selective) { + bool _use_exclusive_proxy) { std::shared_ptr its_info(find_service(_service, _instance)); if (its_info) { - if ((_major < ANY_MAJOR && _major > its_info->get_major()) - || (_major == its_info->get_major() - && _minor < ANY_MINOR && _minor > its_info->get_minor()) - || (_ttl > its_info->get_ttl())) { - host_->on_error(error_code_e::SERVICE_PROPERTY_MISMATCH); - } else { + if ((_major == its_info->get_major() + || DEFAULT_MAJOR == its_info->get_major()) + && (_minor <= its_info->get_minor() + || DEFAULT_MINOR == its_info->get_minor())) { its_info->add_client(_client); + } else { + host_->on_error(error_code_e::SERVICE_PROPERTY_MISMATCH); } } else { if (discovery_) discovery_->request_service(_service, _instance, _major, _minor, - _ttl); + DEFAULT_TTL); } // TODO: Mutex?! - if (_has_selective) { + if (_use_exclusive_proxy) { specific_endpoint_clients.insert(_client); } } @@ -185,35 +175,36 @@ void routing_manager_impl::release_service(client_t _client, service_t _service, } void routing_manager_impl::subscribe(client_t _client, service_t _service, - instance_t _instance, eventgroup_t _eventgroup, major_version_t _major, - ttl_t _ttl) { + instance_t _instance, eventgroup_t _eventgroup, major_version_t _major) { if (discovery_) { if (!host_->on_subscription(_service, _instance, _eventgroup, _client, true)) { VSOMEIP_INFO << "Subscription request for eventgroup " << _eventgroup - << " rejected from application handler"; + << " rejected from application handler"; return; } - eventgroup_clients_[_service][_instance][_eventgroup].insert(_client); - if (0 == find_local_client(_service, _instance)) { - client_t subscriber = VSOMEIP_ROUTING_CLIENT; - // subscriber != VSOMEIP_ROUTING_CLIENT implies to use its own endpoint - auto its_selective = specific_endpoint_clients.find(_client); - if (its_selective != specific_endpoint_clients.end()) { - subscriber = _client; - } - discovery_->subscribe(_service, _instance, _eventgroup, _major, - _ttl, subscriber); - } else { - send_subscribe(_client, _service, _instance, _eventgroup, _major, _ttl); - std::shared_ptr its_eventgroup - = find_eventgroup(_service, _instance, _eventgroup); - if (its_eventgroup) { - std::set > its_events - = its_eventgroup->get_events(); - for (auto e : its_events) { - if (e->is_field()) - e->notify_one(_client); + if (insert_subscription(_service, _instance, _eventgroup, _client)) { + if (0 == find_local_client(_service, _instance)) { + client_t subscriber = VSOMEIP_ROUTING_CLIENT; + // subscriber != VSOMEIP_ROUTING_CLIENT implies to use its own endpoint + auto its_selective = specific_endpoint_clients.find(_client); + if (its_selective != specific_endpoint_clients.end()) { + subscriber = _client; + } + discovery_->subscribe(_service, _instance, _eventgroup, + _major, DEFAULT_TTL, subscriber); + } else { + send_subscribe(_client, _service, _instance, _eventgroup, _major); + + std::shared_ptr its_eventgroup + = find_eventgroup(_service, _instance, _eventgroup); + if (its_eventgroup) { + std::set > its_events + = its_eventgroup->get_events(); + for (auto e : its_events) { + if (e->is_field()) + e->notify_one(_client); + } } } } @@ -240,12 +231,18 @@ void routing_manager_impl::unsubscribe(client_t _client, service_t _service, } } host_->on_subscription(_service, _instance, _eventgroup, _client, false); - if (0 == find_local_client(_service, _instance)) { - discovery_->unsubscribe(_service, _instance, _eventgroup); + client_t subscriber = VSOMEIP_ROUTING_CLIENT; + // subscriber != VSOMEIP_ROUTING_CLIENT implies to use its own endpoint + auto its_selective = specific_endpoint_clients.find(_client); + if (its_selective != specific_endpoint_clients.end()) { + subscriber = _client; + } + discovery_->unsubscribe(_service, _instance, _eventgroup, subscriber); } else { send_unsubscribe(_client, _service, _instance, _eventgroup); } + clear_multicast_endpoints(_service, _instance); } else { VSOMEIP_ERROR<< "SOME/IP eventgroups require SD to be enabled!"; } @@ -265,6 +262,8 @@ bool routing_manager_impl::send(client_t its_client, serializer_->get_size(), _message->get_instance(), _flush, _message->is_reliable()); serializer_->reset(); + } else { + VSOMEIP_ERROR << "Failed to serialize message. Check message size!"; } return (is_sent); @@ -409,7 +408,7 @@ bool routing_manager_impl::send_local( std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + _size + sizeof(instance_t) + sizeof(bool)], &_reliable, sizeof(bool)); - return _target->send(&its_command[0], its_command.size(), _flush); + return _target->send(&its_command[0], uint32_t(its_command.size()), _flush); } bool routing_manager_impl::send_to( @@ -430,12 +429,94 @@ bool routing_manager_impl::send_to( bool routing_manager_impl::send_to( const std::shared_ptr &_target, const byte_t *_data, uint32_t _size) { - std::shared_ptr its_endpoint = find_or_create_server_endpoint( + std::shared_ptr its_endpoint = find_server_endpoint( _target->get_remote_port(), _target->is_reliable()); return (its_endpoint && its_endpoint->send_to(_target, _data, _size)); } +void routing_manager_impl::register_event(client_t _client, + service_t _service, instance_t _instance, + event_t _event, std::set _eventgroups, + bool _is_field, bool _is_provided) { + (void)_client; + + std::shared_ptr its_event = find_event(_service, _instance, _event); + if (its_event) { + if (its_event->is_field() == _is_field) { + if (_is_provided) { + its_event->set_provided(true); + } + for (auto eg : _eventgroups) { + its_event->add_eventgroup(eg); + } + } else { + VSOMEIP_ERROR << "Event registration update failed. " + "Specified arguments do not match existing registration."; + } + } else { + its_event = std::make_shared(this); + its_event->set_service(_service); + its_event->set_instance(_instance); + its_event->set_event(_event); + its_event->set_field(_is_field); + its_event->set_provided(_is_provided); + + if (_eventgroups.size() == 0) { // No eventgroup specified + _eventgroups.insert(_event); + } + + its_event->set_eventgroups(_eventgroups); + } + + its_event->add_ref(); + + for (auto eg : _eventgroups) { + std::shared_ptr its_eventgroup_info + = find_eventgroup(_service, _instance, eg); + if (!its_eventgroup_info) { + its_eventgroup_info = std::make_shared(); + eventgroups_[_service][_instance][eg] = its_eventgroup_info; + } + its_eventgroup_info->add_event(its_event); + } + + events_[_service][_instance][_event] = its_event; +} + +void routing_manager_impl::unregister_event(client_t _client, + service_t _service, instance_t _instance, + event_t _event, bool _is_provided) { + (void)_client; + + auto found_service = events_.find(_service); + if (found_service != events_.end()) { + auto found_instance = found_service->second.find(_instance); + if (found_instance != found_service->second.end()) { + auto found_event = found_instance->second.find(_event); + if (found_event != found_instance->second.end()) { + auto its_event = found_event->second; + if (!its_event->remove_ref()) { + auto its_eventgroups = its_event->get_eventgroups(); + for (auto eg : its_eventgroups) { + std::shared_ptr its_eventgroup_info + = find_eventgroup(_service, _instance, eg); + if (its_eventgroup_info) { + its_eventgroup_info->remove_event(its_event); + if (0 == its_eventgroup_info->get_events().size()) { + remove_eventgroup_info(_service, _instance, eg); + } + } + } + found_instance->second.erase(_event); + } else if (_is_provided) { + its_event->set_provided(false); + } + } + } + } +} + void routing_manager_impl::notify( service_t _service, instance_t _instance, event_t _event, std::shared_ptr _payload) { @@ -443,9 +524,9 @@ void routing_manager_impl::notify( if (its_event) { its_event->set_payload(_payload); } else { - VSOMEIP_ERROR << "routing_manager_impl::notify: event [" + VSOMEIP_WARNING << "Attempt to update the undefined event/field [" << std::hex << _service << "." << _instance << "." << _event - << "] is unknown."; + << "]"; } } @@ -466,10 +547,21 @@ void routing_manager_impl::notify_one(service_t _service, instance_t _instance, } } } else { - VSOMEIP_ERROR << "routing_manager_impl::notify: event [" + VSOMEIP_WARNING << "Attempt to update the undefined event/field [" << std::hex << _service << "." << _instance << "." << _event - << "] is unknown."; + << "]"; + } +} + +void routing_manager_impl::on_error(const byte_t *_data, length_t _length, endpoint *_receiver) { + instance_t its_instance = 0; + if (_length >= VSOMEIP_SERVICE_POS_MAX) { + service_t its_service = VSOMEIP_BYTES_TO_WORD( + _data[VSOMEIP_SERVICE_POS_MIN], _data[VSOMEIP_SERVICE_POS_MAX]); + its_instance = find_instance(its_service, _receiver); } + send_error(return_code_e::E_MALFORMED_MESSAGE, _data, _length, + its_instance, _receiver->is_reliable(), _receiver); } void routing_manager_impl::on_message(const byte_t *_data, length_t _size, @@ -482,9 +574,6 @@ void routing_manager_impl::on_message(const byte_t *_data, length_t _size, VSOMEIP_DEBUG << msg.str(); #endif service_t its_service; - instance_t its_instance; - message_type_e its_message_type; - if (_size >= VSOMEIP_SOMEIP_HEADER_SIZE) { its_service = VSOMEIP_BYTES_TO_WORD(_data[VSOMEIP_SERVICE_POS_MIN], _data[VSOMEIP_SERVICE_POS_MAX]); @@ -492,41 +581,21 @@ void routing_manager_impl::on_message(const byte_t *_data, length_t _size, if (discovery_) discovery_->on_message(_data, _size); } else { - its_instance = find_instance(its_service, _receiver); - its_message_type = static_cast(_data[VSOMEIP_MESSAGE_TYPE_POS]); - if (its_instance == 0xFFFF) { - VSOMEIP_WARNING << "Receiving endpoint is not configured for service 0x" - << std::hex << its_service; + instance_t its_instance = find_instance(its_service, _receiver); + return_code_e return_code = check_error(_data, _size, its_instance); + if (return_code != return_code_e::E_OK) { + if (return_code != return_code_e::E_NOT_OK) { + send_error(return_code, _data, _size, its_instance, + _receiver->is_reliable(), _receiver); + } return; } - // TODO: move specific endpoint handling to to a method! - auto found_service = remote_services_.find(its_service); - if (found_service != remote_services_.end()) { - auto found_instance = found_service->second.find(its_instance); - if (found_instance != found_service->second.end()) { - for (auto client_entry : found_instance->second) { - client_t client = client_entry.first; - if (!client) { - continue; - } - auto found_reliability = client_entry.second.find(_receiver->is_reliable()); - if (found_reliability != client_entry.second.end()) { - auto found_enpoint = found_reliability->second; - if (found_enpoint.get() == _receiver) { - auto local_endpoint = find_local(client); - if (client != get_client()) { - send_local(local_endpoint, client, _data, _size, its_instance, true, _receiver->is_reliable()); - } else { - deliver_message(_data, _size, its_instance, _receiver->is_reliable()); - } - return; - } - } - } - } + if (!deliver_specific_endpoint_message( + its_service, its_instance, _data, _size, _receiver)) { + // Common way of message handling + on_message(its_service, its_instance, _data, _size, _receiver->is_reliable()); } - on_message(its_service, its_instance, _data, _size, _receiver->is_reliable()); } } } @@ -535,6 +604,15 @@ void routing_manager_impl::on_message( service_t _service, instance_t _instance, const byte_t *_data, length_t _size, bool _reliable) { +#if 0 + std::stringstream msg; + msg << "rmi::on_message(" + << std::hex << std::setw(4) << std::setfill('0') + << _service << ", " << _instance << "): "; + for (uint32_t i = 0; i < _size; ++i) + msg << std::hex << std::setw(2) << std::setfill('0') << (int)_data[i] << " "; + VSOMEIP_DEBUG << msg.str(); +#endif method_t its_method; client_t its_client; session_t its_session; @@ -552,10 +630,6 @@ void routing_manager_impl::on_message( const_cast(_data)[VSOMEIP_CLIENT_POS_MIN] = 0; const_cast(_data)[VSOMEIP_CLIENT_POS_MAX] = 0; - its_method = VSOMEIP_BYTES_TO_WORD( - _data[VSOMEIP_METHOD_POS_MIN], - _data[VSOMEIP_METHOD_POS_MAX]); - auto it_subscriber = remote_subscriber_map_.find(its_client); if (it_subscriber != remote_subscriber_map_.end()) { send_to(it_subscriber->second, _data, _size); @@ -574,11 +648,11 @@ void routing_manager_impl::on_message( = find_event(_service, _instance, its_method); if (its_event) { uint32_t its_length = utility::get_payload_size(_data, _size); - std::shared_ptr its_payload = - runtime::get()->create_payload( - &_data[VSOMEIP_PAYLOAD_POS], - its_length); - its_event->set_payload(its_payload); + std::shared_ptr its_payload = + runtime::get()->create_payload( + &_data[VSOMEIP_PAYLOAD_POS], + its_length); + its_event->set_payload(its_payload); if (!utility::is_request_no_return( _data[VSOMEIP_MESSAGE_TYPE_POS])) { @@ -622,27 +696,59 @@ void routing_manager_impl::on_message( _data[VSOMEIP_CLIENT_POS_MAX]); } - if ((its_client == VSOMEIP_ROUTING_CLIENT - && utility::is_notification(_data[VSOMEIP_MESSAGE_TYPE_POS])) - || its_client == host_->get_client()) { + if (its_client == VSOMEIP_ROUTING_CLIENT + && utility::is_notification(_data[VSOMEIP_MESSAGE_TYPE_POS])) { + deliver_notification(_service, _instance, _data, _size, _reliable); + } else if (its_client == host_->get_client()) { deliver_message(_data, _size, _instance, _reliable); } else { send(its_client, _data, _size, _instance, true, _reliable); } } +void routing_manager_impl::on_notification(client_t _client, + service_t _service, instance_t _instance, + const byte_t *_data, length_t _size) { + event_t its_event_id = VSOMEIP_BYTES_TO_WORD( + _data[VSOMEIP_METHOD_POS_MIN], + _data[VSOMEIP_METHOD_POS_MAX]); + + std::shared_ptr its_event = find_event(_service, _instance, its_event_id); + if (its_event) { + uint32_t its_length = utility::get_payload_size(_data, _size); + std::shared_ptr its_payload = + runtime::get()->create_payload( + &_data[VSOMEIP_PAYLOAD_POS], + its_length); + + if (_client == VSOMEIP_ROUTING_CLIENT) + its_event->set_payload(its_payload); + else + its_event->set_payload(its_payload, _client); + } +} + void routing_manager_impl::on_connect(std::shared_ptr _endpoint) { + // Is called when endpoint->connect succeded! for (auto &its_service : remote_services_) { for (auto &its_instance : its_service.second) { - auto found_endpoint = its_instance.second.find(false); - if (found_endpoint != its_instance.second.end()) { - host_->on_availability(its_service.first, its_instance.first, - true); - } else { - found_endpoint = its_instance.second.find(true); - if (found_endpoint != its_instance.second.end()) { - host_->on_availability(its_service.first, - its_instance.first, true); + for (auto &its_client : its_instance.second) { + if (its_client.first == VSOMEIP_ROUTING_CLIENT || + its_client.first == get_client()) { + auto found_endpoint = its_client.second.find(false); + if (found_endpoint != its_client.second.end()) { + if (found_endpoint->second.get() == _endpoint.get()) { + host_->on_availability(its_service.first, its_instance.first, + true); + } + } + found_endpoint = its_client.second.find(true); + if (found_endpoint != its_client.second.end()) { + if (found_endpoint->second.get() == _endpoint.get()) { + host_->on_availability(its_service.first, + its_instance.first, true); + } + } } } } @@ -650,17 +756,26 @@ void routing_manager_impl::on_connect(std::shared_ptr _endpoint) { } void routing_manager_impl::on_disconnect(std::shared_ptr _endpoint) { + // Is called when endpoint->connect fails! for (auto &its_service : remote_services_) { for (auto &its_instance : its_service.second) { - auto found_endpoint = its_instance.second.find(false); - if (found_endpoint != its_instance.second.end()) { - host_->on_availability(its_service.first, its_instance.first, - false); - } else { - found_endpoint = its_instance.second.find(true); - if (found_endpoint != its_instance.second.end()) { - host_->on_availability(its_service.first, - its_instance.first, false); + for (auto &its_client : its_instance.second) { + if (its_client.first == VSOMEIP_ROUTING_CLIENT || + its_client.first == get_client()) { + auto found_endpoint = its_client.second.find(false); + if (found_endpoint != its_client.second.end()) { + if (found_endpoint->second.get() == _endpoint.get()) { + host_->on_availability(its_service.first, its_instance.first, + false); + } + } + found_endpoint = its_client.second.find(true); + if (found_endpoint != its_client.second.end()) { + if (found_endpoint->second.get() == _endpoint.get()) { + host_->on_availability(its_service.first, + its_instance.first, false); + } + } } } } @@ -675,50 +790,147 @@ void routing_manager_impl::on_stop_offer_service(service_t _service, for (auto &e : i.second) e.second->unset_payload(); - host_->on_availability(_service, _instance, false); + /** + * Hold reliable & unreliable server-endpoints from service info + * because if "del_routing_info" is called those entries could be freed + * and we can't be sure this happens synchronous when SD is active. + * After triggering "del_routing_info" this endpoints gets cleanup up + * within this method if they not longer used by any other local service. + */ + std::shared_ptr its_reliable_endpoint; + std::shared_ptr its_unreliable_endpoint; + std::shared_ptr its_info(find_service(_service, _instance)); + if (its_info) { + its_reliable_endpoint = its_info->get_endpoint(true); + its_unreliable_endpoint = its_info->get_endpoint(false); + } + // Trigger "del_routing_info" either over SD or static if (discovery_) { auto found_service = services_.find(_service); if (found_service != services_.end()) { auto found_instance = found_service->second.find(_instance); if (found_instance != found_service->second.end()) { found_instance->second->set_ttl(0); - discovery_->on_offer_change( - found_instance->second->get_group()->get_name()); + discovery_->on_offer_change(); } } } else { - // TODO: allow to withdraw a service on one endpoint only - del_routing_info(_service, _instance, false); - del_routing_info(_service, _instance, true); + del_routing_info(_service, _instance, + (its_reliable_endpoint != nullptr), + (its_unreliable_endpoint != nullptr)); + } + + // Cleanup reliable & unreliable server endpoints hold before + if (its_info) { + std::lock_guard its_lock(endpoint_mutex_); + std::shared_ptr its_empty_endpoint; + bool reliable = true; + + // Loop over reliable/unreliable and cleanup if needed + for (uint8_t i = 0; i < 2; ++i) { + std::shared_ptr its_endpoint; + if (reliable) { + its_endpoint = its_reliable_endpoint; + } else { + its_endpoint = its_unreliable_endpoint; + } + if (!its_endpoint) { + reliable = !reliable; + continue; + } + + // Check whether any service still uses this endpoint + its_endpoint->decrement_use_count(); + bool isLastService = (its_endpoint->get_use_count() == 0); + + // Clear service_instances_ + if (1 >= service_instances_[_service].size()) { + service_instances_.erase(_service); + } else { + service_instances_[_service].erase(its_endpoint.get()); + } + + // Clear server endpoint if no service remains using it + if (isLastService) { + uint16_t port = its_endpoint->get_local_port(); + if (server_endpoints_.find(port) != server_endpoints_.end()) { + server_endpoints_[port].erase(reliable); + if (server_endpoints_[port].find(!reliable) == server_endpoints_[port].end()) { + server_endpoints_.erase(port); + } + } + + // Stop endpoint (close socket) to release its async_handlers! + its_endpoint->stop(); + } + + // Clear service info and service group + clear_service_info(_service, _instance, reliable); + + // Invert reliable flag and loop again + reliable = !reliable; + } } } bool routing_manager_impl::deliver_message(const byte_t *_data, length_t _size, instance_t _instance, bool _reliable) { - bool is_sent(false); + bool is_delivered(false); deserializer_->set_data(_data, _size); std::shared_ptr its_message(deserializer_->deserialize_message()); if (its_message) { its_message->set_instance(_instance); its_message->set_reliable(_reliable); host_->on_message(its_message); - is_sent = true; + is_delivered = true; } else { - // TODO: send error "Malformed Message" - //send_error(); + VSOMEIP_ERROR << "Deserialization of vSomeIP message failed"; + if (utility::is_request(_data[VSOMEIP_MESSAGE_TYPE_POS])) { + send_error(return_code_e::E_MALFORMED_MESSAGE, _data, + _size, _instance, _reliable, nullptr); + } } - return (is_sent); + return is_delivered; } -const std::map > & -routing_manager_impl::get_servicegroups() const { - return (servicegroups_); +bool routing_manager_impl::deliver_notification( + service_t _service, instance_t _instance, + const byte_t *_data, length_t _length, + bool _reliable) { + bool is_delivered(false); + + method_t its_method = VSOMEIP_BYTES_TO_WORD(_data[VSOMEIP_METHOD_POS_MIN], + _data[VSOMEIP_METHOD_POS_MAX]); + + std::shared_ptr its_event = find_event(_service, _instance, its_method); + if (its_event) { + std::vector< byte_t > its_data; + + for (auto its_group : its_event->get_eventgroups()) { + auto its_local_clients = find_local_clients(_service, _instance, its_group); + for (auto its_local_client : its_local_clients) { + if (its_local_client == host_->get_client()) { + deliver_message(_data, _length, _instance, _reliable); + } else { + std::shared_ptr its_local_target = find_local(its_local_client); + if (its_local_target) { + send_local(its_local_target, VSOMEIP_ROUTING_CLIENT, + _data, _length, _instance, true, _reliable); + } + } + } + } + } + + return is_delivered; } std::shared_ptr routing_manager_impl::find_eventgroup( service_t _service, instance_t _instance, eventgroup_t _eventgroup) const { + std::lock_guard its_lock(eventgroups_mutex_); + std::shared_ptr its_info(nullptr); auto found_service = eventgroups_.find(_service); if (found_service != eventgroups_.end()) { @@ -758,20 +970,33 @@ std::shared_ptr routing_manager_impl::find_eventgroup( return (its_info); } +void routing_manager_impl::remove_eventgroup_info(service_t _service, + instance_t _instance, eventgroup_t _eventgroup) { + std::lock_guard its_lock(eventgroups_mutex_); + auto found_service = eventgroups_.find(_service); + if (found_service != eventgroups_.end()) { + auto found_instance = found_service->second.find(_instance); + if (found_instance != found_service->second.end()) { + found_instance->second.erase(_eventgroup); + } + } +} + std::shared_ptr routing_manager_impl::get_configuration() const { return (host_->get_configuration()); } -void routing_manager_impl::create_service_discovery_endpoint( +std::shared_ptr routing_manager_impl::create_service_discovery_endpoint( const std::string &_address, uint16_t _port, bool _reliable) { std::shared_ptr its_service_endpoint = find_server_endpoint(_port, _reliable); if (!its_service_endpoint) { - its_service_endpoint = create_server_endpoint(_port, _reliable); + its_service_endpoint = create_server_endpoint(_port, _reliable, true); if (its_service_endpoint) { std::shared_ptr its_info( - std::make_shared(ANY_MAJOR, ANY_MINOR, ANY_TTL)); + std::make_shared(ANY_MAJOR, ANY_MINOR, DEFAULT_TTL, + false)); // false, because we do _not_ want to announce it... its_info->set_endpoint(its_service_endpoint, _reliable); // routing info @@ -780,35 +1005,33 @@ void routing_manager_impl::create_service_discovery_endpoint( its_service_endpoint->add_multicast(VSOMEIP_SD_SERVICE, VSOMEIP_SD_METHOD, _address, _port); its_service_endpoint->join(_address); - its_service_endpoint->start(); } else { VSOMEIP_ERROR << "Service Discovery endpoint could not be created. " "Please check your network configuration."; } } + return its_service_endpoint; } -services_t routing_manager_impl::get_offered_services( - const std::string &_name) const { +services_t routing_manager_impl::get_offered_services() const { services_t its_offers; - auto find_servicegroup = servicegroups_.find(_name); - if (find_servicegroup != servicegroups_.end()) { - if (find_servicegroup->second->is_local()) { - return (find_servicegroup->second->get_services()); + std::lock_guard its_lock(services_mutex_); + for (auto s : services_) { + for (auto i : s.second) { + if (i.second->is_local()) { + its_offers[s.first][i.first] = i.second; + } } } - return (its_offers); } std::shared_ptr routing_manager_impl::find_or_create_remote_client( service_t _service, instance_t _instance, bool _reliable, client_t _client) { + std::lock_guard its_lock(endpoint_mutex_); std::shared_ptr its_endpoint = find_remote_client(_service, _instance, _reliable, _client); - // Create specific IP-client-endpoint for selective clients - if (!its_endpoint && - specific_endpoint_clients.find(_client) != specific_endpoint_clients.end()) { - + if (!its_endpoint) { its_endpoint = create_remote_client(_service, _instance, _reliable, _client); } return its_endpoint; @@ -820,6 +1043,7 @@ std::shared_ptr routing_manager_impl::find_or_create_remote_client( std::shared_ptr routing_manager_impl::find_service( service_t _service, instance_t _instance) const { std::shared_ptr its_info; + std::lock_guard its_lock(services_mutex_); auto found_service = services_.find(_service); if (found_service != services_.end()) { auto found_instance = found_service->second.find(_instance); @@ -830,19 +1054,20 @@ std::shared_ptr routing_manager_impl::find_service( return (its_info); } -std::shared_ptr routing_manager_impl::create_service( +std::shared_ptr routing_manager_impl::create_service_info( service_t _service, instance_t _instance, major_version_t _major, - minor_version_t _minor, ttl_t _ttl) { - + minor_version_t _minor, ttl_t _ttl, bool _is_local_service) { std::shared_ptr its_info; if (configuration_) { - its_info = std::make_shared(_major, _minor, _ttl); + its_info = std::make_shared(_major, _minor, _ttl, _is_local_service); uint16_t its_reliable_port = configuration_->get_reliable_port(_service, _instance); uint16_t its_unreliable_port = configuration_->get_unreliable_port( _service, _instance); + bool is_someip = configuration_->is_someip(_service, _instance); + its_info->set_multicast_address( configuration_->get_multicast_address(_service, _instance)); its_info->set_multicast_port( @@ -853,41 +1078,41 @@ std::shared_ptr routing_manager_impl::create_service( std::shared_ptr its_reliable_endpoint; std::shared_ptr its_unreliable_endpoint; - if (ILLEGAL_PORT != its_reliable_port) { - its_reliable_endpoint = find_or_create_server_endpoint( - its_reliable_port, - true); - its_info->set_endpoint(its_reliable_endpoint, true); - - // TODO: put this in a method and check whether an assignment already exists! - service_instances_[_service][its_reliable_endpoint.get()] = - _instance; - } + // Create server endpoints for local services only + if (_is_local_service) { + if (ILLEGAL_PORT != its_reliable_port) { + its_reliable_endpoint = find_or_create_server_endpoint( + its_reliable_port, true, is_someip); + if (its_reliable_endpoint) { + its_info->set_endpoint(its_reliable_endpoint, true); + its_reliable_endpoint->increment_use_count(); + service_instances_[_service][its_reliable_endpoint.get()] = + _instance; + } + } - if (ILLEGAL_PORT != its_unreliable_port) { - its_unreliable_endpoint = find_or_create_server_endpoint( - its_unreliable_port, false); - its_info->set_endpoint(its_unreliable_endpoint, false); + if (ILLEGAL_PORT != its_unreliable_port) { + its_unreliable_endpoint = find_or_create_server_endpoint( + its_unreliable_port, false, is_someip); + if (its_unreliable_endpoint) { + its_info->set_endpoint(its_unreliable_endpoint, false); + its_unreliable_endpoint->increment_use_count(); + service_instances_[_service][its_unreliable_endpoint.get()] = + _instance; + } + } - service_instances_[_service][its_unreliable_endpoint.get()] = - _instance; + if (ILLEGAL_PORT == its_reliable_port + && ILLEGAL_PORT == its_unreliable_port) { + VSOMEIP_DEBUG << "Port configuration missing for [" + << std::hex << _service << "." << _instance + << "]. Service is internal."; + } } - if (ILLEGAL_PORT != its_reliable_port - || ILLEGAL_PORT != its_unreliable_port) { - std::string its_servicegroup = configuration_->get_group(_service, - _instance); - auto found_servicegroup = servicegroups_.find(its_servicegroup); - if (found_servicegroup == servicegroups_.end()) { - servicegroups_[its_servicegroup] = - std::make_shared(its_servicegroup, - configuration_->is_local_servicegroup(its_servicegroup)); - } - servicegroups_[its_servicegroup]->add_service(_service, _instance, - its_info); + { + std::lock_guard its_lock(services_mutex_); services_[_service][_instance] = its_info; - } else { - VSOMEIP_DEBUG << "Port configuration missing. Assuming internal service."; } } else { host_->on_error(error_code_e::CONFIGURATION_MISSING); @@ -898,13 +1123,17 @@ std::shared_ptr routing_manager_impl::create_service( std::shared_ptr routing_manager_impl::create_client_endpoint( const boost::asio::ip::address &_address, uint16_t _port, - bool _reliable, client_t _client) { + bool _reliable, client_t _client, bool _start) { + (void)_client; + std::shared_ptr its_endpoint; try { if (_reliable) { its_endpoint = std::make_shared( shared_from_this(), - boost::asio::ip::tcp::endpoint(_address, _port), io_); + boost::asio::ip::tcp::endpoint(_address, _port), io_, + configuration_->get_message_size_reliable( + _address.to_string(), _port)); if (configuration_->has_enabled_magic_cookies(_address.to_string(), _port)) { @@ -915,9 +1144,8 @@ std::shared_ptr routing_manager_impl::create_client_endpoint( shared_from_this(), boost::asio::ip::udp::endpoint(_address, _port), io_); } - - client_endpoints_[_address][_port][_client][_reliable] = its_endpoint; - its_endpoint->start(); + if (_start) + its_endpoint->start(); } catch (...) { host_->on_error(error_code_e::CLIENT_ENDPOINT_CREATION_FAILED); } @@ -925,63 +1153,38 @@ std::shared_ptr routing_manager_impl::create_client_endpoint( return (its_endpoint); } -std::shared_ptr routing_manager_impl::find_client_endpoint( - const boost::asio::ip::address &_address, uint16_t _port, - bool _reliable, client_t _client) { - std::shared_ptr its_endpoint; - auto found_address = client_endpoints_.find(_address); - if (found_address != client_endpoints_.end()) { - auto found_port = found_address->second.find(_port); - if (found_port != found_address->second.end()) { - auto found_client = found_port->second.find(_client); - if (found_client != found_port->second.end()) { - auto found_endpoint = found_client->second.find(_reliable); - if (found_endpoint != found_client->second.end()) { - its_endpoint = found_endpoint->second; - } - } - } - } - return (its_endpoint); -} - -std::shared_ptr routing_manager_impl::find_or_create_client_endpoint( - const boost::asio::ip::address &_address, uint16_t _port, - bool _reliable, client_t _client) { - std::lock_guard its_lock(endpoint_mutex_); - std::shared_ptr its_endpoint = find_client_endpoint(_address, - _port, _reliable, _client); - if (0 == its_endpoint) { - its_endpoint = create_client_endpoint(_address, _port, _reliable, _client); - } - return (its_endpoint); -} - std::shared_ptr routing_manager_impl::create_server_endpoint( - uint16_t _port, bool _reliable) { + uint16_t _port, bool _reliable, bool _start) { + std::lock_guard its_lock(endpoint_mutex_); std::shared_ptr its_endpoint; - try { - boost::asio::ip::address its_unicast = configuration_->get_unicast(); - if (_reliable) { - its_endpoint = std::make_shared( - shared_from_this(), - boost::asio::ip::tcp::endpoint(its_unicast, _port), io_); - if (configuration_->has_enabled_magic_cookies( - its_unicast.to_string(), _port)) { - its_endpoint->enable_magic_cookies(); - } - } else { - // TODO: this should be more specific. - if (its_unicast.is_v4()) { - its_unicast = boost::asio::ip::address_v4::any(); + boost::asio::ip::address its_unicast = configuration_->get_unicast_address(); + if (_start) { + if (_reliable) { + its_endpoint = std::make_shared( + shared_from_this(), + boost::asio::ip::tcp::endpoint(its_unicast, _port), io_, + configuration_->get_message_size_reliable( + its_unicast.to_string(), _port)); + if (configuration_->has_enabled_magic_cookies( + its_unicast.to_string(), _port)) { + its_endpoint->enable_magic_cookies(); + } } else { - // TODO: how is "ANY" specified in IPv6? + 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(); + } + boost::asio::ip::udp::endpoint ep(its_unicast, _port); + its_endpoint = std::make_shared( + shared_from_this(), + ep, io_); } - boost::asio::ip::udp::endpoint ep(its_unicast, _port); - its_endpoint = std::make_shared( - shared_from_this(), - ep, io_); + + } else { + its_endpoint = std::make_shared( + its_unicast.to_string(), _port, _reliable); } if (its_endpoint) { @@ -999,6 +1202,7 @@ std::shared_ptr routing_manager_impl::create_server_endpoint( std::shared_ptr routing_manager_impl::find_server_endpoint( uint16_t _port, bool _reliable) { std::shared_ptr its_endpoint; + std::lock_guard its_lock(endpoint_mutex_); auto found_port = server_endpoints_.find(_port); if (found_port != server_endpoints_.end()) { auto found_endpoint = found_port->second.find(_reliable); @@ -1010,12 +1214,11 @@ std::shared_ptr routing_manager_impl::find_server_endpoint( } std::shared_ptr routing_manager_impl::find_or_create_server_endpoint( - uint16_t _port, bool _reliable) { - std::lock_guard its_lock(endpoint_mutex_); + uint16_t _port, bool _reliable, bool _start) { std::shared_ptr its_endpoint = find_server_endpoint(_port, _reliable); if (0 == its_endpoint) { - its_endpoint = create_server_endpoint(_port, _reliable); + its_endpoint = create_server_endpoint(_port, _reliable, _start); } return (its_endpoint); } @@ -1038,7 +1241,7 @@ std::shared_ptr routing_manager_impl::create_local(client_t _client) { #ifdef WIN32 boost::asio::ip::address address = boost::asio::ip::address::from_string("127.0.0.1"); - int port = 51235 + _client; + int port = VSOMEIP_INTERNAL_BASE_PORT + _client; #endif std::shared_ptr its_endpoint = std::make_shared< @@ -1048,7 +1251,7 @@ std::shared_ptr routing_manager_impl::create_local(client_t _client) { #else boost::asio::local::stream_protocol::endpoint(its_path.str()) #endif - , io_); + , io_, configuration_->get_max_message_size_local()); local_clients_[_client] = its_endpoint; its_endpoint->start(); return (its_endpoint); @@ -1144,26 +1347,35 @@ instance_t routing_manager_impl::find_instance(service_t _service, std::shared_ptr routing_manager_impl::create_remote_client( service_t _service, instance_t _instance, bool _reliable, client_t _client) { std::shared_ptr its_endpoint; - auto found_service = remote_services_.find(_service); - if (found_service != remote_services_.end()) { + std::shared_ptr its_endpoint_def; + auto found_service = remote_service_info_.find(_service); + if (found_service != remote_service_info_.end()) { auto found_instance = found_service->second.find(_instance); if (found_instance != found_service->second.end()) { - for (auto its_client : found_instance->second) { - auto found_reliability = its_client.second.find(_reliable); - if (found_reliability != its_client.second.end()) { - std::shared_ptr endpoint = found_reliability->second; - boost::asio::ip::address address; - endpoint->get_remote_address(address); - its_endpoint = find_or_create_client_endpoint(address, - endpoint->get_remote_port(), _reliable, _client); - break; - } + auto found_reliability = found_instance->second.find(_reliable); + if (found_reliability != found_instance->second.end()) { + its_endpoint_def = found_reliability->second; + its_endpoint = create_client_endpoint( + its_endpoint_def->get_address(), + its_endpoint_def->get_port(), _reliable, _client, + configuration_->is_someip(_service, _instance) + ); } } } if (its_endpoint) { - remote_services_[_service][_instance][_client][_reliable] = its_endpoint; service_instances_[_service][its_endpoint.get()] = _instance; + remote_services_[_service][_instance][_client][_reliable] = its_endpoint; + if (_client == VSOMEIP_ROUTING_CLIENT) { + client_endpoints_by_ip_[its_endpoint_def->get_address()] + [its_endpoint_def->get_port()] + [_reliable] = its_endpoint; + // Set the basic route to the service in the service info + auto found_service_info = find_service(_service, _instance); + if (found_service_info) { + found_service_info->set_endpoint(its_endpoint, _reliable); + } + } } return its_endpoint; } @@ -1185,6 +1397,41 @@ std::shared_ptr routing_manager_impl::find_remote_client( } } } + if(its_endpoint || _client != VSOMEIP_ROUTING_CLIENT) { + return its_endpoint; + } + + // If another service is hosted on the same server_endpoint + // reuse the existing client_endpoint. + auto found_service_info = remote_service_info_.find(_service); + if(found_service_info != remote_service_info_.end()) { + auto found_instance = found_service_info->second.find(_instance); + if(found_instance != found_service_info->second.end()) { + auto found_reliable = found_instance->second.find(_reliable); + if(found_reliable != found_instance->second.end()) { + std::shared_ptr its_ep_def = + found_reliable->second; + auto found_address = client_endpoints_by_ip_.find( + its_ep_def->get_address()); + if(found_address != client_endpoints_by_ip_.end()) { + auto found_port = found_address->second.find( + its_ep_def->get_remote_port()); + if(found_port != found_address->second.end()) { + auto found_reliable2 = found_port->second.find( + _reliable); + if(found_reliable2 != found_port->second.end()) { + its_endpoint = found_reliable2->second; + // store the endpoint under this service/instance id + // as well - needed for later cleanup + remote_services_[_service][_instance][_client][_reliable] = + its_endpoint; + service_instances_[_service][its_endpoint.get()] = _instance; + } + } + } + } + } + } return its_endpoint; } @@ -1220,190 +1467,203 @@ std::set > routing_manager_impl::find_events( return (its_events); } -void routing_manager_impl::add_routing_info(service_t _service, - instance_t _instance, major_version_t _major, minor_version_t _minor, - ttl_t _ttl, const boost::asio::ip::address &_address, uint16_t _port, - bool _reliable) { - std::shared_ptr its_info(find_service(_service, _instance)); - if (!its_info) { - its_info = create_service(_service, _instance, _major, _minor, _ttl); - services_[_service][_instance] = its_info; - } - // If host doesn't have a specific endpoint we create it here - if (specific_endpoint_clients.find(get_client()) == specific_endpoint_clients.end()) { - std::shared_ptr its_endpoint( - find_or_create_client_endpoint(_address, _port, _reliable, VSOMEIP_ROUTING_CLIENT)); - its_info->set_endpoint(its_endpoint, _reliable); +bool routing_manager_impl::is_field(service_t _service, instance_t _instance, + event_t _event) const { + auto find_service = events_.find(_service); + if (find_service != events_.end()) { + auto find_instance = find_service->second.find(_instance); + if (find_instance != find_service->second.end()) { + auto find_event = find_instance->second.find(_event); + if (find_event != find_instance->second.end()) + return find_event->second->is_field(); + } + } + return false; +} - remote_services_[_service][_instance][VSOMEIP_ROUTING_CLIENT][_reliable] = its_endpoint; - service_instances_[_service][its_endpoint.get()] = _instance; +void routing_manager_impl::add_routing_info( + service_t _service, instance_t _instance, + major_version_t _major, minor_version_t _minor, ttl_t _ttl, + const boost::asio::ip::address &_reliable_address, + uint16_t _reliable_port, + const boost::asio::ip::address &_unreliable_address, + uint16_t _unreliable_port) { - if (its_endpoint->is_connected()) { - host_->on_availability(_service, _instance, true); + // Create/Update service info + std::shared_ptr its_info(find_service(_service, _instance)); + if (!its_info) { + boost::asio::ip::address its_unicast_address + = configuration_->get_unicast_address(); + bool is_local(false); + if (_reliable_port != ILLEGAL_PORT + && its_unicast_address == _reliable_address) + is_local = true; + else if (_unreliable_port != ILLEGAL_PORT + && its_unicast_address == _unreliable_address) + is_local = true; + + its_info = create_service_info(_service, _instance, _major, _minor, _ttl, is_local); + { + std::lock_guard its_lock(services_mutex_); + services_[_service][_instance] = its_info; } + } else { + its_info->set_ttl(_ttl); } - // Create all specific endpoints for proxies probably like them - for (client_t client : specific_endpoint_clients) { - std::shared_ptr its_endpoint( - find_or_create_client_endpoint(_address, _port, _reliable, client)); + // Check whether remote services are unchanged + bool is_reliable_known(false); + bool is_unreliable_known(false); - if (client == get_client()) { - its_info->set_endpoint(its_endpoint, _reliable); + auto found_service = remote_service_info_.find(_service); + if (found_service != remote_service_info_.end()) { + auto found_instance = found_service->second.find(_instance); + if (found_instance != found_service->second.end()) { + std::shared_ptr its_definition; + if (_reliable_port != ILLEGAL_PORT) { + auto found_reliable = found_instance->second.find(true); + if (found_reliable != found_instance->second.end()) { + its_definition = found_reliable->second; + if (its_definition->get_address() == _reliable_address + && its_definition->get_port() == _reliable_port) { + is_reliable_known = true; + } + } else { + VSOMEIP_WARNING << "Reliable service endpoint has changed!"; + } + } + if (_unreliable_port != ILLEGAL_PORT) { + auto found_unreliable = found_instance->second.find(false); + if (found_unreliable != found_instance->second.end()) { + its_definition = found_unreliable->second; + if (its_definition->get_address() == _unreliable_address + && its_definition->get_port() == _unreliable_port) { + is_unreliable_known = true; + } else { + VSOMEIP_WARNING << "Unreliable service endpoint has changed!"; + } + } + } } + } - remote_services_[_service][_instance][client][_reliable] = its_endpoint; - service_instances_[_service][its_endpoint.get()] = _instance; + // Add endpoint(s) if necessary + bool is_added(false); + if (_reliable_port != ILLEGAL_PORT && !is_reliable_known) { + std::shared_ptr endpoint_def + = endpoint_definition::get(_reliable_address, _reliable_port, true); + remote_service_info_[_service][_instance][true] = endpoint_def; + is_added = !is_unreliable_known; + } - if (its_endpoint->is_connected()) { - host_->on_availability(_service, _instance, true); - } + if (_unreliable_port != ILLEGAL_PORT && !is_unreliable_known) { + std::shared_ptr endpoint_def + = endpoint_definition::get(_unreliable_address, _unreliable_port, false); + remote_service_info_[_service][_instance][false] = endpoint_def; + is_added = !is_reliable_known; } - stub_->on_offer_service(VSOMEIP_ROUTING_CLIENT, _service, _instance); + if (is_added) { + host_->on_availability(_service, _instance, true); + stub_->on_offer_service(VSOMEIP_ROUTING_CLIENT, _service, _instance); + } } -void routing_manager_impl::del_routing_info(service_t _service, - instance_t _instance, - bool _reliable) { - std::shared_ptr its_info(find_service(_service, _instance)); - if (its_info) { - std::shared_ptr its_empty_endpoint; +void routing_manager_impl::del_routing_info(service_t _service, instance_t _instance, + bool _has_reliable, bool _has_unreliable) { - // TODO: only tell the application if the service is completely gone - host_->on_availability(_service, _instance, false); - stub_->on_stop_offer_service(VSOMEIP_ROUTING_CLIENT, _service, - _instance); + host_->on_availability(_service, _instance, false); + stub_->on_stop_offer_service(VSOMEIP_ROUTING_CLIENT, _service, _instance); - // Implicit unsubscribe - auto found_service = eventgroups_.find(_service); - if (found_service != eventgroups_.end()) { - auto found_instance = found_service->second.find(_instance); - if (found_instance != found_service->second.end()) { - for (auto &its_eventgroup : found_instance->second) { - its_eventgroup.second->clear_targets(); - } + // Implicit unsubscribe + auto found_service = eventgroups_.find(_service); + if (found_service != eventgroups_.end()) { + auto found_instance = found_service->second.find(_instance); + if (found_instance != found_service->second.end()) { + for (auto &its_eventgroup : found_instance->second) { + its_eventgroup.second->clear_targets(); } } + } - std::shared_ptr its_endpoint = its_info->get_endpoint( - _reliable); - if (its_endpoint) { - if (1 >= service_instances_[_service].size()) { - service_instances_.erase(_service); - } else { - service_instances_[_service].erase(its_endpoint.get()); - } + if (_has_reliable) + clear_client_endpoints(_service, _instance, true); + if (_has_unreliable) + clear_client_endpoints(_service, _instance, false); - remote_services_[_service][_instance].erase(_reliable); - auto found_endpoint = remote_services_[_service][_instance].find( - !_reliable); - if (found_endpoint == remote_services_[_service][_instance].end()) { - remote_services_[_service].erase(_instance); - } - if (1 >= remote_services_[_service].size()) { - remote_services_.erase(_service); - } - } + clear_multicast_endpoints(_service, _instance); - if (!its_info->get_endpoint(!_reliable)) { - if (its_info->get_group()) { - its_info->get_group()->remove_service(_service, _instance); - if (1 >= services_[_service].size()) { - services_.erase(_service); + if (_has_reliable) + clear_service_info(_service, _instance, true); + if (_has_unreliable) + clear_service_info(_service, _instance, false); +} + +ttl_t routing_manager_impl::update_routing_info(ttl_t _elapsed) { + ttl_t its_smallest_ttl(DEFAULT_TTL); + std::map > > its_expired_offers; + + for (auto &s : services_) { + for (auto &i : s.second) { + ttl_t its_ttl = i.second->get_ttl(); + if (its_ttl < DEFAULT_TTL) { // do not touch "forever" + if (its_ttl < _elapsed || its_ttl == 0) { + i.second->set_ttl(0); + if (discovery_) + discovery_->unsubscribe_all(s.first, i.first); + its_expired_offers[s.first][i.first] = { + i.second->get_endpoint(true) != nullptr, + i.second->get_endpoint(false) != nullptr + }; } else { - services_[_service].erase(_instance); + ttl_t its_new_ttl(its_ttl - _elapsed); + i.second->set_ttl(its_new_ttl); + if (its_smallest_ttl > its_new_ttl) + its_smallest_ttl = its_new_ttl; } } - } else { - its_info->set_endpoint(its_empty_endpoint, _reliable); } } -} - -void routing_manager_impl::init_routing_info() { - VSOMEIP_INFO<< "Service Discovery disabled. Using static routing information."; - for (auto i : configuration_->get_remote_services()) { - std::string its_address = configuration_->get_unicast(i.first, i.second); - uint16_t its_reliable = configuration_->get_reliable_port(i.first, - i.second); - uint16_t its_unreliable = configuration_->get_unreliable_port(i.first, - i.second); - - if (VSOMEIP_INVALID_PORT != its_reliable) { - VSOMEIP_DEBUG << "Initializing route to service [" - << std::hex << i.first << "." << i.second << "]"; - add_routing_info(i.first, i.second, DEFAULT_MAJOR, DEFAULT_MINOR, - DEFAULT_TTL, - boost::asio::ip::address::from_string(its_address), - its_reliable, true); - } - if (VSOMEIP_INVALID_PORT != its_unreliable) { - add_routing_info(i.first, i.second, DEFAULT_MAJOR, DEFAULT_MINOR, - DEFAULT_TTL, - boost::asio::ip::address::from_string(its_address), - its_unreliable, false); + for (auto &s : its_expired_offers) { + for (auto &i : s.second) { + del_routing_info(s.first, i.first, i.second.first, i.second.second); } } + + return its_smallest_ttl; } -void routing_manager_impl::init_event_routing_info() { - // TODO: the following should be done before(!) initializing - // the configuration object to allow the configuration to - // directly write to the target structure! - std::map > > its_events = - configuration_->get_events(); - for (auto i : its_events) { - for (auto j : i.second) { - for (auto k : j.second) { - std::shared_ptr its_event(std::make_shared(this)); - its_event->set_service(i.first); - its_event->set_instance(j.first); - its_event->set_event(k); - configuration_->set_event(its_event); // sets is_field/is_reliable - events_[i.first][j.first][k] = its_event; +void routing_manager_impl::init_routing_info() { + VSOMEIP_INFO<< "Service Discovery disabled. Using static routing information."; + for (auto i : configuration_->get_remote_services()) { + boost::asio::ip::address its_address( + boost::asio::ip::address::from_string( + configuration_->get_unicast_address(i.first, i.second))); + uint16_t its_reliable_port + = configuration_->get_reliable_port(i.first, i.second); + uint16_t its_unreliable_port + = configuration_->get_unreliable_port(i.first, i.second); + + if (its_reliable_port != ILLEGAL_PORT + || its_unreliable_port != ILLEGAL_PORT) { + + add_routing_info(i.first, i.second, + DEFAULT_MAJOR, DEFAULT_MINOR, DEFAULT_TTL, + its_address, its_reliable_port, + its_address, its_unreliable_port); + + if(its_reliable_port != ILLEGAL_PORT) { + find_or_create_remote_client(i.first, i.second, true, VSOMEIP_ROUTING_CLIENT); } - } - } - - std::map > > > its_eventgroups = - configuration_->get_eventgroups(); - for (auto i : its_eventgroups) { - for (auto j : i.second) { - for (auto k : j.second) { - eventgroups_[i.first][j.first][k.first] = std::make_shared< - eventgroupinfo>(); - for (auto l : k.second) { - std::shared_ptr its_event = find_event(i.first, - j.first, l); - if (its_event) { - eventgroups_[i.first][j.first][k.first]->add_event( - its_event); - its_event->add_eventgroup(k.first); - } - } + if(its_unreliable_port != ILLEGAL_PORT) { + find_or_create_remote_client(i.first, i.second, false, VSOMEIP_ROUTING_CLIENT); } } } - -#if 0 - for (auto i : eventgroups_) { - for (auto j : i.second) { - for (auto k : j.second) { - VSOMEIP_DEBUG<< "Eventgroup [" << std::hex << std::setw(4) - << std::setfill('0') << i.first << "." << j.first << "." << k.first - << "]"; - for (auto l : k.second->get_events()) { - VSOMEIP_DEBUG << " Event " << std::hex << std::setw(4) - << std::setfill('0') << l->get_event(); - } - } - } - } -#endif } void routing_manager_impl::on_subscribe( @@ -1413,42 +1673,47 @@ void routing_manager_impl::on_subscribe( std::shared_ptr its_eventgroup = find_eventgroup(_service, _instance, _eventgroup); if (its_eventgroup) { - std::shared_ptr < eventgroupinfo > its_info = find_eventgroup( - _service, _instance, _eventgroup); - client_t client = 0; - if (!its_info->is_multicast()) { + if (!its_eventgroup->is_multicast()) { if (!_target->is_reliable()) { uint16_t unreliable_port = configuration_->get_unreliable_port(_service, _instance); - auto endpoint = find_or_create_server_endpoint(unreliable_port, false); - client = std::dynamic_pointer_cast(endpoint)->get_client(_target); _target->set_remote_port(unreliable_port); + auto endpoint = find_server_endpoint(unreliable_port, false); + if (endpoint) { + client = std::dynamic_pointer_cast(endpoint)-> + get_client(_target); + } } else { uint16_t reliable_port = configuration_->get_reliable_port(_service, _instance); - auto endpoint = find_or_create_server_endpoint(reliable_port, true); - client = std::dynamic_pointer_cast(endpoint)->get_client(_target); + auto endpoint = find_server_endpoint(reliable_port, true); _target->set_remote_port(reliable_port); + if (endpoint) { + client = std::dynamic_pointer_cast(endpoint)-> + get_client(_target); + } } } if(!host_->on_subscription(_service, _instance, _eventgroup, client, true)) { VSOMEIP_INFO << "Subscription request for eventgroup " << _eventgroup - << " rejected from application handler"; + << " rejected from application handler"; return; } VSOMEIP_DEBUG << "on_subscribe: target=" << _target->get_address().to_string() - << ":" <<_target->get_port() << ":Client=" << std::hex << client; + << ":" << std::dec <<_target->get_port() << ":Client=" << std::hex + << client << (_target->is_reliable() ? " reliable" : " unreliable"); - send_subscribe(client, _service, _instance, _eventgroup, 0, 0); + send_subscribe(client, _service, _instance, _eventgroup, its_eventgroup->get_major()); remote_subscriber_map_[client] = _target; - its_eventgroup->add_target(_target); // unicast or multicast - for (auto its_event : its_eventgroup->get_events()) { - if (its_event->is_field()) { - its_event->notify_one(_subscriber); // unicast + if (its_eventgroup->add_target(_target)) { // unicast or multicast + for (auto its_event : its_eventgroup->get_events()) { + if (its_event->is_field()) { + its_event->notify_one(_subscriber); // unicast + } } } } else { @@ -1462,28 +1727,30 @@ void routing_manager_impl::on_unsubscribe(service_t _service, std::shared_ptr its_eventgroup = find_eventgroup(_service, _instance, _eventgroup); if (its_eventgroup) { - std::shared_ptr < eventgroupinfo > its_info = find_eventgroup( - _service, _instance, _eventgroup); - client_t client = 0; - if (!its_info->is_multicast()) { + if (!its_eventgroup->is_multicast()) { if (!_target->is_reliable()) { - uint16_t unreliable_port = _target->get_remote_port(); - auto endpoint = find_or_create_server_endpoint(unreliable_port, false); - client = std::dynamic_pointer_cast(endpoint)-> - get_client(_target); + 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(endpoint)-> + get_client(_target); + } } else { - uint16_t reliable_port = _target->get_remote_port(); - auto endpoint = find_or_create_server_endpoint(reliable_port, true); - client = std::dynamic_pointer_cast(endpoint)-> - get_client(_target); + 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(endpoint)-> + get_client(_target); + } } } VSOMEIP_DEBUG << "on_unsubscribe: target=" << _target->get_address().to_string() - << ":" <<_target->get_port() << ":Client=" << std::hex << client; + << ":" << std::dec <<_target->get_port() << ":Client=" << std::hex + << client << (_target->is_reliable() ? " reliable" : " unreliable");; - its_eventgroup->del_target(_target); + its_eventgroup->remove_target(_target); if (remote_subscriber_map_.find(client) != remote_subscriber_map_.end()) { remote_subscriber_map_.erase(client); @@ -1498,11 +1765,31 @@ void routing_manager_impl::on_unsubscribe(service_t _service, void routing_manager_impl::on_subscribe_ack(service_t _service, instance_t _instance, const boost::asio::ip::address &_address, uint16_t _port) { - // TODO: find a way of getting rid of the following endpoint in - // case it is used for multicast exclusively and the subscription - // is withdrawn or the service got lost - std::shared_ptr its_endpoint = find_or_create_server_endpoint( - _port, false); + + if (multicast_info.find(_service) != multicast_info.end()) { + if (multicast_info[_service].find(_instance) != multicast_info[_service].end()) { + auto endpoint_def = multicast_info[_service][_instance]; + if (endpoint_def->get_address() == _address && + endpoint_def->get_port() == _port) { + + // Multicast info and endpoint already created before + // This can happen when more than one client subscribe on the same instance! + return; + } + } + } + + // Save multicast info to be able to delete the endpoint + // as soon as the instance stops offering its service + std::shared_ptr endpoint_def = + endpoint_definition::get(_address, _port, false); + multicast_info[_service][_instance] = endpoint_def; + + bool is_someip = configuration_->is_someip(_service, _instance); + + // Create multicast endpoint & join multicase group + std::shared_ptr its_endpoint + = find_or_create_server_endpoint(_port, false, is_someip); if (its_endpoint) { service_instances_[_service][its_endpoint.get()] = _instance; its_endpoint->join(_address.to_string()); @@ -1513,7 +1800,7 @@ void routing_manager_impl::on_subscribe_ack(service_t _service, void routing_manager_impl::send_subscribe(client_t _client, service_t _service, instance_t _instance, eventgroup_t _eventgroup, - major_version_t _major, ttl_t _ttl) { + major_version_t _major) { byte_t its_command[VSOMEIP_SUBSCRIBE_COMMAND_SIZE]; uint32_t its_size = VSOMEIP_SUBSCRIBE_COMMAND_SIZE @@ -1531,8 +1818,6 @@ void routing_manager_impl::send_subscribe(client_t _client, service_t _service, std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 4], &_eventgroup, sizeof(_eventgroup)); its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 6] = _major; - std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 7], &_ttl, - sizeof(_ttl)); std::shared_ptr target = find_local(_service, _instance); if (target) { @@ -1565,5 +1850,326 @@ void routing_manager_impl::send_unsubscribe(client_t _client, service_t _service } } +bool routing_manager_impl::insert_subscription( + service_t _service, instance_t _instance, eventgroup_t _eventgroup, + client_t _client) { + + auto found_service = eventgroup_clients_.find(_service); + if (found_service != eventgroup_clients_.end()) { + auto found_instance = found_service->second.find(_instance); + if (found_instance != found_service->second.end()) { + auto found_eventgroup = found_instance->second.find(_eventgroup); + if (found_eventgroup != found_instance->second.end()) { + if (found_eventgroup->second.find(_client) + != found_eventgroup->second.end()) + return false; + } + } + } + + eventgroup_clients_[_service][_instance][_eventgroup].insert(_client); + return true; +} + + +bool routing_manager_impl::deliver_specific_endpoint_message(service_t _service, + instance_t _instance, const byte_t *_data, length_t _size, endpoint *_receiver) { + // Try to deliver specific endpoint message (for selective subscribers) + auto found_servic = remote_services_.find(_service); + if (found_servic != remote_services_.end()) { + auto found_instance = found_servic->second.find(_instance); + if (found_instance != found_servic->second.end()) { + for (auto client_entry : found_instance->second) { + client_t client = client_entry.first; + if (!client) { + continue; + } + auto found_reliability = client_entry.second.find(_receiver->is_reliable()); + if (found_reliability != client_entry.second.end()) { + auto found_enpoint = found_reliability->second; + if (found_enpoint.get() == _receiver) { + auto local_endpoint = find_local(client); + if (client != get_client()) { + send_local(local_endpoint, client, _data, _size, _instance, true, _receiver->is_reliable()); + } else { + deliver_message(_data, _size, _instance, _receiver->is_reliable()); + } + return true; + } + } + } + } + } + + return false; +} + +void routing_manager_impl::clear_client_endpoints(service_t _service, instance_t _instance, + bool _reliable) { + std::lock_guard its_lock(endpoint_mutex_); + std::shared_ptr deleted_endpoint; + // Clear client endpoints for remote services (generic and specific ones) + if (remote_services_.find(_service) != remote_services_.end()) { + if (remote_services_[_service].find(_instance) != remote_services_[_service].end()) { + auto endpoint = remote_services_[_service][_instance][VSOMEIP_ROUTING_CLIENT][_reliable]; + if (endpoint) { + service_instances_[_service].erase(endpoint.get()); + deleted_endpoint = endpoint; + } + remote_services_[_service][_instance][VSOMEIP_ROUTING_CLIENT].erase(_reliable); + auto found_endpoint = remote_services_[_service][_instance][VSOMEIP_ROUTING_CLIENT].find( + !_reliable); + if (found_endpoint == remote_services_[_service][_instance][VSOMEIP_ROUTING_CLIENT].end()) { + remote_services_[_service][_instance].erase(VSOMEIP_ROUTING_CLIENT); + } + } + } + for (client_t client : specific_endpoint_clients) { + if (remote_services_.find(_service) != remote_services_.end()) { + if (remote_services_[_service].find(_instance) != remote_services_[_service].end()) { + auto endpoint = remote_services_[_service][_instance][client][_reliable]; + if (endpoint) { + service_instances_[_service].erase(endpoint.get()); + endpoint->stop(); + } + remote_services_[_service][_instance][client].erase(_reliable); + auto found_endpoint = remote_services_[_service][_instance][client].find(!_reliable); + if (found_endpoint == remote_services_[_service][_instance][client].end()) { + remote_services_[_service][_instance].erase(client); + } + } + } + } + if (remote_services_.find(_service) != remote_services_.end()) { + if (remote_services_[_service].find(_instance) != remote_services_[_service].end()) { + if (!remote_services_[_service][_instance].size()) { + remote_services_[_service].erase(_instance); + if (0 >= remote_services_[_service].size()) { + remote_services_.erase(_service); + } + } + } + } + // Clear remote_service_info_ + if (remote_service_info_.find(_service) != remote_service_info_.end()) { + if (remote_service_info_[_service].find(_instance) != remote_service_info_[_service].end()) { + remote_service_info_[_service][_instance].erase(_reliable); + auto found_endpoint_def = remote_service_info_[_service][_instance].find(!_reliable); + if (found_endpoint_def == remote_service_info_[_service][_instance].end()) { + remote_service_info_[_service].erase(_instance); + if (0 >= remote_service_info_[_service].size()) { + remote_service_info_.erase(_service); + } + } + } + } + + if (1 >= service_instances_[_service].size()) { + service_instances_.erase(_service); + } + if(deleted_endpoint) { + stop_and_delete_client_endpoint(deleted_endpoint); + } +} + +void routing_manager_impl::stop_and_delete_client_endpoint( + std::shared_ptr _endpoint) { + // Only stop and delete the endpoint if none of the services + // reachable through it is online anymore. + bool delete_endpoint(true); + + for (const auto& service : remote_services_) { + for (const auto& instance : service.second) { + const auto& client = instance.second.find(VSOMEIP_ROUTING_CLIENT); + if(client != instance.second.end()) { + for (const auto& reliable : client->second) { + if(reliable.second == _endpoint) { + delete_endpoint = false; + break; + } + } + } + if(!delete_endpoint) { break; } + } + if(!delete_endpoint) { break; } + } + + if(delete_endpoint) { + _endpoint->stop(); + for (auto address = client_endpoints_by_ip_.begin(); + address != client_endpoints_by_ip_.end();) { + for (auto port = address->second.begin(); + port != address->second.end();) { + for (auto reliable = port->second.begin(); + reliable != port->second.end();) { + std::shared_ptr its_endpoint = reliable->second; + if (_endpoint == its_endpoint) { + reliable = port->second.erase(reliable); + } else { + ++reliable; + } + } + if (!port->second.size()) { + port = address->second.erase(port); + } else { + ++port; + } + } + if(!address->second.size()) { + address = client_endpoints_by_ip_.erase(address); + } else { + ++address; + } + } + } +} + +void routing_manager_impl::clear_multicast_endpoints(service_t _service, instance_t _instance) { + std::lock_guard its_lock(endpoint_mutex_); + // Clear multicast info and endpoint and multicast instance (remote service) + if (multicast_info.find(_service) != multicast_info.end()) { + if (multicast_info[_service].find(_instance) != multicast_info[_service].end()) { + std::string address = multicast_info[_service][_instance]->get_address().to_string(); + uint16_t port = multicast_info[_service][_instance]->get_port(); + auto multicast_endpoint = server_endpoints_[port][false]; + multicast_endpoint->leave(address); + multicast_endpoint->stop(); + server_endpoints_[port].erase(false); + if (server_endpoints_[port].find(true) == server_endpoints_[port].end()) { + server_endpoints_.erase(port); + } + multicast_info[_service].erase(_instance); + if (0 >= multicast_info[_service].size()) { + multicast_info.erase(_service); + } + // Clear service_instances_ for multicase endpoint + if (1 >= service_instances_[_service].size()) { + service_instances_.erase(_service); + } else { + service_instances_[_service].erase(multicast_endpoint.get()); + } + } + } +} + +void routing_manager_impl::clear_service_info(service_t _service, instance_t _instance, + bool _reliable) { + std::shared_ptr its_info(find_service(_service, _instance)); + if (!its_info) { + return; + } + // Clear service_info and service_group + std::shared_ptr its_empty_endpoint; + if (!its_info->get_endpoint(!_reliable)) { + if (1 >= services_[_service].size()) { + services_.erase(_service); + } else { + services_[_service].erase(_instance); + } + } else { + its_info->set_endpoint(its_empty_endpoint, _reliable); + } +} + +return_code_e routing_manager_impl::check_error(const byte_t *_data, length_t _size, + instance_t _instance) { + + service_t its_service = VSOMEIP_BYTES_TO_WORD(_data[VSOMEIP_SERVICE_POS_MIN], + _data[VSOMEIP_SERVICE_POS_MAX]); + + if (utility::is_request(_data[VSOMEIP_MESSAGE_TYPE_POS])) { + if (_size >= VSOMEIP_PAYLOAD_POS) { + if (_data[VSOMEIP_PROTOCOL_VERSION_POS] != VSOMEIP_PROTOCOL_VERSION) { + VSOMEIP_WARNING << "Received a message with unsupported protocol version for service 0x" + << std::hex << its_service; + return return_code_e::E_WRONG_PROTOCOL_VERSION; + } + if (_instance == 0xFFFF) { + VSOMEIP_WARNING << "Receiving endpoint is not configured for service 0x" + << std::hex << its_service; + return return_code_e::E_UNKNOWN_SERVICE; + } + // TODO: Check interface version handling?! + if (_data[VSOMEIP_INTERFACE_VERSION_POS] != 0x0) { + // Interface is currently set to zero always! + return return_code_e::E_WRONG_INTERFACE_VERSION; + } + if (_data[VSOMEIP_RETURN_CODE_POS] != static_cast (return_code_e::E_OK)) { + // Request calls must to have return code E_OK set! + return return_code_e::E_NOT_OK; + } + } else { + // Message shorter than vSomeIP message header + return return_code_e::E_MALFORMED_MESSAGE; + } + } + return return_code_e::E_OK; +} + +void routing_manager_impl::send_error(return_code_e _return_code, + const byte_t *_data, length_t _size, + instance_t _instance, bool _reliable, + endpoint *_receiver) { + + client_t its_client = 0; + service_t its_service = 0; + method_t its_method = 0; + session_t its_session = 0; + + if (_size >= VSOMEIP_CLIENT_POS_MAX) { + its_client = VSOMEIP_BYTES_TO_WORD(_data[VSOMEIP_CLIENT_POS_MIN], + _data[VSOMEIP_CLIENT_POS_MAX]); + } + if (_size >= VSOMEIP_SERVICE_POS_MAX) { + its_service = VSOMEIP_BYTES_TO_WORD( + _data[VSOMEIP_SERVICE_POS_MIN], _data[VSOMEIP_SERVICE_POS_MAX]); + } + if (_size >= VSOMEIP_METHOD_POS_MAX) { + its_method = VSOMEIP_BYTES_TO_WORD( + _data[VSOMEIP_METHOD_POS_MIN], _data[VSOMEIP_METHOD_POS_MAX]); + } + if (_size >= VSOMEIP_SESSION_POS_MAX) { + its_session = VSOMEIP_BYTES_TO_WORD(_data[VSOMEIP_SESSION_POS_MIN], + _data[VSOMEIP_SESSION_POS_MAX]); + } + + auto error_message = runtime::get()->create_message(_reliable); + error_message->set_client(its_client); + error_message->set_instance(_instance); + error_message->set_interface_version(0); + error_message->set_message_type(message_type_e::MT_ERROR); + error_message->set_method(its_method); + error_message->set_return_code(_return_code); + error_message->set_service(its_service); + error_message->set_session(its_session); + + std::lock_guard its_lock(serialize_mutex_); + if (serializer_->serialize(error_message.get())) { + if (_receiver) { + boost::asio::ip::address adr; + uint16_t port; + if (_receiver->is_reliable()) { + auto remote = static_cast(_receiver)->get_remote(); + adr = remote.address(); + port = remote.port(); + } else { + auto remote = static_cast(_receiver)->get_remote(); + adr = remote.address(); + port = remote.port(); + } + auto its_endpoint_def = + std::make_shared(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()); + } else { + send(get_client(), serializer_->get_data(), serializer_->get_size(), + _instance, true, _reliable); + } + serializer_->reset(); + } else { + VSOMEIP_ERROR << "Failed to serialize error message."; + } +} + } // namespace vsomeip diff --git a/implementation/routing/src/routing_manager_proxy.cpp b/implementation/routing/src/routing_manager_proxy.cpp index 1df8b90..cbf14ff 100644 --- a/implementation/routing/src/routing_manager_proxy.cpp +++ b/implementation/routing/src/routing_manager_proxy.cpp @@ -6,17 +6,17 @@ #include #include -#include #include -#include #include #include "../include/event.hpp" #include "../include/routing_manager_host.hpp" #include "../include/routing_manager_proxy.hpp" +#include "../../configuration/include/configuration.hpp" #include "../../configuration/include/internal.hpp" #include "../../endpoints/include/local_client_endpoint_impl.hpp" #include "../../endpoints/include/local_server_endpoint_impl.hpp" +#include "../../logging/include/logger.hpp" #include "../../message/include/deserializer.hpp" #include "../../message/include/serializer.hpp" #include "../../service_discovery/include/runtime.hpp" @@ -26,10 +26,17 @@ namespace vsomeip { routing_manager_proxy::routing_manager_proxy(routing_manager_host *_host) : - io_(_host->get_io()), host_(_host), client_(_host->get_client()), sender_( - 0), receiver_(0), serializer_(std::make_shared()), deserializer_( - std::make_shared()), is_connected_(false), is_started_(false), - state_(event_type_e::ET_DEREGISTERED) { + io_(_host->get_io()), + is_connected_(false), + is_started_(false), + state_(state_type_e::ST_DEREGISTERED), + host_(_host), + client_(_host->get_client()), + configuration_(host_->get_configuration()), + serializer_(std::make_shared()), + deserializer_(std::make_shared()), + sender_(0), + receiver_(0) { } routing_manager_proxy::~routing_manager_proxy() { @@ -44,13 +51,7 @@ client_t routing_manager_proxy::get_client() const { } void routing_manager_proxy::init() { - uint32_t its_max_message_size = VSOMEIP_MAX_LOCAL_MESSAGE_SIZE; - if (VSOMEIP_MAX_TCP_MESSAGE_SIZE > its_max_message_size) - its_max_message_size = VSOMEIP_MAX_TCP_MESSAGE_SIZE; - if (VSOMEIP_MAX_UDP_MESSAGE_SIZE > its_max_message_size) - its_max_message_size = VSOMEIP_MAX_UDP_MESSAGE_SIZE; - - serializer_->create_data(its_max_message_size); + serializer_->create_data(configuration_->get_max_message_size_local()); std::stringstream its_sender_path; sender_ = create_local(VSOMEIP_ROUTING_CLIENT); @@ -59,7 +60,7 @@ void routing_manager_proxy::init() { its_client << VSOMEIP_BASE_PATH << std::hex << client_; #ifdef WIN32 ::_unlink(its_client.str().c_str()); - int port = 51235 + client_; + int port = VSOMEIP_INTERNAL_BASE_PORT + client_; #else ::unlink(its_client.str().c_str()); #endif @@ -69,7 +70,7 @@ void routing_manager_proxy::init() { #else boost::asio::local::stream_protocol::endpoint(its_client.str()), #endif - io_); + io_, configuration_->get_max_message_size_local()); #ifdef WIN32 VSOMEIP_DEBUG << "Listening at " << port; @@ -110,13 +111,12 @@ void routing_manager_proxy::stop() { } void routing_manager_proxy::offer_service(client_t _client, service_t _service, - instance_t _instance, major_version_t _major, minor_version_t _minor, - ttl_t _ttl) { + instance_t _instance, major_version_t _major, minor_version_t _minor) { if (is_connected_) { - send_offer_service(_client, _service, _instance, _major, _minor, _ttl); + send_offer_service(_client, _service, _instance, _major, _minor); } else { - service_data_t offer = { _service, _instance, _major, _minor, _ttl }; + service_data_t offer = { _service, _instance, _major, _minor, false }; std::lock_guard its_lock(pending_mutex_); pending_offers_.insert(offer); } @@ -124,7 +124,8 @@ void routing_manager_proxy::offer_service(client_t _client, service_t _service, void routing_manager_proxy::send_offer_service(client_t _client, service_t _service, instance_t _instance, major_version_t _major, - minor_version_t _minor, ttl_t _ttl) { + minor_version_t _minor) { + (void)_client; byte_t its_command[VSOMEIP_OFFER_SERVICE_COMMAND_SIZE]; uint32_t its_size = VSOMEIP_OFFER_SERVICE_COMMAND_SIZE @@ -142,14 +143,13 @@ void routing_manager_proxy::send_offer_service(client_t _client, its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 4] = _major; std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 5], &_minor, sizeof(_minor)); - std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 9], &_ttl, - sizeof(_ttl)); sender_->send(its_command, sizeof(its_command)); } void routing_manager_proxy::stop_offer_service(client_t _client, service_t _service, instance_t _instance) { + (void)_client; if (is_connected_) { byte_t its_command[VSOMEIP_STOP_OFFER_SERVICE_COMMAND_SIZE]; @@ -184,31 +184,109 @@ void routing_manager_proxy::stop_offer_service(client_t _client, void routing_manager_proxy::request_service(client_t _client, service_t _service, instance_t _instance, major_version_t _major, - minor_version_t _minor, ttl_t _ttl, bool _has_selective) { - - is_selective_ = _has_selective; - send_request_service(_client, _service, _instance, _major, _minor, _ttl, _has_selective); + minor_version_t _minor, bool _use_exclusive_proxy) { + send_request_service(_client, _service, _instance, _major, _minor, + _use_exclusive_proxy); } void routing_manager_proxy::release_service(client_t _client, service_t _service, instance_t _instance) { + (void)_client; + (void)_service; + (void)_instance; +} + +void routing_manager_proxy::register_event(client_t _client, + service_t _service, instance_t _instance, + event_t _event, std::set _eventgroups, + bool _is_field, bool _is_provided) { + (void)_client; + + if (_is_field) + fields_[_service][_instance].insert(_event); + + send_register_event(client_, _service, _instance, + _event, _eventgroups, _is_field, _is_provided); +} + +void routing_manager_proxy::unregister_event(client_t _client, + service_t _service, instance_t _instance, event_t _event, + bool _is_provided) { + (void)_client; + auto find_service = fields_.find(_service); + if (find_service != fields_.end()) { + auto find_instance = find_service->second.find(_instance); + if (find_instance != find_service->second.end()) { + find_instance->second.erase(_event); + if (find_instance->second.size() == 0) + find_service->second.erase(find_instance); + } + if (find_service->second.size() == 0) + fields_.erase(find_service); + } + + if (is_connected_) { + 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 + 5] + = static_cast(_is_provided); + + sender_->send(its_command, sizeof(its_command)); + } else { + std::lock_guard its_lock(pending_mutex_); + auto it = pending_event_registrations_.begin(); + while (it != pending_event_registrations_.end()) { + if (it->service_ == _service + && it->instance_ == _instance + && it->event_ == _event) { + break; + } + it++; + } + + if (it != pending_event_registrations_.end()) + pending_event_registrations_.erase(it); + } +} +bool routing_manager_proxy::is_field(service_t _service, instance_t _instance, + event_t _event) const { + auto find_service = fields_.find(_service); + if (find_service != fields_.end()) { + auto find_instance = find_service->second.find(_instance); + if (find_instance != find_service->second.end()) + return (find_instance->second.find(_event) != find_instance->second.end()); + } + return false; } void routing_manager_proxy::subscribe(client_t _client, service_t _service, - instance_t _instance, eventgroup_t _eventgroup, major_version_t _major, - ttl_t _ttl) { + instance_t _instance, eventgroup_t _eventgroup, major_version_t _major) { if (is_connected_) { - send_subscribe(_client, _service, _instance, _eventgroup, _major, _ttl); + send_subscribe(_client, _service, _instance, _eventgroup, _major); } else { - eventgroup_data_t subscription = { _service, _instance, _eventgroup, _major, _ttl }; + eventgroup_data_t subscription = { _service, _instance, _eventgroup, _major }; std::lock_guard its_lock(pending_mutex_); pending_subscriptions_.insert(subscription); } } void routing_manager_proxy::send_subscribe(client_t _client, service_t _service, - instance_t _instance, eventgroup_t _eventgroup, major_version_t _major, - ttl_t _ttl) { + instance_t _instance, eventgroup_t _eventgroup, major_version_t _major) { + (void)_client; + byte_t its_command[VSOMEIP_SUBSCRIBE_COMMAND_SIZE]; uint32_t its_size = VSOMEIP_SUBSCRIBE_COMMAND_SIZE - VSOMEIP_COMMAND_HEADER_SIZE; @@ -225,14 +303,13 @@ void routing_manager_proxy::send_subscribe(client_t _client, service_t _service, std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 4], &_eventgroup, sizeof(_eventgroup)); its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 6] = _major; - std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 7], &_ttl, - sizeof(_ttl)); sender_->send(its_command, sizeof(its_command)); } void routing_manager_proxy::unsubscribe(client_t _client, service_t _service, instance_t _instance, eventgroup_t _eventgroup) { + (void)_client; if (is_connected_) { byte_t its_command[VSOMEIP_UNSUBSCRIBE_COMMAND_SIZE]; @@ -278,6 +355,8 @@ bool routing_manager_proxy::send(client_t its_client, serializer_->get_size(), _message->get_instance(), _flush, _message->is_reliable()); serializer_->reset(); + } else { + VSOMEIP_ERROR << "Failed to serialize message. Check message size!"; } return (is_sent); } @@ -311,7 +390,10 @@ bool routing_manager_proxy::send(client_t _client, const byte_t *_data, std::vector its_command( VSOMEIP_COMMAND_HEADER_SIZE + _size + sizeof(instance_t) + sizeof(bool) + sizeof(bool)); - its_command[VSOMEIP_COMMAND_TYPE_POS] = VSOMEIP_SEND; + its_command[VSOMEIP_COMMAND_TYPE_POS] + = utility::is_notification(_data[VSOMEIP_MESSAGE_TYPE_POS]) ? + VSOMEIP_NOTIFY : VSOMEIP_SEND; + std::memcpy(&its_command[VSOMEIP_COMMAND_CLIENT_POS], &_client, sizeof(client_t)); std::memcpy(&its_command[VSOMEIP_COMMAND_SIZE_POS_MIN], &_size, @@ -323,16 +405,7 @@ bool routing_manager_proxy::send(client_t _client, const byte_t *_data, _flush; its_command[VSOMEIP_COMMAND_PAYLOAD_POS + _size + sizeof(instance_t) + sizeof(bool)] = _reliable; - -#if 0 - std::stringstream msg; - msg << "rmp:send: "; - for (int i = 0; i < its_command.size(); i++) - msg << std::hex << std::setw(2) << std::setfill('0') << (int)its_command[i] << " "; - VSOMEIP_DEBUG << msg.str(); -#endif - - is_sent = its_target->send(&its_command[0], its_command.size()); + is_sent = its_target->send(&its_command[0], uint32_t(its_command.size())); } return (is_sent); } @@ -340,27 +413,32 @@ bool routing_manager_proxy::send(client_t _client, const byte_t *_data, bool routing_manager_proxy::send_to( const std::shared_ptr &_target, std::shared_ptr _message) { + (void)_target; + (void)_message; return (false); } bool routing_manager_proxy::send_to( const std::shared_ptr &_target, const byte_t *_data, uint32_t _size) { + (void)_target; + (void)_data; + (void)_size; return (false); } void routing_manager_proxy::notify( service_t _service, instance_t _instance, event_t _event, std::shared_ptr _payload) { - std::shared_ptr its_notification = runtime::get()->create_request(); - its_notification->set_message_type(message_type_e::MT_REQUEST_NO_RETURN); + std::shared_ptr its_notification + = runtime::get()->create_notification(); its_notification->set_service(_service); its_notification->set_instance(_instance); its_notification->set_method(_event); its_notification->set_payload(_payload); if (is_connected_) { send(VSOMEIP_ROUTING_CLIENT, its_notification, true); - } else { + } else if (is_field(_service, _instance, _event)) { std::lock_guard its_lock(pending_mutex_); pending_notifications_[_service][_instance][_event] = its_notification; } @@ -369,7 +447,8 @@ void routing_manager_proxy::notify( void routing_manager_proxy::notify_one(service_t _service, instance_t _instance, event_t _event, std::shared_ptr _payload, client_t _client) { - std::shared_ptr its_notification = runtime::get()->create_notification(); + std::shared_ptr its_notification + = runtime::get()->create_notification(); its_notification->set_service(_service); its_notification->set_instance(_instance); its_notification->set_method(_event); @@ -388,12 +467,24 @@ void routing_manager_proxy::on_connect(std::shared_ptr _endpoint) { void routing_manager_proxy::on_disconnect(std::shared_ptr _endpoint) { is_connected_ = !(_endpoint == sender_); if (!is_connected_) { - host_->on_event(event_type_e::ET_DEREGISTERED); + host_->on_state(state_type_e::ST_DEREGISTERED); } } +void routing_manager_proxy::on_error(const byte_t *_data, length_t _length, + endpoint *_receiver) { + + // Implement me when needed + + (void)(_data); + (void)(_length); + (void)(_receiver); +} + + void routing_manager_proxy::on_message(const byte_t *_data, length_t _size, endpoint *_receiver) { + (void)_receiver; #if 0 std::stringstream msg; msg << "rmp::on_message: "; @@ -407,9 +498,7 @@ void routing_manager_proxy::on_message(const byte_t *_data, length_t _size, service_t its_service; instance_t its_instance; eventgroup_t its_eventgroup; - //event_t its_event; major_version_t its_major; - minor_version_t its_minor; ttl_t its_ttl; if (_size > VSOMEIP_COMMAND_SIZE_POS_MAX) { @@ -425,15 +514,19 @@ void routing_manager_proxy::on_message(const byte_t *_data, length_t _size, std::memcpy(&its_instance, &_data[_size - sizeof(instance_t) - sizeof(bool) - sizeof(bool)], sizeof(instance_t)); + bool its_reliable; + std::memcpy(&its_reliable, &_data[_size - sizeof(bool)], + sizeof(its_reliable)); deserializer_->set_data(&_data[VSOMEIP_COMMAND_PAYLOAD_POS], its_length); std::shared_ptr its_message( deserializer_->deserialize_message()); if (its_message) { its_message->set_instance(its_instance); + its_message->set_reliable(its_reliable); host_->on_message(its_message); } else { - // TODO: send_error(return_code_e::E_MALFORMED_MESSAGE); + VSOMEIP_ERROR << "Deserialization of vSomeIP message failed"; } deserializer_->reset(); } @@ -487,62 +580,64 @@ void routing_manager_proxy::on_routing_info(const byte_t *_data, msg << std::hex << std::setw(2) << std::setfill('0') << (int)_data[i] << " "; VSOMEIP_DEBUG << msg.str(); #endif - event_type_e its_state(event_type_e::ET_DEREGISTERED); - - std::map > old_local_services = local_services_; - local_services_.clear(); - - uint32_t i = 0; - while (i + sizeof(uint32_t) <= _size) { - uint32_t its_client_size; - std::memcpy(&its_client_size, &_data[i], sizeof(uint32_t)); - i += sizeof(uint32_t); - - if (i + sizeof(client_t) <= _size) { - client_t its_client; - std::memcpy(&its_client, &_data[i], sizeof(client_t)); - i += sizeof(client_t); - - if (its_client != client_) { - (void) find_or_create_local(its_client); - } else { - its_state = event_type_e::ET_REGISTERED; - } + state_type_e its_state(state_type_e::ST_DEREGISTERED); + std::map > old_local_services; + { + std::lock_guard its_lock(local_services_mutex_); + old_local_services = local_services_; + local_services_.clear(); + + uint32_t i = 0; + while (i + sizeof(uint32_t) <= _size) { + uint32_t its_client_size; + std::memcpy(&its_client_size, &_data[i], sizeof(uint32_t)); + i += uint32_t(sizeof(uint32_t)); + + if (i + sizeof(client_t) <= _size) { + client_t its_client; + std::memcpy(&its_client, &_data[i], sizeof(client_t)); + i += uint32_t(sizeof(client_t)); + + if (its_client != client_) { + (void) find_or_create_local(its_client); + } else { + its_state = state_type_e::ST_REGISTERED; + } - uint32_t j = 0; - while (j + sizeof(uint32_t) <= its_client_size) { - uint32_t its_services_size; - std::memcpy(&its_services_size, &_data[i + j], sizeof(uint32_t)); - j += sizeof(uint32_t); + uint32_t j = 0; + while (j + sizeof(uint32_t) <= its_client_size) { + uint32_t its_services_size; + std::memcpy(&its_services_size, &_data[i + j], sizeof(uint32_t)); + j += uint32_t(sizeof(uint32_t)); - if (its_services_size >= sizeof(service_t) + sizeof(instance_t)) { - its_services_size -= sizeof(service_t); + if (its_services_size >= sizeof(service_t) + sizeof(instance_t)) { + its_services_size -= uint32_t(sizeof(service_t)); - service_t its_service; - std::memcpy(&its_service, &_data[i + j], sizeof(service_t)); - j += sizeof(service_t); + service_t its_service; + std::memcpy(&its_service, &_data[i + j], sizeof(service_t)); + j += uint32_t(sizeof(service_t)); - while (its_services_size >= sizeof(instance_t)) { - instance_t its_instance; - std::memcpy(&its_instance, &_data[i + j], sizeof(instance_t)); - j += sizeof(instance_t); + while (its_services_size >= sizeof(instance_t)) { + instance_t its_instance; + std::memcpy(&its_instance, &_data[i + j], sizeof(instance_t)); + j += uint32_t(sizeof(instance_t)); - if (its_client != client_) - local_services_[its_service][its_instance] = its_client; + if (its_client != client_) + local_services_[its_service][its_instance] = its_client; - its_services_size -= sizeof(instance_t); + its_services_size -= uint32_t(sizeof(instance_t)); + } } } - } - i += j; + i += j; + } } } // inform host about its own registration state changes if (state_ != its_state) { - host_->on_event(its_state); + host_->on_state(its_state); state_ = its_state; } @@ -595,7 +690,12 @@ void routing_manager_proxy::register_application() { for (auto &po : pending_offers_) send_offer_service(client_, po.service_, po.instance_, - po.major_, po.minor_, po.ttl_); + po.major_, po.minor_); + + for (auto &per : pending_event_registrations_) + send_register_event(client_, per.service_, per.instance_, + per.event_, per.eventgroups_, + per.is_field_, per.is_provided_); for (auto &s : pending_notifications_) { for (auto &i : s.second) { @@ -607,13 +707,13 @@ void routing_manager_proxy::register_application() { for (auto &po : pending_requests_) { send_request_service(client_, po.service_, po.instance_, - po.major_, po.minor_, po.ttl_, is_selective_); + po.major_, po.minor_, po.use_exclusive_proxy_); } std::lock_guard its_lock(pending_mutex_); for (auto &ps : pending_subscriptions_) send_subscribe(client_, ps.service_, ps.instance_, - ps.eventgroup_, ps.major_, ps.ttl_); + ps.eventgroup_, ps.major_); pending_offers_.clear(); pending_requests_.clear(); @@ -632,7 +732,7 @@ void routing_manager_proxy::deregister_application() { std::memcpy(&its_command[VSOMEIP_COMMAND_SIZE_POS_MIN], &its_size, sizeof(its_size)); if (is_connected_) - (void)sender_->send(&its_command[0], its_command.size()); + (void)sender_->send(&its_command[0], uint32_t(its_command.size())); } std::shared_ptr routing_manager_proxy::find_local(client_t _client) { @@ -651,7 +751,7 @@ std::shared_ptr routing_manager_proxy::create_local( #ifdef WIN32 boost::asio::ip::address address = boost::asio::ip::address::from_string("127.0.0.1"); - int port = 51234; + int port = VSOMEIP_INTERNAL_BASE_PORT + _client; VSOMEIP_DEBUG<< "Connecting to [" << std::hex << _client << "] at " << port; #else @@ -666,7 +766,7 @@ std::shared_ptr routing_manager_proxy::create_local( #else boost::asio::local::stream_protocol::endpoint(its_path.str()), #endif - io_); + io_, configuration_->get_max_message_size_local()); local_endpoints_[_client] = its_endpoint; @@ -693,6 +793,7 @@ void routing_manager_proxy::remove_local(client_t _client) { std::shared_ptr routing_manager_proxy::find_local(service_t _service, instance_t _instance) { client_t its_client(0); + std::lock_guard its_lock(local_services_mutex_); auto found_service = local_services_.find(_service); if (found_service != local_services_.end()) { auto found_instance = found_service->second.find(_instance); @@ -716,35 +817,87 @@ void routing_manager_proxy::send_pong() const { void routing_manager_proxy::send_request_service(client_t _client, service_t _service, instance_t _instance, major_version_t _major, - minor_version_t _minor, ttl_t _ttl, bool _is_selective) { + minor_version_t _minor, bool _use_exclusive_proxy) { + (void)_client; - byte_t its_command[VSOMEIP_REQUEST_SERVICE_COMMAND_SIZE]; - uint32_t its_size = VSOMEIP_REQUEST_SERVICE_COMMAND_SIZE - - VSOMEIP_COMMAND_HEADER_SIZE; + if (is_connected_) { + byte_t its_command[VSOMEIP_REQUEST_SERVICE_COMMAND_SIZE]; + uint32_t its_size = VSOMEIP_REQUEST_SERVICE_COMMAND_SIZE + - VSOMEIP_COMMAND_HEADER_SIZE; - its_command[VSOMEIP_COMMAND_TYPE_POS] = VSOMEIP_REQUEST_SERVICE; - 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)); - its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 4] = _major; - std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 5], &_minor, - sizeof(_minor)); - std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 9], &_ttl, - sizeof(_ttl)); - std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 13], &_is_selective, - sizeof(_is_selective)); + its_command[VSOMEIP_COMMAND_TYPE_POS] = VSOMEIP_REQUEST_SERVICE; + 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)); + its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 4] = _major; + std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 5], &_minor, + sizeof(_minor)); + std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 9], &_use_exclusive_proxy, + sizeof(_use_exclusive_proxy)); - if (is_connected_) { sender_->send(its_command, sizeof(its_command)); } else { - service_data_t offer = { _service, _instance, _major, _minor, _ttl }; + service_data_t request = { _service, _instance, _major, _minor, _use_exclusive_proxy }; + std::lock_guard its_lock(pending_mutex_); + pending_requests_.insert(request); + } +} + +void routing_manager_proxy::send_register_event(client_t _client, + service_t _service, instance_t _instance, + event_t _event, std::set _eventgroups, + bool _is_field, bool _is_provided) { + if (is_connected_) { + uint32_t its_eventgroups_size = uint32_t(_eventgroups.size() * sizeof(eventgroup_t)); + byte_t *its_command = new byte_t[VSOMEIP_REGISTER_EVENT_COMMAND_SIZE + its_eventgroups_size]; + uint32_t its_size = VSOMEIP_REGISTER_EVENT_COMMAND_SIZE + + its_eventgroups_size + - VSOMEIP_COMMAND_HEADER_SIZE; + + its_command[VSOMEIP_COMMAND_TYPE_POS] = VSOMEIP_REGISTER_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(_is_field); + its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 7] + = static_cast(_is_provided); + + std::size_t i = 8; + for (auto eg : _eventgroups) { + std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + i], &eg, + sizeof(eventgroup_t)); + i += sizeof(eventgroup_t); + } + + sender_->send(its_command, + uint32_t(VSOMEIP_REGISTER_EVENT_COMMAND_SIZE + + its_eventgroups_size)); + + delete[] its_command; + } else { + event_data_t registration = { + _service, + _instance, + _event, + _is_field, + _is_provided, + _eventgroups + }; std::lock_guard its_lock(pending_mutex_); - pending_requests_.insert(offer); + pending_event_registrations_.insert(registration); } } diff --git a/implementation/routing/src/routing_manager_stub.cpp b/implementation/routing/src/routing_manager_stub.cpp index 1c3a53c..dfca76f 100644 --- a/implementation/routing/src/routing_manager_stub.cpp +++ b/implementation/routing/src/routing_manager_stub.cpp @@ -11,195 +11,217 @@ #include #include -#include #include #include #include "../include/routing_manager_stub.hpp" #include "../include/routing_manager_stub_host.hpp" +#include "../../configuration/include/configuration.hpp" #include "../../configuration/include/internal.hpp" #include "../../endpoints/include/local_server_endpoint_impl.hpp" +#include "../../logging/include/logger.hpp" #include "../../utility/include/byteorder.hpp" namespace vsomeip { -routing_manager_stub::routing_manager_stub(routing_manager_stub_host *_host) : - host_(_host), io_(_host->get_io()), watchdog_timer_(_host->get_io()) { +routing_manager_stub::routing_manager_stub( + routing_manager_stub_host *_host, + std::shared_ptr _configuration) : + host_(_host), + io_(_host->get_io()), + watchdog_timer_(_host->get_io()), + configuration_(_configuration) { } routing_manager_stub::~routing_manager_stub() { } void routing_manager_stub::init() { - std::stringstream its_endpoint_path; - its_endpoint_path << VSOMEIP_BASE_PATH << VSOMEIP_ROUTING_CLIENT; - endpoint_path_ = its_endpoint_path.str(); + 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 = 51234; - VSOMEIP_DEBUG << "Routing endpoint at " << port; + ::_unlink(endpoint_path_.c_str()); + int port = VSOMEIP_INTERNAL_BASE_PORT; + VSOMEIP_DEBUG << "Routing endpoint at " << port; #else - ::unlink(endpoint_path_.c_str()); - VSOMEIP_DEBUG << "Routing endpoint at " << endpoint_path_; + ::unlink(endpoint_path_.c_str()); + VSOMEIP_DEBUG << "Routing endpoint at " << endpoint_path_; #endif - 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_); + 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()); } void routing_manager_stub::start() { - endpoint_->start(); + endpoint_->start(); - // Start watchdog (TODO: only if configured) - start_watchdog(); + // Start watchdog (TODO: only if configured) + start_watchdog(); } void routing_manager_stub::stop() { - watchdog_timer_.cancel(); - endpoint_->stop(); + watchdog_timer_.cancel(); + endpoint_->stop(); #ifdef WIN32 - ::_unlink(endpoint_path_.c_str()); + ::_unlink(endpoint_path_.c_str()); #else - ::unlink(endpoint_path_.c_str()); + ::unlink(endpoint_path_.c_str()); #endif } void routing_manager_stub::on_connect(std::shared_ptr _endpoint) { - + (void)_endpoint; } void routing_manager_stub::on_disconnect(std::shared_ptr _endpoint) { + (void)_endpoint; +} + +void routing_manager_stub::on_error(const byte_t *_data, length_t _length, + endpoint *_receiver) { + + // Implement me when needed + (void)(_data); + (void)(_length); + (void)(_receiver); } void routing_manager_stub::on_message(const byte_t *_data, length_t _size, - endpoint *_receiver) { + endpoint *_receiver) { + (void)_receiver; #if 0 - std::stringstream msg; - msg << "rms::on_message: "; - for (int i = 0; i < _size; ++i) - msg << std::hex << std::setw(2) << std::setfill('0') << (int)_data[i] << " "; - VSOMEIP_DEBUG << msg.str(); + std::stringstream msg; + msg << "rms::on_message: "; + for (length_t i = 0; i < _size; ++i) + msg << std::hex << std::setw(2) << std::setfill('0') << (int)_data[i] << " "; + VSOMEIP_DEBUG << msg.str(); #endif - if (VSOMEIP_COMMAND_SIZE_POS_MAX < _size) { - byte_t its_command; - client_t its_client; - //session_t its_session; - std::string its_client_endpoint; - service_t its_service; - instance_t its_instance; - eventgroup_t its_eventgroup; - //event_t its_event; - major_version_t its_major; - minor_version_t its_minor; - ttl_t its_ttl; - std::shared_ptr its_payload; - const byte_t *its_data; - uint32_t its_size; - bool its_reliable(false); - bool its_flush(true); - - its_command = _data[VSOMEIP_COMMAND_TYPE_POS]; - std::memcpy(&its_client, &_data[VSOMEIP_COMMAND_CLIENT_POS], - sizeof(its_client)); - - std::memcpy(&its_size, &_data[VSOMEIP_COMMAND_SIZE_POS_MIN], - sizeof(its_size)); - - if (its_size <= _size - VSOMEIP_COMMAND_HEADER_SIZE) { - switch (its_command) { - case VSOMEIP_REGISTER_APPLICATION: - on_register_application(its_client); - VSOMEIP_DEBUG << "Application/Client " - << std::hex << std::setw(4) << std::setfill('0') - << its_client << " got registered!"; - break; - - case VSOMEIP_DEREGISTER_APPLICATION: - on_deregister_application(its_client); - VSOMEIP_DEBUG << "Application/Client " - << std::hex << std::setw(4) << std::setfill('0') - << its_client << " got deregistered!"; - break; - - case VSOMEIP_PONG: - on_pong(its_client); - break; - - case VSOMEIP_OFFER_SERVICE: - std::memcpy(&its_service, &_data[VSOMEIP_COMMAND_PAYLOAD_POS], - sizeof(its_service)); - std::memcpy(&its_instance, - &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 2], - sizeof(its_instance)); - std::memcpy(&its_major, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 4], - sizeof(its_major)); - std::memcpy(&its_minor, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 5], - sizeof(its_minor)); - std::memcpy(&its_ttl, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 9], - sizeof(its_ttl)); - host_->offer_service(its_client, its_service, its_instance, - its_major, its_minor, its_ttl); - on_offer_service(its_client, its_service, its_instance); - break; - - case VSOMEIP_STOP_OFFER_SERVICE: - std::memcpy(&its_service, &_data[VSOMEIP_COMMAND_PAYLOAD_POS], - sizeof(its_service)); - std::memcpy(&its_instance, - &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 2], - sizeof(its_instance)); - host_->stop_offer_service(its_client, its_service, its_instance); - on_stop_offer_service(its_client, its_service, its_instance); - break; - - case VSOMEIP_SUBSCRIBE: - std::memcpy(&its_service, &_data[VSOMEIP_COMMAND_PAYLOAD_POS], - sizeof(its_service)); - std::memcpy(&its_instance, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 2], - sizeof(its_instance)); - std::memcpy(&its_eventgroup, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 4], - sizeof(its_eventgroup)); - std::memcpy(&its_major, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 6], - sizeof(its_major)); - std::memcpy(&its_ttl, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 7], - sizeof(its_ttl)); - - host_->subscribe(its_client, its_service, - its_instance, its_eventgroup, its_major, its_ttl); - break; - - case VSOMEIP_UNSUBSCRIBE: - std::memcpy(&its_service, &_data[VSOMEIP_COMMAND_PAYLOAD_POS], - sizeof(its_service)); - std::memcpy(&its_instance, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 2], - sizeof(its_instance)); - std::memcpy(&its_eventgroup, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 4], - sizeof(its_eventgroup)); - host_->unsubscribe(its_client, its_service, - its_instance, its_eventgroup); - break; - - case VSOMEIP_SEND: - 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 - 4], sizeof(its_instance)); - std::memcpy(&its_reliable, &_data[_size - 1], sizeof(its_reliable)); - host_->on_message(its_service, its_instance, its_data, its_size, its_reliable); - break; - - case VSOMEIP_REQUEST_SERVICE: - bool its_selective; + if (VSOMEIP_COMMAND_SIZE_POS_MAX < _size) { + byte_t its_command; + client_t its_client; + std::string its_client_endpoint; + service_t its_service; + instance_t its_instance; + eventgroup_t its_eventgroup; + std::set its_eventgroups; + event_t its_event; + bool is_field(false); + bool is_provided(false); + major_version_t its_major; + minor_version_t its_minor; + std::shared_ptr its_payload; + const byte_t *its_data; + uint32_t its_size; + bool its_reliable(false); + bool use_exclusive_proxy(false); + + its_command = _data[VSOMEIP_COMMAND_TYPE_POS]; + std::memcpy(&its_client, &_data[VSOMEIP_COMMAND_CLIENT_POS], + sizeof(its_client)); + + std::memcpy(&its_size, &_data[VSOMEIP_COMMAND_SIZE_POS_MIN], + sizeof(its_size)); + + if (its_size <= _size - VSOMEIP_COMMAND_HEADER_SIZE) { + switch (its_command) { + case VSOMEIP_REGISTER_APPLICATION: + on_register_application(its_client); + VSOMEIP_DEBUG << "Application/Client " + << std::hex << std::setw(4) << std::setfill('0') + << its_client << " got registered!"; + break; + + case VSOMEIP_DEREGISTER_APPLICATION: + on_deregister_application(its_client); + VSOMEIP_DEBUG << "Application/Client " + << std::hex << std::setw(4) << std::setfill('0') + << its_client << " got deregistered!"; + break; + + case VSOMEIP_PONG: + on_pong(its_client); + break; + + case VSOMEIP_OFFER_SERVICE: + std::memcpy(&its_service, &_data[VSOMEIP_COMMAND_PAYLOAD_POS], + sizeof(its_service)); + std::memcpy(&its_instance, + &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 2], + sizeof(its_instance)); + std::memcpy(&its_major, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 4], + sizeof(its_major)); + std::memcpy(&its_minor, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 5], + sizeof(its_minor)); + host_->offer_service(its_client, its_service, its_instance, + its_major, its_minor); + on_offer_service(its_client, its_service, its_instance); + break; + + case VSOMEIP_STOP_OFFER_SERVICE: + std::memcpy(&its_service, &_data[VSOMEIP_COMMAND_PAYLOAD_POS], + sizeof(its_service)); + std::memcpy(&its_instance, + &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 2], + sizeof(its_instance)); + host_->stop_offer_service(its_client, its_service, its_instance); + on_stop_offer_service(its_client, its_service, its_instance); + break; + + case VSOMEIP_SUBSCRIBE: + std::memcpy(&its_service, &_data[VSOMEIP_COMMAND_PAYLOAD_POS], + sizeof(its_service)); + std::memcpy(&its_instance, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 2], + sizeof(its_instance)); + std::memcpy(&its_eventgroup, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 4], + sizeof(its_eventgroup)); + std::memcpy(&its_major, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 6], + sizeof(its_major)); + + host_->subscribe(its_client, its_service, + its_instance, its_eventgroup, its_major); + break; + + case VSOMEIP_UNSUBSCRIBE: + std::memcpy(&its_service, &_data[VSOMEIP_COMMAND_PAYLOAD_POS], + sizeof(its_service)); + std::memcpy(&its_instance, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 2], + sizeof(its_instance)); + std::memcpy(&its_eventgroup, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 4], + sizeof(its_eventgroup)); + host_->unsubscribe(its_client, its_service, + its_instance, its_eventgroup); + break; + + case VSOMEIP_SEND: + 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 - 4], sizeof(its_instance)); + std::memcpy(&its_reliable, &_data[_size - 1], sizeof(its_reliable)); + host_->on_message(its_service, its_instance, its_data, its_size, its_reliable); + break; + + case VSOMEIP_NOTIFY: + 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 - 4], sizeof(its_instance)); + host_->on_notification(its_client, its_service, its_instance, its_data, its_size); + break; + + case VSOMEIP_REQUEST_SERVICE: std::memcpy(&its_service, &_data[VSOMEIP_COMMAND_PAYLOAD_POS], sizeof(its_service)); std::memcpy(&its_instance, @@ -209,238 +231,286 @@ void routing_manager_stub::on_message(const byte_t *_data, length_t _size, sizeof(its_major)); std::memcpy(&its_minor, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 5], sizeof(its_minor)); - std::memcpy(&its_ttl, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 9], - sizeof(its_ttl)); - std::memcpy(&its_selective, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 13], - sizeof(its_selective)); - host_->request_service(its_client, its_service, its_instance, - its_major, its_minor, its_ttl, its_selective); - break; - } - } - } + 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); + break; + + + case VSOMEIP_RELEASE_SERVICE: + break; + + case VSOMEIP_REGISTER_EVENT: + std::memcpy(&its_service, + &_data[VSOMEIP_COMMAND_PAYLOAD_POS], + sizeof(its_service)); + std::memcpy(&its_instance, + &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 2], + sizeof(its_instance)); + std::memcpy(&its_event, + &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 4], + sizeof(its_event)); + std::memcpy(&is_field, + &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 6], + sizeof(is_field)); + std::memcpy(&is_provided, + &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 7], + sizeof(is_provided)); + for (std::size_t i = 8; i+1 < its_size; i++) { + std::memcpy(&its_eventgroup, + &_data[VSOMEIP_COMMAND_PAYLOAD_POS + i], + sizeof(its_eventgroup)); + its_eventgroups.insert(its_eventgroup); + } + host_->register_event(its_client, its_service, + its_instance, its_event, its_eventgroups, + is_field, is_provided); + break; + + case VSOMEIP_UNREGISTER_EVENT: + std::memcpy(&its_service, &_data[VSOMEIP_COMMAND_PAYLOAD_POS], + sizeof(its_service)); + std::memcpy(&its_instance, + &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 2], + sizeof(its_instance)); + std::memcpy(&its_event, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 4], + sizeof(its_event)); + std::memcpy(&is_provided, + &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 6], + sizeof(is_provided)); + host_->unregister_event(its_client, its_service, its_instance, + its_event, is_provided); + break; + } + } + } } void routing_manager_stub::on_register_application(client_t _client) { - std::lock_guard its_guard(routing_info_mutex_); - (void)host_->find_or_create_local(_client); - routing_info_[_client].first = 0; - broadcast_routing_info(); + std::lock_guard its_guard(routing_info_mutex_); + (void)host_->find_or_create_local(_client); + routing_info_[_client].first = 0; + broadcast_routing_info(); } void routing_manager_stub::on_deregister_application(client_t _client) { - routing_info_mutex_.lock(); - auto its_info = routing_info_.find(_client); - if (its_info != routing_info_.end()) { - for (auto &its_service : its_info->second.second) { - for (auto &its_instance : its_service.second) { - routing_info_mutex_.unlock(); - host_->on_stop_offer_service(its_service.first, its_instance); - routing_info_mutex_.lock(); - } - } - } - routing_info_mutex_.unlock(); - - std::lock_guard its_lock(routing_info_mutex_); - host_->remove_local(_client); - routing_info_.erase(_client); - broadcast_routing_info(); + routing_info_mutex_.lock(); + auto its_info = routing_info_.find(_client); + if (its_info != routing_info_.end()) { + for (auto &its_service : its_info->second.second) { + for (auto &its_instance : its_service.second) { + routing_info_mutex_.unlock(); + host_->on_stop_offer_service(its_service.first, its_instance); + routing_info_mutex_.lock(); + } + } + } + routing_info_mutex_.unlock(); + + std::lock_guard its_lock(routing_info_mutex_); + host_->remove_local(_client); + routing_info_.erase(_client); + broadcast_routing_info(); } void routing_manager_stub::on_offer_service(client_t _client, - service_t _service, instance_t _instance) { - std::lock_guard its_guard(routing_info_mutex_); - routing_info_[_client].second[_service].insert(_instance); - broadcast_routing_info(); + service_t _service, instance_t _instance) { + std::lock_guard its_guard(routing_info_mutex_); + routing_info_[_client].second[_service].insert(_instance); + broadcast_routing_info(); } void routing_manager_stub::on_stop_offer_service(client_t _client, - service_t _service, instance_t _instance) { - std::lock_guard its_guard(routing_info_mutex_); - auto found_client = routing_info_.find(_client); - if (found_client != routing_info_.end()) { - auto found_service = found_client->second.second.find(_service); - if (found_service != found_client->second.second.end()) { - auto found_instance = found_service->second.find(_instance); - if (found_instance != found_service->second.end()) { - found_service->second.erase(_instance); - if (0 == found_service->second.size()) { - found_client->second.second.erase(_service); - } - broadcast_routing_info(); - } - } - } + service_t _service, instance_t _instance) { + std::lock_guard its_guard(routing_info_mutex_); + auto found_client = routing_info_.find(_client); + if (found_client != routing_info_.end()) { + auto found_service = found_client->second.second.find(_service); + if (found_service != found_client->second.second.end()) { + auto found_instance = found_service->second.find(_instance); + if (found_instance != found_service->second.end()) { + found_service->second.erase(_instance); + if (0 == found_service->second.size()) { + found_client->second.second.erase(_service); + } + broadcast_routing_info(); + } + } + } } void routing_manager_stub::send_routing_info(client_t _client) { - std::shared_ptr its_endpoint = host_->find_local(_client); - if (its_endpoint) { - uint32_t its_capacity = 4096; // TODO: dynamic resizing - std::vector its_command(its_capacity); - its_command[VSOMEIP_COMMAND_TYPE_POS] = VSOMEIP_ROUTING_INFO; - std::memset(&its_command[VSOMEIP_COMMAND_CLIENT_POS], 0, - sizeof(client_t)); - uint32_t its_size = VSOMEIP_COMMAND_PAYLOAD_POS; - - for (auto &info : routing_info_) { - uint32_t its_size_pos = its_size; - uint32_t its_entry_size = its_size; - - its_size += sizeof(uint32_t); // placeholder - - if (info.first != host_->get_client()) { - std::memcpy(&its_command[its_size], &info.first, sizeof(client_t)); - } else { - std::memset(&its_command[its_size], 0x0, sizeof(client_t)); - } - - its_size += sizeof(client_t); - - for (auto &service : info.second.second) { - uint32_t its_service_entry_size = sizeof(service_t) - + service.second.size() * sizeof(instance_t); - - std::memcpy(&its_command[its_size], &its_service_entry_size, - sizeof(uint32_t)); - its_size += sizeof(uint32_t); - - std::memcpy(&its_command[its_size], &service.first, - sizeof(service_t)); - its_size += sizeof(service_t); - - for (auto &instance : service.second) { - std::memcpy(&its_command[its_size], &instance, - sizeof(instance_t)); - its_size += sizeof(instance_t); - } - } - - its_entry_size = its_size - its_entry_size - sizeof(uint32_t); - std::memcpy(&its_command[its_size_pos], &its_entry_size, - sizeof(uint32_t)); - } - - its_size -= VSOMEIP_COMMAND_PAYLOAD_POS; - std::memcpy(&its_command[VSOMEIP_COMMAND_SIZE_POS_MIN], &its_size, - sizeof(its_size)); - its_size += VSOMEIP_COMMAND_PAYLOAD_POS; + std::shared_ptr its_endpoint = host_->find_local(_client); + if (its_endpoint) { + uint32_t its_capacity = 4096; // TODO: dynamic resizing + std::vector its_command(its_capacity); + its_command[VSOMEIP_COMMAND_TYPE_POS] = VSOMEIP_ROUTING_INFO; + std::memset(&its_command[VSOMEIP_COMMAND_CLIENT_POS], 0, + sizeof(client_t)); + uint32_t its_size = VSOMEIP_COMMAND_PAYLOAD_POS; + + for (auto &info : routing_info_) { + uint32_t its_size_pos = its_size; + uint32_t its_entry_size = its_size; + + its_size += uint32_t(sizeof(uint32_t)); // placeholder + + if (info.first != host_->get_client()) { + std::memcpy(&its_command[its_size], &info.first, sizeof(client_t)); + } else { + std::memset(&its_command[its_size], 0x0, sizeof(client_t)); + } + + its_size += uint32_t(sizeof(client_t)); + + for (auto &service : info.second.second) { + uint32_t its_service_entry_size = uint32_t(sizeof(service_t) + + service.second.size() * sizeof(instance_t)); + + std::memcpy(&its_command[its_size], &its_service_entry_size, + sizeof(uint32_t)); + its_size += uint32_t(sizeof(uint32_t)); + + std::memcpy(&its_command[its_size], &service.first, + sizeof(service_t)); + its_size += uint32_t(sizeof(service_t)); + + for (auto &instance : service.second) { + std::memcpy(&its_command[its_size], &instance, + sizeof(instance_t)); + its_size += uint32_t(sizeof(instance_t)); + } + } + + its_entry_size = its_size - its_entry_size - uint32_t(sizeof(uint32_t)); + std::memcpy(&its_command[its_size_pos], &its_entry_size, + sizeof(uint32_t)); + } + + its_size -= VSOMEIP_COMMAND_PAYLOAD_POS; + std::memcpy(&its_command[VSOMEIP_COMMAND_SIZE_POS_MIN], &its_size, + sizeof(its_size)); + its_size += VSOMEIP_COMMAND_PAYLOAD_POS; #if 0 - std::stringstream msg; - msg << "rms::send_routing_info "; - for (int i = 0; i < its_size; ++i) - msg << std::hex << std::setw(2) << std::setfill('0') << (int)its_command[i] << " "; - VSOMEIP_DEBUG << msg.str(); + std::stringstream msg; + msg << "rms::send_routing_info "; + for (int i = 0; i < its_size; ++i) + msg << std::hex << std::setw(2) << std::setfill('0') << (int)its_command[i] << " "; + VSOMEIP_DEBUG << msg.str(); #endif - its_endpoint->send(&its_command[0], its_size, true); - } + its_endpoint->send(&its_command[0], its_size, true); + } } void routing_manager_stub::broadcast_routing_info() { - for (auto& info : routing_info_) { - if (info.first != host_->get_client()) - send_routing_info(info.first); - } + for (auto& info : routing_info_) { + if (info.first != VSOMEIP_ROUTING_CLIENT) + send_routing_info(info.first); + } } void routing_manager_stub::broadcast(std::vector &_command) const { - std::lock_guard its_guard(routing_info_mutex_); - for (auto a : routing_info_) { - if (a.first > 0) { - std::shared_ptr its_endpoint - = host_->find_local(a.first); - if (its_endpoint) { - its_endpoint->send(&_command[0], _command.size(), true); - } - } - } + std::lock_guard its_guard(routing_info_mutex_); + for (auto a : routing_info_) { + if (a.first > 0) { + std::shared_ptr its_endpoint + = host_->find_local(a.first); + if (its_endpoint) { + its_endpoint->send(&_command[0], uint32_t(_command.size()), true); + } + } + } } // Watchdog void routing_manager_stub::broadcast_ping() const { - const byte_t its_ping[] = { - VSOMEIP_PING, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; + const byte_t its_ping[] = { + VSOMEIP_PING, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; - std::vector its_command(sizeof(its_ping)); - its_command.assign(its_ping, its_ping + sizeof(its_ping)); - broadcast(its_command); + std::vector its_command(sizeof(its_ping)); + its_command.assign(its_ping, its_ping + sizeof(its_ping)); + broadcast(its_command); } void routing_manager_stub::on_pong(client_t _client) { - auto found_info = routing_info_.find(_client); - if (found_info != routing_info_.end()) { - found_info->second.first = 0; - } else { - VSOMEIP_ERROR << "Received PONG from unregistered application!"; - } + auto found_info = routing_info_.find(_client); + if (found_info != routing_info_.end()) { + found_info->second.first = 0; + } else { + VSOMEIP_ERROR << "Received PONG from unregistered application!"; + } } void routing_manager_stub::start_watchdog() { - watchdog_timer_.expires_from_now( - std::chrono::milliseconds(VSOMEIP_DEFAULT_WATCHDOG_CYCLE)); // TODO: use config variable + watchdog_timer_.expires_from_now( + std::chrono::milliseconds(VSOMEIP_DEFAULT_WATCHDOG_CYCLE)); // TODO: use config variable - std::function its_callback = - [this](boost::system::error_code const &_error) { - if (!_error) - check_watchdog(); - }; + std::function its_callback = + [this](boost::system::error_code const &_error) { + if (!_error) + check_watchdog(); + }; - watchdog_timer_.async_wait(its_callback); + watchdog_timer_.async_wait(its_callback); } void routing_manager_stub::check_watchdog() { - for (auto i = routing_info_.begin(); i != routing_info_.end(); ++i) { - i->second.first++; - } - broadcast_ping(); - - watchdog_timer_.expires_from_now( - std::chrono::milliseconds(VSOMEIP_DEFAULT_WATCHDOG_TIMEOUT)); // TODO: use config variable - - std::function its_callback = - [this](boost::system::error_code const &_error) { - std::list< client_t > lost; - { - std::lock_guard its_lock(routing_info_mutex_); - for (auto i : routing_info_) { - if (i.first > 0 && i.first != host_->get_client()) { - if (i.second.first > VSOMEIP_DEFAULT_MAX_MISSING_PONGS) { // TODO: use config variable - VSOMEIP_WARNING << "Lost contact to application " << std::hex << (int)i.first; - lost.push_back(i.first); - } - } - } - - for (auto i : lost) { - routing_info_.erase(i); - } - } - if (0 < lost.size()) - send_application_lost(lost); - - start_watchdog(); - }; - - watchdog_timer_.async_wait(its_callback); + { + std::lock_guard its_guard(routing_info_mutex_); + for (auto i = routing_info_.begin(); i != routing_info_.end(); ++i) { + i->second.first++; + } + } + broadcast_ping(); + + watchdog_timer_.expires_from_now( + std::chrono::milliseconds(VSOMEIP_DEFAULT_WATCHDOG_TIMEOUT)); // TODO: use config variable + + std::function its_callback = + [this](boost::system::error_code const &_error) { + (void)_error; + std::list< client_t > lost; + { + std::lock_guard its_lock(routing_info_mutex_); + for (auto i : routing_info_) { + if (i.first > 0 && i.first != host_->get_client()) { + if (i.second.first > VSOMEIP_DEFAULT_MAX_MISSING_PONGS) { // TODO: use config variable + VSOMEIP_WARNING << "Lost contact to application " << std::hex << (int)i.first; + lost.push_back(i.first); + } + } + } + + for (auto i : lost) { + routing_info_.erase(i); + } + } + if (0 < lost.size()) + send_application_lost(lost); + + start_watchdog(); + }; + + watchdog_timer_.async_wait(its_callback); } void routing_manager_stub::send_application_lost(std::list &_lost) { - uint32_t its_size = _lost.size() * sizeof(client_t); - std::vector its_command(VSOMEIP_COMMAND_HEADER_SIZE + its_size); - its_command[VSOMEIP_COMMAND_TYPE_POS] = VSOMEIP_APPLICATION_LOST; - std::memset(&its_command[VSOMEIP_COMMAND_CLIENT_POS], 0, sizeof(client_t)); - std::memcpy(&its_command[VSOMEIP_COMMAND_SIZE_POS_MIN], &its_size, - sizeof(uint32_t)); - - uint32_t its_offset = 0; - for (auto i : _lost) { - std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + its_offset], &i, - sizeof(client_t)); - its_offset += sizeof(client_t); - } - - broadcast(its_command); + uint32_t its_size = uint32_t(_lost.size() * sizeof(client_t)); + std::vector its_command(VSOMEIP_COMMAND_HEADER_SIZE + its_size); + its_command[VSOMEIP_COMMAND_TYPE_POS] = VSOMEIP_APPLICATION_LOST; + std::memset(&its_command[VSOMEIP_COMMAND_CLIENT_POS], 0, sizeof(client_t)); + std::memcpy(&its_command[VSOMEIP_COMMAND_SIZE_POS_MIN], &its_size, + sizeof(uint32_t)); + + uint32_t its_offset = 0; + for (auto i : _lost) { + std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + its_offset], &i, + sizeof(client_t)); + its_offset += uint32_t(sizeof(client_t)); + } + + broadcast(its_command); } } // namespace vsomeip diff --git a/implementation/routing/src/servicegroup.cpp b/implementation/routing/src/servicegroup.cpp deleted file mode 100644 index ce4739e..0000000 --- a/implementation/routing/src/servicegroup.cpp +++ /dev/null @@ -1,70 +0,0 @@ -// Copyright (C) 2014-2015 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/servicegroup.hpp" -#include "../include/serviceinfo.hpp" - -namespace vsomeip { - -servicegroup::servicegroup(const std::string &_name, bool _is_local) - : name_(_name), is_local_(_is_local) { -} - -servicegroup::~servicegroup() { -} - -std::string servicegroup::get_name() const { - return name_; -} - -bool servicegroup::is_local() const { - return is_local_; -} - -bool servicegroup::add_service( - service_t _service, instance_t _instance, - std::shared_ptr< serviceinfo > _info) { - bool its_result(true); - auto find_service = services_.find(_service); - if (find_service != services_.end()) { - auto find_instance = find_service->second.find(_instance); - if (find_instance != find_service->second.end()) { - its_result = false; - } else { - find_service->second[_instance] = _info; - } - } else { - services_[_service][_instance] = _info; - } - - _info->set_group(this); - - return its_result; -} - -bool servicegroup::remove_service(service_t _service, instance_t _instance) { - bool its_result(false); - auto find_service = services_.find(_service); - if (find_service != services_.end()) { - auto find_instance = find_service->second.find(_instance); - if (find_instance != find_service->second.end()) { - find_service->second.erase(_instance); - if (0 == find_service->second.size()) { - services_.erase(_service); - } - its_result = true; - } - } - return its_result; -} - -services_t servicegroup::get_services() const { - return services_; -} - -} // namespace vsomeip - - - diff --git a/implementation/routing/src/serviceinfo.cpp b/implementation/routing/src/serviceinfo.cpp index 60704ad..75d11dd 100644 --- a/implementation/routing/src/serviceinfo.cpp +++ b/implementation/routing/src/serviceinfo.cpp @@ -8,14 +8,15 @@ namespace vsomeip { serviceinfo::serviceinfo(major_version_t _major, minor_version_t _minor, - ttl_t _ttl) + ttl_t _ttl, bool _is_local) : group_(0), major_(_major), minor_(_minor), ttl_(_ttl), reliable_(nullptr), unreliable_(nullptr), - multicast_group_(0xFFFF) { + multicast_group_(0xFFFF), + is_local_(_is_local) { } serviceinfo::~serviceinfo() { @@ -90,5 +91,9 @@ void serviceinfo::remove_client(client_t _client) { requesters_.erase(_client); } +bool serviceinfo::is_local() const { + return is_local_; +} + } // namespace vsomeip diff --git a/implementation/runtime/include/application_impl.hpp b/implementation/runtime/include/application_impl.hpp index 3b37df0..76d316e 100644 --- a/implementation/runtime/include/application_impl.hpp +++ b/implementation/runtime/include/application_impl.hpp @@ -37,30 +37,47 @@ public: VSOMEIP_EXPORT application_impl(const std::string &_name); VSOMEIP_EXPORT ~application_impl(); + VSOMEIP_EXPORT void set_configuration(const std::shared_ptr _configuration); + VSOMEIP_EXPORT bool init(); VSOMEIP_EXPORT void start(); VSOMEIP_EXPORT void stop(); + // Provide services / events VSOMEIP_EXPORT void offer_service(service_t _service, instance_t _instance, - major_version_t _major, minor_version_t _minor, ttl_t _ttl); + major_version_t _major, minor_version_t _minor); VSOMEIP_EXPORT void stop_offer_service(service_t _service, instance_t _instance); - // Consume services + VSOMEIP_EXPORT void offer_event(service_t _service, + instance_t _instance, event_t _event, + std::set _eventgroups, + bool _is_field); + VSOMEIP_EXPORT void stop_offer_event(service_t _service, + instance_t _instance, event_t _event); + + // Consume services / events VSOMEIP_EXPORT void request_service(service_t _service, - instance_t _instance, bool _has_selective, major_version_t _major, - minor_version_t _minor, ttl_t _ttl); + instance_t _instance, major_version_t _major, + minor_version_t _minor, bool _use_exclusive_proxy); VSOMEIP_EXPORT void release_service(service_t _service, instance_t _instance); + VSOMEIP_EXPORT void request_event(service_t _service, + instance_t _instance, event_t _event, + std::set _eventgroups, + bool _is_field); + VSOMEIP_EXPORT void release_event(service_t _service, + instance_t _instance, event_t _event); + VSOMEIP_EXPORT void subscribe(service_t _service, instance_t _instance, - eventgroup_t _eventgroup, major_version_t _major, ttl_t _ttl); + eventgroup_t _eventgroup, major_version_t _major); VSOMEIP_EXPORT void unsubscribe(service_t _service, instance_t _instance, eventgroup_t _eventgroup); - VSOMEIP_EXPORT bool is_available(service_t _service, instance_t _instance); + VSOMEIP_EXPORT bool is_available(service_t _service, instance_t _instance) const; VSOMEIP_EXPORT void send(std::shared_ptr _message, bool _flush); @@ -70,8 +87,8 @@ public: VSOMEIP_EXPORT void notify_one(service_t _service, instance_t _instance, event_t _event, std::shared_ptr _payload, client_t _client) const; - VSOMEIP_EXPORT void register_event_handler(event_handler_t _handler); - VSOMEIP_EXPORT void unregister_event_handler(); + VSOMEIP_EXPORT void register_state_handler(state_handler_t _handler); + VSOMEIP_EXPORT void unregister_state_handler(); VSOMEIP_EXPORT void register_message_handler(service_t _service, instance_t _instance, method_t _method, message_handler_t _handler); @@ -94,10 +111,9 @@ public: VSOMEIP_EXPORT std::shared_ptr get_configuration() const; VSOMEIP_EXPORT boost::asio::io_service & get_io(); - VSOMEIP_EXPORT void on_event(event_type_e _event); - VSOMEIP_EXPORT void on_availability(service_t _service, - instance_t _instance, - bool _is_available) const; + VSOMEIP_EXPORT void on_state(state_type_e _state); + VSOMEIP_EXPORT void on_availability(service_t _service, instance_t _instance, + bool _is_available) const; VSOMEIP_EXPORT void on_message(std::shared_ptr _message); VSOMEIP_EXPORT void on_error(error_code_e _error); VSOMEIP_EXPORT bool on_subscription(service_t _service, instance_t _instance, @@ -116,24 +132,28 @@ private: } void dispatch(); + void wait_for_stop(); private: client_t client_; // unique application identifier session_t session_; + std::mutex session_mutex_; std::mutex initialize_mutex_; bool is_initialized_; std::string name_; std::shared_ptr configuration_; + std::string file_; // configuration file + std::string folder_; // configuration folder boost::asio::io_service io_; // Proxy to or the Routing Manager itself std::shared_ptr routing_; - // (Non-SOME/IP) Event handler - event_handler_t handler_; + // vsomeip state handler + state_handler_t handler_; // Method/Event (=Member) handlers std::map logger_; + + std::condition_variable stop_cv_; + std::mutex start_stop_mutex_; + bool stopped_; + std::thread stop_thread_; }; } // namespace vsomeip diff --git a/implementation/runtime/include/runtime_impl.hpp b/implementation/runtime/include/runtime_impl.hpp index 6240969..123272b 100644 --- a/implementation/runtime/include/runtime_impl.hpp +++ b/implementation/runtime/include/runtime_impl.hpp @@ -7,6 +7,7 @@ #define VSOMEIP_RUNTIME_IMPL_HPP #include +#include namespace vsomeip { @@ -17,7 +18,7 @@ public: virtual ~runtime_impl(); std::shared_ptr create_application( - const std::string &_name) const; + const std::string &_name); std::shared_ptr create_message(bool _reliable) const; std::shared_ptr create_request(bool _reliable) const; @@ -30,6 +31,14 @@ public: uint32_t _size) const; std::shared_ptr create_payload( const std::vector &_data) const; + + std::shared_ptr get_application( + const std::string &_name) const; + +private: + static std::shared_ptr the_runtime_; + + std::map> applications_; }; } // namespace vsomeip diff --git a/implementation/runtime/src/application_impl.cpp b/implementation/runtime/src/application_impl.cpp index 77eef78..f713e28 100644 --- a/implementation/runtime/src/application_impl.cpp +++ b/implementation/runtime/src/application_impl.cpp @@ -3,70 +3,175 @@ // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. +#include #include -#include +#include -#include +#ifndef WIN32 +#include +#endif +#include #include -#include #include "../include/application_impl.hpp" +#include "../../configuration/include/configuration.hpp" #include "../../configuration/include/internal.hpp" +#include "../../logging/include/logger.hpp" #include "../../message/include/serializer.hpp" #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" namespace vsomeip { application_impl::application_impl(const std::string &_name) - : name_(_name), is_initialized_(false), routing_(0), signals_(io_, - SIGINT, SIGTERM), num_dispatchers_(0), logger_(logger::get()) { + : is_initialized_(false), name_(_name), + file_(VSOMEIP_DEFAULT_CONFIGURATION_FILE), + folder_(VSOMEIP_DEFAULT_CONFIGURATION_FOLDER), + routing_(0), + signals_(io_, SIGINT, SIGTERM), + num_dispatchers_(0), logger_(logger::get()), + stopped_(false) { } application_impl::~application_impl() { #ifdef WIN32 - // killemall - exit(0); + exit(0); // TODO: clean solution... #endif + stop_thread_.join(); } -bool application_impl::init() { - bool is_initialized(false); +void application_impl::set_configuration( + const std::shared_ptr _configuration) { + if(_configuration) + configuration_ = std::make_shared(*(std::static_pointer_cast(_configuration))); +} +bool application_impl::init() { // Application name if (name_ == "") { const char *its_name = getenv(VSOMEIP_ENV_APPLICATION_NAME); if (nullptr != its_name) { name_ = its_name; + } + } + + // 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 << "\" was loaded"; + if (!configuration_) { + VSOMEIP_ERROR << "Configuration not set."; + return false; + } } else { - VSOMEIP_ERROR<< "Missing application name. " - "Please set environment variable VSOMEIP_APPLICATION_NAME."; + 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 << "\" was loaded"; + if(!configuration_) { + VSOMEIP_ERROR << "Configuration not set."; + return false; + } + } 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_ = ""; + } + } } - // Set default path - std::string its_path(VSOMEIP_DEFAULT_CONFIGURATION_FILE_PATH); + std::shared_ptr its_configuration = get_configuration(); + if (its_configuration) { + VSOMEIP_INFO << "Initializing vsomeip application \"" << name_ << "\""; - // Override with path from environment - const char *its_env_path = getenv(VSOMEIP_ENV_CONFIGURATION_FILE_PATH); - if (nullptr != its_env_path && utility::exists(its_env_path)) - its_path = its_env_path; + if (utility::is_file(file_)) + VSOMEIP_INFO << "Using configuration file: \"" << file_ << "\""; - // Override with local path - std::string its_local_path(VSOMEIP_LOCAL_CONFIGURATION_FILE_PATH); - if (utility::exists(its_local_path)) - its_path = its_local_path; + if (utility::is_folder(folder_)) + VSOMEIP_INFO << "Using configuration folder: \"" << folder_ << "\""; - configuration_.reset(configuration::get(its_path)); - VSOMEIP_INFO<< "Using configuration file: " << its_path; + bool is_routing_manager_host(false); + client_ = its_configuration->get_id(name_); + std::string its_routing_host = its_configuration->get_routing_host(); - if (configuration_) { - client_ = configuration_->get_id(name_); + if (client_ == 0 || its_routing_host == "") { +#ifndef WIN32 + if (!utility::auto_configuration_init()) { + VSOMEIP_ERROR << "Configuration incomplete and " + "Auto-configuration failed!"; + return false; + } +#else + return false; +#endif + } + // Client ID + if (client_ == 0) { +#ifndef WIN32 + client_ = utility::get_client_id(); + VSOMEIP_INFO << "No SOME/IP client identifier configured. " + << "Using auto-configured " + << std::hex << std::setfill('0') << std::setw(4) + << client_; +#else + return false; +#endif + } // Routing - if (name_ == configuration_->get_routing_host()) { + if (its_routing_host == "") { +#ifndef WIN32 + is_routing_manager_host = utility::is_routing_manager_host(); + VSOMEIP_INFO << "No routing manager configured. " + << "Using auto-configuration (" + << (is_routing_manager_host ? + "Host" : "Proxy") << ")"; +#else + return false; +#endif + } else { + is_routing_manager_host = (its_routing_host == name_); + } + + if (is_routing_manager_host) { routing_ = std::make_shared(this); } else { routing_ = std::make_shared(this); @@ -74,19 +179,22 @@ bool application_impl::init() { routing_->init(); - num_dispatchers_ = configuration_->get_num_dispatchers(name_); + num_dispatchers_ = its_configuration->get_num_dispatchers(name_); // Smallest allowed session identifier session_ = 0x0001; - VSOMEIP_DEBUG<< "Application(" << name_ << ", " - << std::hex << client_ << ") is initialized (uses " + VSOMEIP_DEBUG<< "Application(" << (name_ != "" ? name_ : "unnamed") + << ", " << std::hex << client_ << ") is initialized (uses " << std::dec << num_dispatchers_ << " dispatcher threads)."; is_initialized_ = true; } if (is_initialized_) { + signals_.add(SIGINT); + signals_.add(SIGTERM); + // Register signal handler std::function its_signal_handler = [this] (boost::system::error_code const &_error, int _signal) { @@ -109,35 +217,60 @@ bool application_impl::init() { } void application_impl::start() { - is_dispatching_ = true; + { + std::lock_guard its_lock(start_stop_mutex_); + if(io_.stopped()) { + io_.reset(); + } else if(stop_thread_.joinable()) { + VSOMEIP_ERROR << "Trying to start an already started application."; + return; + } - for (size_t i = 0; i < num_dispatchers_; i++) - dispatchers_.push_back( - std::thread(std::bind(&application_impl::dispatch, this))); + is_dispatching_ = true; - if (routing_) - routing_->start(); + for (size_t i = 0; i < num_dispatchers_; i++) + dispatchers_.push_back( + std::thread(std::bind(&application_impl::dispatch, this))); + if(stop_thread_.joinable()) { + stop_thread_.join(); + } + stop_thread_= std::thread(&application_impl::wait_for_stop, this); + + if (routing_) + routing_->start(); + } + VSOMEIP_INFO << "Starting vsomeip application \"" << name_ << "\""; io_.run(); } void application_impl::stop() { + VSOMEIP_INFO << "Stopping vsomeip application \"" << name_ << "\""; + std::lock_guard its_lock(start_stop_mutex_); is_dispatching_ = false; dispatch_condition_.notify_all(); - for (auto &t : dispatchers_) - t.join(); + for (auto &t : dispatchers_) { + if(t.get_id() == std::this_thread::get_id()) { + continue; + } + if(t.joinable()) { + t.join(); + } + } if (routing_) routing_->stop(); - - io_.stop(); +#ifndef WIN32 + utility::auto_configuration_exit(); +#endif + stopped_ = true; + stop_cv_.notify_one(); } void application_impl::offer_service(service_t _service, instance_t _instance, - major_version_t _major, minor_version_t _minor, ttl_t _ttl) { + major_version_t _major, minor_version_t _minor) { if (routing_) - routing_->offer_service(client_, _service, _instance, _major, _minor, - _ttl); + routing_->offer_service(client_, _service, _instance, _major, _minor); } void application_impl::stop_offer_service(service_t _service, @@ -147,11 +280,10 @@ void application_impl::stop_offer_service(service_t _service, } void application_impl::request_service(service_t _service, instance_t _instance, - bool _has_selective, major_version_t _major, minor_version_t _minor, - ttl_t _ttl) { + major_version_t _major, minor_version_t _minor, bool _use_exclusive_proxy) { if (routing_) routing_->request_service(client_, _service, _instance, _major, _minor, - _ttl, _has_selective); + _use_exclusive_proxy); } void application_impl::release_service(service_t _service, @@ -161,10 +293,9 @@ void application_impl::release_service(service_t _service, } void application_impl::subscribe(service_t _service, instance_t _instance, - eventgroup_t _eventgroup, major_version_t _major, ttl_t _ttl) { + eventgroup_t _eventgroup, major_version_t _major) { if (routing_) - routing_->subscribe(client_, _service, _instance, _eventgroup, _major, - _ttl); + routing_->subscribe(client_, _service, _instance, _eventgroup, _major); } void application_impl::unsubscribe(service_t _service, instance_t _instance, @@ -173,7 +304,8 @@ void application_impl::unsubscribe(service_t _service, instance_t _instance, routing_->unsubscribe(client_, _service, _instance, _eventgroup); } -bool application_impl::is_available(service_t _service, instance_t _instance) { +bool application_impl::is_available( + service_t _service, instance_t _instance) const { auto found_available = available_.find(_service); if (found_available == available_.end()) return false; @@ -183,6 +315,7 @@ bool application_impl::is_available(service_t _service, instance_t _instance) { } void application_impl::send(std::shared_ptr _message, bool _flush) { + std::lock_guard its_lock(session_mutex_); if (routing_) { // in case of requests set the request-id (client-id|session-id) bool is_request = utility::is_request(_message); @@ -214,18 +347,23 @@ void application_impl::notify_one(service_t _service, instance_t _instance, } } -void application_impl::register_event_handler(event_handler_t _handler) { +void application_impl::register_state_handler(state_handler_t _handler) { handler_ = _handler; } -void application_impl::unregister_event_handler() { +void application_impl::unregister_state_handler() { handler_ = nullptr; } void application_impl::register_availability_handler(service_t _service, instance_t _instance, availability_handler_t _handler) { - std::unique_lock its_lock(availability_mutex_); - availability_[_service][_instance] = _handler; + { + std::unique_lock its_lock(availability_mutex_); + availability_[_service][_instance] = _handler; + } + std::async(std::launch::async, [this, _service, _instance, _handler]() { + _handler(_service, _instance, is_available(_service, _instance)); + }); } void application_impl::unregister_availability_handler(service_t _service, @@ -302,6 +440,32 @@ void application_impl::unregister_message_handler(service_t _service, } } +void application_impl::offer_event(service_t _service, instance_t _instance, + event_t _event, std::set _eventgroups, bool _is_field) { + if (routing_) + routing_->register_event(client_, _service, _instance, _event, + _eventgroups, _is_field, true); +} + +void application_impl::stop_offer_event(service_t _service, instance_t _instance, + event_t _event) { + if (routing_) + routing_->unregister_event(client_, _service, _instance, _event, true); +} + +void application_impl::request_event(service_t _service, instance_t _instance, + event_t _event, std::set _eventgroups, bool _is_field) { + if (routing_) + routing_->register_event(client_, _service, _instance, _event, + _eventgroups, _is_field, false); + } + +void application_impl::release_event(service_t _service, instance_t _instance, + event_t _event) { + if (routing_) + routing_->unregister_event(client_, _service, _instance, _event, false); +} + // Interface "routing_manager_host" const std::string & application_impl::get_name() const { return name_; @@ -312,23 +476,36 @@ client_t application_impl::get_client() const { } std::shared_ptr application_impl::get_configuration() const { - return configuration_; + if(configuration_) { + return configuration_; + } else { + std::set its_input; + std::shared_ptr its_configuration; + if (file_ != "") { + its_input.insert(file_); + } + if (folder_ != "") { + its_input.insert(folder_); + } + its_configuration = configuration::get(its_input); + return its_configuration; + } } boost::asio::io_service & application_impl::get_io() { return io_; } -void application_impl::on_event(event_type_e _event) { +void application_impl::on_state(state_type_e _state) { if (handler_) { if (num_dispatchers_ > 0) { std::unique_lock its_lock(dispatch_mutex_); - handlers_.push_back([this, _event]() { - handler_(_event); + handlers_.push_back([this, _state]() { + handler_(_state); }); dispatch_condition_.notify_one(); } else { - handler_(_event); + handler_(_state); } } } @@ -346,6 +523,9 @@ void application_impl::on_availability(service_t _service, instance_t _instance, { std::unique_lock its_lock(availability_mutex_); + if (_is_available == is_available(_service, _instance)) + return; + if (_is_available) { available_[_service].insert(_instance); } else { @@ -474,4 +654,19 @@ void application_impl::dispatch() { } } +void application_impl::wait_for_stop() { + std::unique_lock its_lock(start_stop_mutex_); + while(!stopped_) { + stop_cv_.wait(its_lock); + } + stopped_ = false; + + for (auto &t : dispatchers_) { + if(t.joinable()) { + t.join(); + } + } + io_.stop(); +} + } // namespace vsomeip diff --git a/implementation/runtime/src/runtime_impl.cpp b/implementation/runtime/src/runtime_impl.cpp index 896ed15..e50ceca 100644 --- a/implementation/runtime/src/runtime_impl.cpp +++ b/implementation/runtime/src/runtime_impl.cpp @@ -12,18 +12,20 @@ namespace vsomeip { +std::shared_ptr runtime_impl::the_runtime_ = std::make_shared(); + std::shared_ptr runtime_impl::get() { - static std::shared_ptr the_runtime = - std::make_shared(); - return the_runtime; + return the_runtime_; } runtime_impl::~runtime_impl() { } std::shared_ptr runtime_impl::create_application( - const std::string &_name) const { - return (std::make_shared(_name)); + const std::string &_name) { + std::shared_ptr application = std::make_shared(_name); + applications_[_name] = application; + return application; } std::shared_ptr runtime_impl::create_message(bool _reliable) const { @@ -86,4 +88,12 @@ std::shared_ptr runtime_impl::create_payload( return (std::make_shared(_data)); } +std::shared_ptr 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 nullptr; +} + } // namespace vsomeip diff --git a/implementation/service_discovery/include/defines.hpp b/implementation/service_discovery/include/defines.hpp index a239f54..2d23c3c 100644 --- a/implementation/service_discovery/include/defines.hpp +++ b/implementation/service_discovery/include/defines.hpp @@ -15,11 +15,18 @@ #define VSOMEIP_SD_METHOD 0x8100 #define VSOMEIP_SD_CLIENT 0x0000 -#define VSOMEIP_SD_DEFAULT_MIN_INITIAL_DELAY 0 -#define VSOMEIP_SD_DEFAULT_MAX_INITIAL_DELAY 3000 -#define VSOMEIP_SD_DEFAULT_REPETITION_BASE_DELAY 10 -#define VSOMEIP_SD_DEFAULT_REPETITION_MAX 5 -#define VSOMEIP_SD_DEFAULT_CYCLIC_OFFER_DELAY 1000 -#define VSOMEIP_SD_DEFAULT_CYCLIC_REQUEST_DELAY 2000 + +#define VSOMEIP_SD_DEFAULT_ENABLED true +#define VSOMEIP_SD_DEFAULT_PROTOCOL "udp" +#define VSOMEIP_SD_DEFAULT_MULTICAST "224.224.224.0" +#define VSOMEIP_SD_DEFAULT_PORT 30490 + +#define VSOMEIP_SD_DEFAULT_INITIAL_DELAY_MIN 0 +#define VSOMEIP_SD_DEFAULT_INITIAL_DELAY_MAX 3000 +#define VSOMEIP_SD_DEFAULT_REPETITIONS_BASE_DELAY 10 +#define VSOMEIP_SD_DEFAULT_REPETITIONS_MAX 3 +#define VSOMEIP_SD_DEFAULT_TTL 5 +#define VSOMEIP_SD_DEFAULT_CYCLIC_OFFER_DELAY 1000 +#define VSOMEIP_SD_DEFAULT_REQUEST_RESPONSE_DELAY 2000 #endif // VSOMEIP_SD_DEFINES_HPP diff --git a/implementation/service_discovery/include/entry_impl.hpp b/implementation/service_discovery/include/entry_impl.hpp index 2da3a5f..fde425c 100755 --- a/implementation/service_discovery/include/entry_impl.hpp +++ b/implementation/service_discovery/include/entry_impl.hpp @@ -10,12 +10,12 @@ #include #include -#include +#include #include "enumeration_types.hpp" #include "message_element_impl.hpp" -#define VSOMEIP_MAX_OPTION_RUN 2 +#define VSOMEIP_MAX_OPTION_RUN 2 namespace vsomeip { @@ -57,6 +57,8 @@ public: virtual bool serialize(vsomeip::serializer *_to) const; virtual bool deserialize(vsomeip::deserializer *_from); + uint8_t get_num_options(uint8_t _run) const; + protected: entry_type_e type_; service_t service_; @@ -66,6 +68,8 @@ protected: std::vector options_[VSOMEIP_MAX_OPTION_RUN]; + uint8_t num_options_[VSOMEIP_MAX_OPTION_RUN]; + entry_impl(); entry_impl(const entry_impl &entry_); }; diff --git a/implementation/service_discovery/include/enumeration_types.hpp b/implementation/service_discovery/include/enumeration_types.hpp index 8584bca..016fdae 100644 --- a/implementation/service_discovery/include/enumeration_types.hpp +++ b/implementation/service_discovery/include/enumeration_types.hpp @@ -39,6 +39,13 @@ enum class entry_type_e UNKNOWN = 0xFF }; +enum class layer_four_protocol_e + : uint8_t { + TCP = 0x06, + UDP = 0x11, + UNKNOWN = 0xFF +}; + } // namespace sd } // namespace vsomeip diff --git a/implementation/service_discovery/include/ip_option_impl.hpp b/implementation/service_discovery/include/ip_option_impl.hpp new file mode 100644 index 0000000..8fd426b --- /dev/null +++ b/implementation/service_discovery/include/ip_option_impl.hpp @@ -0,0 +1,41 @@ +// Copyright (C) 2014-2015 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_IP_OPTION_IMPL_HPP +#define VSOMEIP_SD_IP_OPTION_IMPL_HPP + +#include + +#include "option_impl.hpp" + +namespace vsomeip { +namespace sd { + +class ip_option_impl: public option_impl { +public: + ip_option_impl(); + virtual ~ip_option_impl(); + bool operator ==(const option_impl &_option) const; + + uint16_t get_port() const; + void set_port(uint16_t _port); + + layer_four_protocol_e get_layer_four_protocol() const; + void set_layer_four_protocol(layer_four_protocol_e _protocol); + + bool is_multicast() const; + + virtual bool serialize(vsomeip::serializer *_to) const = 0; + virtual bool deserialize(vsomeip::deserializer *_from) = 0; + +protected: + layer_four_protocol_e protocol_; + uint16_t port_; +}; + +} // namespace sd +} // namespace vsomeip + +#endif // VSOMEIP_SD_IP_OPTION_IMPL_HPP diff --git a/implementation/service_discovery/include/ipv4_option_impl.hpp b/implementation/service_discovery/include/ipv4_option_impl.hpp index 179d82f..b8051cc 100644 --- a/implementation/service_discovery/include/ipv4_option_impl.hpp +++ b/implementation/service_discovery/include/ipv4_option_impl.hpp @@ -8,35 +8,24 @@ #include -#include "option_impl.hpp" +#include "ip_option_impl.hpp" namespace vsomeip { namespace sd { -class ipv4_option_impl: public option_impl { +class ipv4_option_impl: public ip_option_impl { public: ipv4_option_impl(bool _is_multicast); virtual ~ipv4_option_impl(); - bool operator ==(const option_impl &_option) const; const ipv4_address_t & get_address() const; void set_address(const ipv4_address_t &_address); - unsigned short get_port() const; - void set_port(unsigned short _port); - - bool is_udp() const; - void set_udp(bool _is_udp); - - bool is_multicast() const; - bool serialize(vsomeip::serializer *_to) const; bool deserialize(vsomeip::deserializer *_from); -protected: +private: ipv4_address_t address_; - unsigned short port_; - bool is_udp_; }; } // namespace sd diff --git a/implementation/service_discovery/include/ipv6_option_impl.hpp b/implementation/service_discovery/include/ipv6_option_impl.hpp index f1a7a1c..48938b0 100644 --- a/implementation/service_discovery/include/ipv6_option_impl.hpp +++ b/implementation/service_discovery/include/ipv6_option_impl.hpp @@ -6,39 +6,26 @@ #ifndef VSOMEIP_SD_IPV6_OPTION_IMPL_HPP #define VSOMEIP_SD_IPV6_OPTION_IMPL_HPP -#include - #include -#include "option_impl.hpp" +#include "ip_option_impl.hpp" namespace vsomeip { namespace sd { -class ipv6_option_impl: public option_impl { +class ipv6_option_impl: public ip_option_impl { public: ipv6_option_impl(bool _is_multicast); virtual ~ipv6_option_impl(); - bool operator ==(const option_impl &_option) const; const ipv6_address_t & get_address() const; void set_address(const ipv6_address_t &_address); - unsigned short get_port() const; - void set_port(unsigned short _port); - - bool is_udp() const; - void set_udp(bool _is_udp); - - bool is_multicast() const; - bool serialize(vsomeip::serializer *_to) const; bool deserialize(vsomeip::deserializer *_from); -protected: +private: ipv6_address_t address_; - unsigned short port_; - bool is_udp_; }; } // namespace sd diff --git a/implementation/service_discovery/include/message_impl.hpp b/implementation/service_discovery/include/message_impl.hpp index e471ace..b0702df 100755 --- a/implementation/service_discovery/include/message_impl.hpp +++ b/implementation/service_discovery/include/message_impl.hpp @@ -55,6 +55,7 @@ public: const std::vector > & get_options() const; int16_t get_option_index(const std::shared_ptr &_option) const; + uint32_t get_options_length(); std::shared_ptr get_payload() const; void set_payload(std::shared_ptr _payload); @@ -68,6 +69,7 @@ private: private: flags_t flags_; + uint32_t options_length_; std::vector > entries_; std::vector > options_; diff --git a/implementation/service_discovery/include/service_discovery.hpp b/implementation/service_discovery/include/service_discovery.hpp index 0d10388..38b414f 100644 --- a/implementation/service_discovery/include/service_discovery.hpp +++ b/implementation/service_discovery/include/service_discovery.hpp @@ -35,13 +35,14 @@ public: virtual void subscribe(service_t _service, instance_t _instance, eventgroup_t _eventgroup, major_version_t _major, ttl_t _ttl, client_t _client) = 0; virtual void unsubscribe(service_t _service, instance_t _instance, - eventgroup_t _eventgroup) = 0; + eventgroup_t _eventgroup, client_t _client) = 0; + virtual void unsubscribe_all(service_t _service, instance_t _instance) = 0; - virtual void send(const std::string &_name, bool _is_announcing) = 0; + virtual void send(bool _is_announcing) = 0; virtual void on_message(const byte_t *_data, length_t _length) = 0; - virtual void on_offer_change(const std::string &_name) = 0; + virtual void on_offer_change() = 0; }; } // namespace sd diff --git a/implementation/service_discovery/include/service_discovery_fsm.hpp b/implementation/service_discovery/include/service_discovery_fsm.hpp index d731b0b..f3fe7fd 100644 --- a/implementation/service_discovery/include/service_discovery_fsm.hpp +++ b/implementation/service_discovery/include/service_discovery_fsm.hpp @@ -43,8 +43,8 @@ struct fsm: sc::state_machine, public fsm_base { void timer_expired(const boost::system::error_code &_error); uint32_t initial_delay_; - uint32_t repetition_base_delay_; - uint8_t repetition_max_; + uint32_t repetitions_base_delay_; + uint8_t repetitions_max_; uint32_t cyclic_offer_delay_; bool is_up_; @@ -116,10 +116,7 @@ struct announce: sc::state { class service_discovery_fsm: public std::enable_shared_from_this< service_discovery_fsm> { public: - service_discovery_fsm(const std::string &_name, - std::shared_ptr _discovery); - - const std::string & get_name() const; + service_discovery_fsm(std::shared_ptr _discovery); void start(); void stop(); @@ -132,8 +129,6 @@ public: } private: - std::string name_; - std::weak_ptr discovery_; std::shared_ptr<_sd::fsm> fsm_; diff --git a/implementation/service_discovery/include/service_discovery_host.hpp b/implementation/service_discovery/include/service_discovery_host.hpp index f9ad9e5..de1dd93 100644 --- a/implementation/service_discovery/include/service_discovery_host.hpp +++ b/implementation/service_discovery/include/service_discovery_host.hpp @@ -30,10 +30,10 @@ public: virtual boost::asio::io_service & get_io() = 0; virtual std::shared_ptr get_configuration() const = 0; - virtual void create_service_discovery_endpoint(const std::string &_address, - uint16_t _port, bool _reliable) = 0; + virtual std::shared_ptr create_service_discovery_endpoint( + const std::string &_address, uint16_t _port, bool _reliable) = 0; - virtual services_t get_offered_services(const std::string &_name) const = 0; + virtual services_t get_offered_services() const = 0; virtual std::shared_ptr find_eventgroup(service_t _service, instance_t _instance, eventgroup_t _eventgroup) const = 0; @@ -45,11 +45,15 @@ public: virtual void add_routing_info(service_t _service, instance_t _instance, major_version_t _major, minor_version_t _minor, ttl_t _ttl, - const boost::asio::ip::address &_address, uint16_t _port, - bool _reliable) = 0; + const boost::asio::ip::address &_reliable_address, + uint16_t _reliable_port, + const boost::asio::ip::address &_unreliable_address, + uint16_t _unreliable_port) = 0; virtual void del_routing_info(service_t _service, instance_t _instance, - bool _reliable) = 0; + bool _has_reliable, bool _has_unreliable) = 0; + + virtual ttl_t update_routing_info(ttl_t _elapsed) = 0; virtual void on_subscribe(service_t _service, instance_t _instance, eventgroup_t _eventgroup, diff --git a/implementation/service_discovery/include/service_discovery_impl.hpp b/implementation/service_discovery/include/service_discovery_impl.hpp index d07698e..0aceb02 100644 --- a/implementation/service_discovery/include/service_discovery_impl.hpp +++ b/implementation/service_discovery/include/service_discovery_impl.hpp @@ -11,10 +11,12 @@ #include #include +#include #include #include "service_discovery.hpp" #include "../../routing/include/types.hpp" +#include "ip_option_impl.hpp" namespace vsomeip { @@ -54,13 +56,14 @@ public: void subscribe(service_t _service, instance_t _instance, eventgroup_t _eventgroup, major_version_t _major, ttl_t _ttl, client_t _client); void unsubscribe(service_t _service, instance_t _instance, - eventgroup_t _eventgroup); + eventgroup_t _eventgroup, client_t _client); + void unsubscribe_all(service_t _service, instance_t _instance); - void send(const std::string &_name, bool _is_announcing); + void send(bool _is_announcing); void on_message(const byte_t *_data, length_t _length); - void on_offer_change(const std::string &_name); + void on_offer_change(); private: session_t get_session(const boost::asio::ip::address &_address); @@ -74,22 +77,39 @@ private: requests_t &_requests); void insert_offer_entries(std::shared_ptr &_message, services_t &_services); + void insert_offer_service(std::shared_ptr _message, + service_t _service, instance_t _instance, + const std::shared_ptr &_info); void insert_subscription(std::shared_ptr &_message, service_t _service, instance_t _instance, eventgroup_t _eventgroup, std::shared_ptr &_subscription); void insert_subscription_ack(std::shared_ptr &_message, service_t _service, instance_t _instance, eventgroup_t _eventgroup, + std::shared_ptr &_info, ttl_t _ttl); + void insert_subscription_nack(std::shared_ptr &_message, service_t _service, + instance_t _instance, eventgroup_t _eventgroup, std::shared_ptr &_info); void process_serviceentry(std::shared_ptr &_entry, const std::vector > &_options); + void process_offerservice_serviceentry( + service_t _service, instance_t _instance, major_version_t _major, + minor_version_t _minor, ttl_t _ttl, + const boost::asio::ip::address &_reliable_address, + uint16_t _reliable_port, + const boost::asio::ip::address &_unreliable_address, + uint16_t _unreliable_port); + void send_unicast_offer_service(const std::shared_ptr& _info, + service_t _service, instance_t _instance, + major_version_t _major, + minor_version_t _minor); + void process_findservice_serviceentry(service_t _service, + instance_t _instance, + major_version_t _major, + minor_version_t _minor); void process_eventgroupentry(std::shared_ptr &_entry, const std::vector > &_options); - void handle_service_availability(service_t _service, instance_t _instance, - major_version_t _major, minor_version_t _minor, ttl_t _ttl, - const boost::asio::ip::address &_address, uint16_t _port, - bool _reliable); void handle_eventgroup_subscription(service_t _service, instance_t _instance, eventgroup_t _eventgroup, major_version_t _major, ttl_t _ttl, @@ -99,6 +119,21 @@ private: instance_t _instance, eventgroup_t _eventgroup, major_version_t _major, ttl_t _ttl, const boost::asio::ip::address &_address, uint16_t _port); + void serialize_and_send(std::shared_ptr _message, + const boost::asio::ip::address &_address); + + void start_ttl_timer(); + ttl_t stop_ttl_timer(); + void check_ttl(const boost::system::error_code &_error); + boost::asio::ip::address get_current_remote_address() const; + bool check_static_header_fields( + const std::shared_ptr &_message) const; + void send_eventgroup_subscription_nack(service_t _service, + instance_t _instance, + eventgroup_t _eventgroup, + major_version_t _major); + bool check_layer_four_protocol( + const std::shared_ptr _ip_option) const; private: boost::asio::io_service &io_; @@ -107,6 +142,7 @@ private: boost::asio::ip::address unicast_; uint16_t port_; bool reliable_; + std::shared_ptr endpoint_; std::shared_ptr serializer_; std::shared_ptr deserializer_; @@ -119,6 +155,7 @@ private: std::map > > > > subscribed_; + std::mutex subscribed_mutex_; std::mutex serialize_mutex_; @@ -127,6 +164,11 @@ private: // Runtime std::weak_ptr runtime_; + + // TTL handling + boost::asio::system_timer ttl_timer_; + ttl_t smallest_ttl_; + ttl_t ttl_; }; } // namespace sd diff --git a/implementation/service_discovery/include/subscription.hpp b/implementation/service_discovery/include/subscription.hpp index c710b9d..bda9698 100644 --- a/implementation/service_discovery/include/subscription.hpp +++ b/implementation/service_discovery/include/subscription.hpp @@ -20,8 +20,7 @@ class subscription { public: subscription(major_version_t _major, ttl_t _ttl, std::shared_ptr _reliable, - std::shared_ptr _unreliable, - client_t _target); + std::shared_ptr _unreliable); ~subscription(); major_version_t get_major() const; @@ -30,7 +29,7 @@ public: std::shared_ptr get_endpoint(bool _reliable) const; void set_endpoint(std::shared_ptr _endpoint, bool _reliable); - bool is_acknowleged() const; + bool is_acknowledged() const; void set_acknowledged(bool _is_acknowledged); private: diff --git a/implementation/service_discovery/src/configuration_option_impl.cpp b/implementation/service_discovery/src/configuration_option_impl.cpp index e6092da..67a9d4c 100755 --- a/implementation/service_discovery/src/configuration_option_impl.cpp +++ b/implementation/service_discovery/src/configuration_option_impl.cpp @@ -33,13 +33,13 @@ bool configuration_option_impl::operator ==(const option_impl &_other) const { void configuration_option_impl::add_item(const std::string &_key, const std::string &_value) { configuration_[_key] = _value; - length_ += (_key.length() + _value.length() + 2); // +2 for the '=' and length + length_ = uint16_t(length_ + _key.length() + _value.length() + 2u); // +2 for the '=' and length } void configuration_option_impl::remove_item(const std::string &_key) { auto it = configuration_.find(_key); if (it != configuration_.end()) { - length_ -= (it->first.length() + it->second.length() + 2); + length_ = uint16_t(length_ - (it->first.length() + it->second.length() + 2u)); configuration_.erase(it); } } @@ -72,7 +72,7 @@ bool configuration_option_impl::serialize(vsomeip::serializer *_to) const { std::string configuration_string; for (auto i = configuration_.begin(); i != configuration_.end(); ++i) { - char l_length = 1 + i->first.length() + i->second.length(); + char l_length = char(1 + i->first.length() + i->second.length()); configuration_string.push_back(l_length); configuration_string.append(i->first); configuration_string.push_back('='); @@ -84,7 +84,7 @@ bool configuration_option_impl::serialize(vsomeip::serializer *_to) const { if (is_successful) { is_successful = _to->serialize( reinterpret_cast(configuration_string.c_str()), - configuration_string.length()); + uint32_t(configuration_string.length())); } return is_successful; diff --git a/implementation/service_discovery/src/entry_impl.cpp b/implementation/service_discovery/src/entry_impl.cpp index 735f120..ea7a511 100755 --- a/implementation/service_discovery/src/entry_impl.cpp +++ b/implementation/service_discovery/src/entry_impl.cpp @@ -20,6 +20,8 @@ entry_impl::entry_impl() { service_ = 0x0; instance_ = 0x0; ttl_ = 0x0; + num_options_[0] = 0; + num_options_[1] = 0; } entry_impl::entry_impl(const entry_impl &_entry) { @@ -28,6 +30,8 @@ entry_impl::entry_impl(const entry_impl &_entry) { service_ = _entry.service_; instance_ = _entry.instance_; ttl_ = _entry.ttl_; + num_options_[0] = _entry.num_options_[0]; + num_options_[1] = _entry.num_options_[1]; } entry_impl::~entry_impl() { @@ -86,7 +90,7 @@ void entry_impl::assign_option(const std::shared_ptr &_option, if (_run > 0 && _run <= VSOMEIP_MAX_OPTION_RUN) { _run--; // Index = Run-1 - uint8_t option_index = get_owning_message()->get_option_index(_option); + uint8_t option_index = uint8_t(get_owning_message()->get_option_index(_option)); if (0x10 > option_index) { // as we have only a nibble for the option counter options_[_run].push_back(option_index); std::sort(options_[_run].begin(), options_[_run].end()); @@ -112,7 +116,7 @@ bool entry_impl::serialize(vsomeip::serializer *_to) const { index_second_option_run = options_[1][0]; is_successful = is_successful && _to->serialize(index_second_option_run); - uint8_t number_of_options = ((((uint8_t) options_[0].size()) << 4) + uint8_t number_of_options = uint8_t((((uint8_t) options_[0].size()) << 4) | (((uint8_t) options_[1].size()) & 0x0F)); is_successful = is_successful && _to->serialize(number_of_options); @@ -128,7 +132,7 @@ bool entry_impl::serialize(vsomeip::serializer *_to) const { bool entry_impl::deserialize(vsomeip::deserializer *_from) { bool is_successful = (0 != _from); - uint8_t its_type; + uint8_t its_type(0); is_successful = is_successful && _from->deserialize(its_type); type_ = static_cast(its_type); @@ -141,13 +145,13 @@ bool entry_impl::deserialize(vsomeip::deserializer *_from) { uint8_t its_numbers; is_successful = is_successful && _from->deserialize(its_numbers); - uint8_t its_numbers1 = (its_numbers >> 4); - uint8_t its_numbers2 = (its_numbers & 0xF); + num_options_[0] = uint8_t(its_numbers >> 4); + num_options_[1] = uint8_t(its_numbers & 0xF); - for (uint8_t i = its_index1; i < its_index1 + its_numbers1; ++i) + for (uint8_t i = its_index1; i < its_index1 + num_options_[0]; ++i) options_[0].push_back(i); - for (uint8_t i = its_index2; i < its_index2 + its_numbers2; ++i) + for (uint8_t i = its_index2; i < its_index2 + num_options_[1]; ++i) options_[1].push_back(i); uint16_t its_id; @@ -169,5 +173,12 @@ bool entry_impl::is_eventgroup_entry() const { && type_ <= entry_type_e::SUBSCRIBE_EVENTGROUP_ACK); } +uint8_t entry_impl::get_num_options(uint8_t _run) const { + if (_run < 1 || _run > VSOMEIP_MAX_OPTION_RUN) { + return 0x0; + } + return num_options_[_run-1]; +} + } // namespace sd } // namespace vsomeip diff --git a/implementation/service_discovery/src/eventgroupentry_impl.cpp b/implementation/service_discovery/src/eventgroupentry_impl.cpp index ba303d9..024756d 100755 --- a/implementation/service_discovery/src/eventgroupentry_impl.cpp +++ b/implementation/service_discovery/src/eventgroupentry_impl.cpp @@ -34,7 +34,7 @@ void eventgroupentry_impl::set_eventgroup(eventgroup_t _eventgroup) { bool eventgroupentry_impl::serialize(vsomeip::serializer *_to) const { bool is_successful = entry_impl::serialize(_to); - is_successful = is_successful && _to->serialize(protocol::reserved_byte); + is_successful = is_successful && _to->serialize(major_version_); is_successful = is_successful && _to->serialize(static_cast(ttl_), true); @@ -50,8 +50,9 @@ bool eventgroupentry_impl::serialize(vsomeip::serializer *_to) const { bool eventgroupentry_impl::deserialize(vsomeip::deserializer *_from) { bool is_successful = entry_impl::deserialize(_from); - uint8_t its_reserved0; - is_successful = is_successful && _from->deserialize(its_reserved0); + uint8_t tmp_major_version; + is_successful = is_successful && _from->deserialize(tmp_major_version); + major_version_ = static_cast(tmp_major_version); uint32_t its_ttl; is_successful = is_successful && _from->deserialize(its_ttl, true); diff --git a/implementation/service_discovery/src/ip_option_impl.cpp b/implementation/service_discovery/src/ip_option_impl.cpp new file mode 100644 index 0000000..3fcffac --- /dev/null +++ b/implementation/service_discovery/src/ip_option_impl.cpp @@ -0,0 +1,59 @@ +// Copyright (C) 2014-2015 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 "../include/constants.hpp" +#include "../include/ip_option_impl.hpp" +#include "../../message/include/deserializer.hpp" +#include "../../message/include/serializer.hpp" + +namespace vsomeip { +namespace sd { + +ip_option_impl::ip_option_impl() : + protocol_(layer_four_protocol_e::UNKNOWN), + port_(0xFFFF) { +} + +ip_option_impl::~ip_option_impl() { +} + +bool ip_option_impl::operator ==(const option_impl &_other) const { + if (type_ != _other.get_type()) + return false; + +#ifdef VSOMEIP_TODO + const ip_option_impl & other = + dynamic_cast(_other); +#endif + return true; +} + +unsigned short ip_option_impl::get_port() const { + return port_; +} + +void ip_option_impl::set_port(unsigned short _port) { + port_ = _port; +} + +layer_four_protocol_e ip_option_impl::get_layer_four_protocol() const { + return protocol_; +} + +void ip_option_impl::set_layer_four_protocol( + layer_four_protocol_e _protocol) { + protocol_ = _protocol; +} + +bool ip_option_impl::is_multicast() const { + return (type_ == option_type_e::IP4_MULTICAST + || type_ == option_type_e::IP6_MULTICAST); +} + +} // namespace sd +} // namespace vsomeip + diff --git a/implementation/service_discovery/src/ipv4_option_impl.cpp b/implementation/service_discovery/src/ipv4_option_impl.cpp index 6416cf0..ca5a2c5 100644 --- a/implementation/service_discovery/src/ipv4_option_impl.cpp +++ b/implementation/service_discovery/src/ipv4_option_impl.cpp @@ -13,26 +13,17 @@ namespace vsomeip { namespace sd { -ipv4_option_impl::ipv4_option_impl(bool _is_multicast) { +ipv4_option_impl::ipv4_option_impl(bool _is_multicast) : + address_({0}) { length_ = (1 + 4 + 1 + 1 + 2); type_ = ( _is_multicast ? option_type_e::IP4_MULTICAST : option_type_e::IP4_ENDPOINT); - is_udp_ = _is_multicast; } ipv4_option_impl::~ipv4_option_impl() { } -bool ipv4_option_impl::operator ==(const option_impl &_other) const { - if (type_ != _other.get_type()) - return false; - - const ipv4_option_impl & other = - dynamic_cast(_other); - return true; -} - const ipv4_address_t & ipv4_option_impl::get_address() const { return address_; } @@ -41,31 +32,11 @@ void ipv4_option_impl::set_address(const ipv4_address_t &_address) { address_ = _address; } -unsigned short ipv4_option_impl::get_port() const { - return port_; -} - -void ipv4_option_impl::set_port(unsigned short _port) { - port_ = _port; -} - -bool ipv4_option_impl::is_udp() const { - return is_udp_; -} - -void ipv4_option_impl::set_udp(bool _is_udp) { - is_udp_ = _is_udp; -} - -bool ipv4_option_impl::is_multicast() const { - return (type_ == option_type_e::IP4_MULTICAST); -} - bool ipv4_option_impl::serialize(vsomeip::serializer *_to) const { bool is_successful = option_impl::serialize(_to); - _to->serialize(&address_[0], address_.size()); + _to->serialize(&address_[0], uint32_t(address_.size())); _to->serialize(protocol::reserved_byte); - _to->serialize(is_udp_ ? protocol::udp : protocol::tcp); + _to->serialize(static_cast(protocol_)); _to->serialize(port_); return is_successful; } @@ -76,7 +47,14 @@ bool ipv4_option_impl::deserialize(vsomeip::deserializer *_from) { _from->deserialize(address_.data(), 4); _from->deserialize(its_reserved); _from->deserialize(its_reserved); - is_udp_ = (protocol::udp == its_reserved); + switch (static_cast(its_reserved)) { + case layer_four_protocol_e::TCP: + case layer_four_protocol_e::UDP: + protocol_ = static_cast(its_reserved); + break; + default: + protocol_ = layer_four_protocol_e::UNKNOWN; + } _from->deserialize(port_); return is_successful; } diff --git a/implementation/service_discovery/src/ipv6_option_impl.cpp b/implementation/service_discovery/src/ipv6_option_impl.cpp index 556045c..1aa2570 100755 --- a/implementation/service_discovery/src/ipv6_option_impl.cpp +++ b/implementation/service_discovery/src/ipv6_option_impl.cpp @@ -13,27 +13,17 @@ namespace vsomeip { namespace sd { -ipv6_option_impl::ipv6_option_impl(bool _is_multicast) { +ipv6_option_impl::ipv6_option_impl(bool _is_multicast) : + address_({0}) { length_ = (1 + 16 + 1 + 1 + 2); type_ = ( _is_multicast ? option_type_e::IP6_MULTICAST : option_type_e::IP6_ENDPOINT); - is_udp_ = _is_multicast; } ipv6_option_impl::~ipv6_option_impl() { } -bool ipv6_option_impl::operator ==(const option_impl &_other) const { - if (_other.get_type() != option_type_e::IP6_ENDPOINT) - return false; - - const ipv6_option_impl& other = - dynamic_cast(_other); - - return true; // TODO: -} - const ipv6_address_t & ipv6_option_impl::get_address() const { return address_; } @@ -42,27 +32,11 @@ void ipv6_option_impl::set_address(const ipv6_address_t &_address) { address_ = _address; } -unsigned short ipv6_option_impl::get_port() const { - return port_; -} - -void ipv6_option_impl::set_port(unsigned short _port) { - port_ = _port; -} - -bool ipv6_option_impl::is_udp() const { - return is_udp_; -} - -void ipv6_option_impl::set_udp(bool _is_udp) { - is_udp_ = _is_udp; -} - bool ipv6_option_impl::serialize(vsomeip::serializer *_to) const { bool is_successful = option_impl::serialize(_to); - _to->serialize(&address_[0], address_.size()); + _to->serialize(&address_[0], uint32_t(address_.size())); _to->serialize(protocol::reserved_byte); - _to->serialize(is_udp_ ? protocol::udp : protocol::tcp); + _to->serialize(static_cast(protocol_)); _to->serialize(port_); return is_successful; } @@ -73,7 +47,14 @@ bool ipv6_option_impl::deserialize(vsomeip::deserializer *_from) { _from->deserialize(address_.data(), 16); _from->deserialize(its_reserved); _from->deserialize(its_reserved); - is_udp_ = (protocol::udp == its_reserved); + switch (static_cast(its_reserved)) { + case layer_four_protocol_e::TCP: + case layer_four_protocol_e::UDP: + protocol_ = static_cast(its_reserved); + break; + default: + protocol_ = layer_four_protocol_e::UNKNOWN; + } _from->deserialize(port_); return is_successful; } diff --git a/implementation/service_discovery/src/message_impl.cpp b/implementation/service_discovery/src/message_impl.cpp index 6736b50..3130dda 100755 --- a/implementation/service_discovery/src/message_impl.cpp +++ b/implementation/service_discovery/src/message_impl.cpp @@ -7,7 +7,6 @@ #include #include -#include #include "../include/constants.hpp" #include "../include/defines.hpp" @@ -19,6 +18,7 @@ #include "../include/load_balancing_option_impl.hpp" #include "../include/protection_option_impl.hpp" #include "../include/message_impl.hpp" +#include "../../logging/include/logger.hpp" #include "../../message/include/deserializer.hpp" #include "../../message/include/payload_impl.hpp" #include "../../message/include/serializer.hpp" @@ -31,15 +31,16 @@ message_impl::message_impl() { header_.method_ = 0x8100; header_.protocol_version_ = 0x01; flags_ = 0x00; + options_length_ = 0x0000; } message_impl::~message_impl() { } length_t message_impl::get_length() const { - length_t current_length = VSOMEIP_SOMEIP_HEADER_SIZE - + VSOMEIP_SOMEIP_SD_DATA_SIZE; - current_length += (entries_.size() * VSOMEIP_SOMEIP_SD_ENTRY_SIZE); + length_t current_length = (VSOMEIP_SOMEIP_HEADER_SIZE + + VSOMEIP_SOMEIP_SD_DATA_SIZE); + current_length += uint32_t(entries_.size() * VSOMEIP_SOMEIP_SD_ENTRY_SIZE); for (size_t i = 0; i < options_.size(); ++i) { current_length += (options_[i]->get_length() + VSOMEIP_SOMEIP_SD_OPTION_HEADER_SIZE); @@ -55,9 +56,9 @@ bool message_impl::get_reboot_flag() const { void message_impl::set_reboot_flag(bool _is_set) { if (_is_set) - flags_ |= VSOMEIP_REBOOT_FLAG; + flags_ |= flags_t(VSOMEIP_REBOOT_FLAG); else - flags_ &= ~VSOMEIP_REBOOT_FLAG; + flags_ &= flags_t(~VSOMEIP_REBOOT_FLAG); } #define VSOMEIP_UNICAST_FLAG 0x40 @@ -68,12 +69,13 @@ bool message_impl::get_unicast_flag() const { void message_impl::set_unicast_flag(bool _is_set) { if (_is_set) - flags_ |= VSOMEIP_UNICAST_FLAG; + flags_ |= flags_t(VSOMEIP_UNICAST_FLAG); else - flags_ &= ~VSOMEIP_UNICAST_FLAG; + flags_ &= flags_t(~VSOMEIP_UNICAST_FLAG); } void message_impl::set_length(length_t _length) { + (void)_length; } std::shared_ptr message_impl::create_eventgroup_entry() { @@ -154,7 +156,7 @@ int16_t message_impl::get_option_index( const std::shared_ptr &_option) const { int16_t i = 0; - while (i < options_.size()) { + while (i < int16_t(options_.size())) { if (options_[i] == _option) return i; i++; @@ -163,11 +165,16 @@ int16_t message_impl::get_option_index( return -1; } +uint32_t message_impl::get_options_length() { + return options_length_; +} + std::shared_ptr message_impl::get_payload() const { return std::make_shared(); } void message_impl::set_payload(std::shared_ptr _payload) { + (void)_payload; } bool message_impl::serialize(vsomeip::serializer *_to) const { @@ -177,7 +184,7 @@ bool message_impl::serialize(vsomeip::serializer *_to) const { is_successful = is_successful && _to->serialize(protocol::reserved_long, true); - uint32_t entries_length = (entries_.size() * VSOMEIP_SOMEIP_SD_ENTRY_SIZE); + uint32_t entries_length = uint32_t(entries_.size() * VSOMEIP_SOMEIP_SD_ENTRY_SIZE); is_successful = is_successful && _to->serialize(entries_length); for (auto it = entries_.begin(); it != entries_.end(); ++it) @@ -213,7 +220,7 @@ bool message_impl::deserialize(vsomeip::deserializer *_from) { is_successful = is_successful && _from->deserialize(entries_length); // backup the current remaining length - uint32_t save_remaining = _from->get_remaining(); + uint32_t save_remaining = uint32_t(_from->get_remaining()); // set remaining bytes to length of entries array _from->set_remaining(entries_length); @@ -231,9 +238,18 @@ bool message_impl::deserialize(vsomeip::deserializer *_from) { // set length to remaining bytes after entries array _from->set_remaining(save_remaining - entries_length); + // Don't try to deserialize options if there aren't any + if(_from->get_remaining() == 0) { + return is_successful; + } + // deserialize the options - uint32_t options_length = 0; - is_successful = is_successful && _from->deserialize(options_length); + is_successful = is_successful && _from->deserialize(options_length_); + + // check if there is unreferenced data behind the last option and discard it + if(_from->get_remaining() > options_length_) { + _from->set_remaining(options_length_); + } while (is_successful && _from->get_remaining()) { std::shared_ptr < option_impl > its_option(deserialize_option(_from)); @@ -279,6 +295,7 @@ entry_impl * message_impl::deserialize_entry(vsomeip::deserializer *_from) { // deserialize object if (0 != deserialized_entry) { + deserialized_entry->set_owning_message(this); if (!deserialized_entry->deserialize(_from)) { delete deserialized_entry; deserialized_entry = 0; @@ -323,6 +340,7 @@ option_impl * message_impl::deserialize_option(vsomeip::deserializer *_from) { break; default: + deserialized_option = new option_impl(); break; }; diff --git a/implementation/service_discovery/src/option_impl.cpp b/implementation/service_discovery/src/option_impl.cpp index a9ac4a9..71bbc6a 100755 --- a/implementation/service_discovery/src/option_impl.cpp +++ b/implementation/service_discovery/src/option_impl.cpp @@ -20,6 +20,7 @@ option_impl::~option_impl() { } bool option_impl::operator ==(const option_impl &_other) const { + (void)_other; return false; } @@ -43,7 +44,25 @@ bool option_impl::deserialize(vsomeip::deserializer *_from) { && _from->deserialize(its_type) && _from->deserialize(reserved)); if (l_result) { - type_ = static_cast(its_type); + switch(static_cast(its_type)) { + case option_type_e::CONFIGURATION: + case option_type_e::LOAD_BALANCING: + case option_type_e::PROTECTION: + case option_type_e::IP4_ENDPOINT: + case option_type_e::IP6_ENDPOINT: + case option_type_e::IP4_MULTICAST: + case option_type_e::IP6_MULTICAST: + type_ = static_cast(its_type); + break; + default: + type_ = option_type_e::UNKNOWN; + // reduce remaining bytes of the deserializer by the length of + // the unknown option to make it look like it was deserialized. + // - 1 because the reserved byte which is included in the length + // was already deserialized (s. above) + std::size_t remaining = _from->get_remaining(); + _from->set_remaining(remaining - (length_ - 1)); + } } return l_result; diff --git a/implementation/service_discovery/src/service_discovery_fsm.cpp b/implementation/service_discovery/src/service_discovery_fsm.cpp index 8b2cb17..d2428dd 100644 --- a/implementation/service_discovery/src/service_discovery_fsm.cpp +++ b/implementation/service_discovery/src/service_discovery_fsm.cpp @@ -6,12 +6,11 @@ #include #include -#include -#include - #include "../include/defines.hpp" #include "../include/service_discovery.hpp" #include "../include/service_discovery_fsm.hpp" +#include "../../configuration/include/configuration.hpp" +#include "../../logging/include/logger.hpp" namespace vsomeip { namespace sd { @@ -48,12 +47,14 @@ inactive::inactive(my_context context) std::shared_ptr < service_discovery_fsm > fsm = outermost_context().fsm_.lock(); if (fsm) { - VSOMEIP_TRACE << "sd<" << fsm->get_name() << ">::inactive"; + 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(); } @@ -62,6 +63,8 @@ sc::result inactive::react(const ev_none &_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(); @@ -78,7 +81,7 @@ active::active(my_context _context) std::shared_ptr < service_discovery_fsm > fsm = outermost_context().fsm_.lock(); if (fsm) { - VSOMEIP_TRACE << "sd<" << fsm->get_name() << ">::active"; + VSOMEIP_TRACE << "sd::active"; } } @@ -86,6 +89,8 @@ 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_) @@ -102,12 +107,13 @@ initial::initial(my_context _context) std::shared_ptr < service_discovery_fsm > fsm = outermost_context().fsm_.lock(); if (fsm) { - VSOMEIP_TRACE << "sd<" << fsm->get_name() << ">::active.initial"; + VSOMEIP_TRACE << "sd::active.initial"; outermost_context().start_timer(outermost_context().initial_delay_); } } sc::result initial::react(const ev_timeout &_event) { + (void)_event; return transit(); } @@ -119,8 +125,8 @@ repeat::repeat(my_context _context) std::shared_ptr < service_discovery_fsm > fsm = outermost_context().fsm_.lock(); if (fsm) { - VSOMEIP_TRACE << "sd<" << fsm->get_name() << ">::active.repeat"; - uint32_t its_timeout = (outermost_context().repetition_base_delay_ + VSOMEIP_TRACE << "sd::active.repeat"; + uint32_t its_timeout = (outermost_context().repetitions_base_delay_ << outermost_context().run_); outermost_context().run_++; fsm->send(false); @@ -129,13 +135,16 @@ repeat::repeat(my_context _context) } sc::result repeat::react(const ev_timeout &_event) { - if (outermost_context().run_ < outermost_context().repetition_max_) + (void)_event; + + if (outermost_context().run_ < outermost_context().repetitions_max_) return transit(); return transit(); } sc::result repeat::react(const ev_find_service &_event) { + (void)_event; return discard_event(); } @@ -147,7 +156,7 @@ announce::announce(my_context _context) std::shared_ptr < service_discovery_fsm > fsm = outermost_context().fsm_.lock(); if (fsm) { - VSOMEIP_TRACE << "sd<" << fsm->get_name() << ">::active.announce"; + VSOMEIP_TRACE << "sd::active.announce"; outermost_context().start_timer( outermost_context().cyclic_offer_delay_); fsm->send(true); @@ -155,14 +164,17 @@ announce::announce(my_context _context) } sc::result announce::react(const ev_timeout &_event) { + (void)_event; return transit(); } sc::result announce::react(const ev_find_service &_event) { + (void)_event; return discard_event(); } sc::result announce::react(const ev_offer_change &_event) { + (void)_event; return transit(); } @@ -171,9 +183,9 @@ sc::result announce::react(const ev_offer_change &_event) { /////////////////////////////////////////////////////////////////////////////// // Interface /////////////////////////////////////////////////////////////////////////////// -service_discovery_fsm::service_discovery_fsm(const std::string &_name, +service_discovery_fsm::service_discovery_fsm( std::shared_ptr _discovery) - : name_(_name), discovery_(_discovery), fsm_( + : discovery_(_discovery), fsm_( std::make_shared < _sd::fsm > (_discovery->get_io())) { std::shared_ptr < service_discovery > discovery = discovery_.lock(); @@ -181,57 +193,54 @@ service_discovery_fsm::service_discovery_fsm(const std::string &_name, std::shared_ptr < configuration > its_configuration = discovery->get_configuration(); - int32_t its_min_initial_delay = - its_configuration->get_min_initial_delay(name_); - if (its_min_initial_delay < 0) - its_min_initial_delay = VSOMEIP_SD_DEFAULT_MIN_INITIAL_DELAY; + 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_max_initial_delay = - its_configuration->get_max_initial_delay(name_); - if (its_max_initial_delay <= 0) - its_max_initial_delay = VSOMEIP_SD_DEFAULT_MAX_INITIAL_DELAY; + 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_min_initial_delay > its_max_initial_delay) { - int32_t tmp_initial_delay = its_min_initial_delay; - its_min_initial_delay = its_max_initial_delay; - its_max_initial_delay = its_min_initial_delay; + 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_min_initial_delay << ", " - << its_max_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_min_initial_delay, its_max_initial_delay); + its_initial_delay_min, its_initial_delay_max); fsm_->initial_delay_ = its_distribution(its_generator); - fsm_->repetition_base_delay_ = - its_configuration->get_repetition_base_delay(name_); - if (fsm_->repetition_base_delay_ <= 0) - fsm_->repetition_base_delay_ - = VSOMEIP_SD_DEFAULT_REPETITION_BASE_DELAY; - fsm_->repetition_max_ = its_configuration->get_repetition_max(name_); - if (fsm_->repetition_max_ <= 0) - fsm_->repetition_max_ = VSOMEIP_SD_DEFAULT_REPETITION_MAX; - - fsm_->cyclic_offer_delay_ = - its_configuration->get_cyclic_offer_delay(name_); + 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 [" << fsm_->initial_delay_ << ":" - << fsm_->repetition_base_delay_ << ":" - << (int) fsm_->repetition_max_ << ":" + << fsm_->repetitions_base_delay_ << ":" + << (int) fsm_->repetitions_max_ << ":" << fsm_->cyclic_offer_delay_ << "]"; } else { VSOMEIP_ERROR << "SD initialization failed"; } } -const std::string & service_discovery_fsm::get_name() const { - return name_; -} - void service_discovery_fsm::start() { fsm_->set_fsm(shared_from_this()); fsm_->initiate(); @@ -243,7 +252,7 @@ void service_discovery_fsm::stop() { void service_discovery_fsm::send(bool _is_announcing) { std::shared_ptr < service_discovery > discovery = discovery_.lock(); if (discovery) - discovery->send(name_, _is_announcing); + discovery->send(_is_announcing); } } // namespace sd diff --git a/implementation/service_discovery/src/service_discovery_impl.cpp b/implementation/service_discovery/src/service_discovery_impl.cpp index 42d93b6..38975fb 100644 --- a/implementation/service_discovery/src/service_discovery_impl.cpp +++ b/implementation/service_discovery/src/service_discovery_impl.cpp @@ -3,8 +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 -#include +#include #include "../include/constants.hpp" #include "../include/defines.hpp" @@ -21,23 +20,27 @@ #include "../include/service_discovery_impl.hpp" #include "../include/serviceentry_impl.hpp" #include "../include/subscription.hpp" +#include "../../configuration/include/configuration.hpp" #include "../../configuration/include/internal.hpp" #include "../../endpoints/include/endpoint.hpp" #include "../../endpoints/include/endpoint_definition.hpp" #include "../../endpoints/include/tcp_server_endpoint_impl.hpp" #include "../../endpoints/include/udp_server_endpoint_impl.hpp" +#include "../../logging/include/logger.hpp" #include "../../message/include/serializer.hpp" #include "../../routing/include/eventgroupinfo.hpp" -#include "../../routing/include/servicegroup.hpp" #include "../../routing/include/serviceinfo.hpp" namespace vsomeip { namespace sd { service_discovery_impl::service_discovery_impl(service_discovery_host *_host) - : host_(_host), io_(_host->get_io()), serializer_( - std::make_shared()), deserializer_( - std::make_shared()) { + : io_(_host->get_io()), + host_(_host), + serializer_(std::make_shared()), + deserializer_(std::make_shared()), + ttl_timer_(_host->get_io()), + smallest_ttl_(DEFAULT_TTL) { } service_discovery_impl::~service_discovery_impl() { @@ -53,27 +56,15 @@ boost::asio::io_service & service_discovery_impl::get_io() { void service_discovery_impl::init() { runtime_ = runtime::get(); - default_ = std::make_shared < service_discovery_fsm - > ("default", shared_from_this()); + default_ = std::make_shared(shared_from_this()); std::shared_ptr < configuration > its_configuration = host_->get_configuration(); if (its_configuration) { - unicast_ = its_configuration->get_unicast(); - - std::set < std::string > its_servicegroups = - its_configuration->get_servicegroups(); - for (auto its_group : its_servicegroups) { - if (its_group != "default" - && its_configuration->is_local_servicegroup(its_group)) { - additional_[its_group] = std::make_shared - < service_discovery_fsm - > (its_group, shared_from_this()); - } - } + unicast_ = its_configuration->get_unicast_address(); - port_ = its_configuration->get_service_discovery_port(); - reliable_ = (its_configuration->get_service_discovery_protocol() + port_ = its_configuration->get_sd_port(); + reliable_ = (its_configuration->get_sd_protocol() == "tcp"); serializer_->create_data( @@ -81,10 +72,10 @@ void service_discovery_impl::init() { VSOMEIP_MAX_TCP_MESSAGE_SIZE : VSOMEIP_MAX_UDP_MESSAGE_SIZE); - host_->create_service_discovery_endpoint( - its_configuration->get_service_discovery_multicast(), port_, - reliable_); + endpoint_ = host_->create_service_discovery_endpoint( + its_configuration->get_sd_multicast(), port_, reliable_); + ttl_ = its_configuration->get_sd_ttl(); } else { VSOMEIP_ERROR << "SD: no configuration found!"; } @@ -134,6 +125,8 @@ void service_discovery_impl::release_service(service_t _service, void service_discovery_impl::subscribe(service_t _service, instance_t _instance, eventgroup_t _eventgroup, major_version_t _major, ttl_t _ttl, client_t _client) { + std::lock_guard its_lock(subscribed_mutex_); + auto found_service = subscribed_.find(_service); if (found_service != subscribed_.end()) { auto found_instance = found_service->second.find(_instance); @@ -155,70 +148,108 @@ void service_discovery_impl::subscribe(service_t _service, instance_t _instance, } } + // New subscription std::shared_ptr < endpoint > its_reliable = host_->find_or_create_remote_client( _service, _instance, true, _client); std::shared_ptr < endpoint > its_unreliable = host_->find_or_create_remote_client( _service, _instance, false, _client); std::shared_ptr < subscription > its_subscription = std::make_shared - < subscription > (_major, _ttl, its_reliable, its_unreliable, _client); + < subscription > (_major, _ttl, its_reliable, its_unreliable); subscribed_[_service][_instance][_eventgroup][_client] = its_subscription; - if (!its_subscription->is_acknowleged()) { - bool has_address(false); - boost::asio::ip::address its_address; - - std::shared_ptr its_endpoint - = host_->find_or_create_remote_client(_service, _instance, false, _client); + bool has_address(false); + boost::asio::ip::address its_address; - if (its_endpoint) { - has_address = its_endpoint->get_remote_address(its_address); - its_subscription->set_endpoint(its_endpoint, false); - } + std::shared_ptr its_endpoint + = host_->find_or_create_remote_client(_service, _instance, false, _client); - its_endpoint = host_->find_or_create_remote_client(_service, _instance, true, _client); - if (its_endpoint) { - has_address = has_address || its_endpoint->get_remote_address(its_address); - its_subscription->set_endpoint(its_endpoint, true); - } + if (its_endpoint) { + has_address = its_endpoint->get_remote_address(its_address); + its_subscription->set_endpoint(its_endpoint, false); + } - if (has_address) { - std::shared_ptr < runtime > its_runtime = runtime_.lock(); - if (!its_runtime) - return; + its_endpoint = host_->find_or_create_remote_client(_service, _instance, true, _client); + if (its_endpoint) { + has_address = has_address || its_endpoint->get_remote_address(its_address); + its_subscription->set_endpoint(its_endpoint, true); + } - std::shared_ptr < message_impl > its_message - = its_runtime->create_message(); + if (has_address) { + std::shared_ptr its_runtime = runtime_.lock(); + if (!its_runtime) + return; - // TODO: consume major & ttl - insert_subscription(its_message, _service, _instance, _eventgroup, - its_subscription); - its_message->set_session(get_session(its_address)); + std::shared_ptr its_message + = its_runtime->create_message(); - serializer_->serialize(its_message.get()); + // TODO: consume major & ttl + insert_subscription(its_message, _service, _instance, _eventgroup, + its_subscription); + serialize_and_send(its_message, its_address); - if (host_->send_to( - std::make_shared( - its_address, port_, reliable_), - serializer_->get_data(), - serializer_->get_size())) { - increment_session(its_address); - } - serializer_->reset(); - } + its_subscription->set_acknowledged(false); } } void service_discovery_impl::unsubscribe(service_t _service, - instance_t _instance, eventgroup_t _eventgroup) { - // TODO: add client_id!!! + instance_t _instance, eventgroup_t _eventgroup, client_t _client) { + + std::lock_guard its_lock(subscribed_mutex_); + auto found_service = subscribed_.find(_service); if (found_service != subscribed_.end()) { auto found_instance = found_service->second.find(_instance); if (found_instance != found_service->second.end()) { auto found_eventgroup = found_instance->second.find(_eventgroup); if (found_eventgroup != found_instance->second.end()) { - for (auto its_client : found_eventgroup->second) { - its_client.second->set_ttl(0); // is read once and removed afterwards! + auto found_client = found_eventgroup->second.find(_client); + if (found_client != found_eventgroup->second.end()) { + found_client->second->set_ttl(0); + } + } + } + } + + boost::asio::ip::address its_address; + + std::shared_ptr < runtime > its_runtime = runtime_.lock(); + if (!its_runtime) + return; + + std::shared_ptr < subscription > its_subscription = + subscribed_[_service][_instance][_eventgroup][_client]; + + auto endpoint = its_subscription->get_endpoint(false); + if (endpoint) { + endpoint->get_remote_address(its_address); + } else { + endpoint = its_subscription->get_endpoint(true); + if (endpoint) { + endpoint->get_remote_address(its_address); + } + } + + std::shared_ptr < message_impl > its_message + = its_runtime->create_message(); + + insert_subscription(its_message, _service, _instance, _eventgroup, + its_subscription); + its_message->set_session(get_session(its_address)); + + serialize_and_send(its_message, its_address); +} + +void service_discovery_impl::unsubscribe_all(service_t _service, instance_t _instance) { + std::lock_guard its_lock(subscribed_mutex_); + auto found_service = subscribed_.find(_service); + if (found_service != subscribed_.end()) { + auto found_instance = found_service->second.find(_instance); + if (found_instance != found_service->second.end()) { + for (auto &its_eventgroup : found_instance->second) { + for (auto its_client : its_eventgroup.second) { + its_client.second->set_acknowledged(true); + its_client.second->set_endpoint(nullptr, true); + its_client.second->set_endpoint(nullptr, false); } } } @@ -262,7 +293,9 @@ void service_discovery_impl::insert_option( if (its_option) { its_option->set_address(its_address); its_option->set_port(_port); - its_option->set_udp(!_is_reliable); + its_option->set_layer_four_protocol( + _is_reliable ? layer_four_protocol_e::TCP : + layer_four_protocol_e::UDP); _entry->assign_option(its_option, 1); } } else { @@ -272,7 +305,9 @@ void service_discovery_impl::insert_option( if (its_option) { its_option->set_address(its_address); its_option->set_port(_port); - its_option->set_udp(!_is_reliable); + its_option->set_layer_four_protocol( + _is_reliable ? layer_four_protocol_e::TCP : + layer_four_protocol_e::UDP); _entry->assign_option(its_option, 1); } } @@ -325,40 +360,8 @@ void service_discovery_impl::insert_offer_entries( std::shared_ptr &_message, services_t &_services) { for (auto its_service : _services) { for (auto its_instance : its_service.second) { - auto its_info = its_instance.second; - std::shared_ptr < serviceentry_impl > its_entry = - _message->create_service_entry(); - if (its_entry) { - its_entry->set_type(entry_type_e::OFFER_SERVICE); - its_entry->set_service(its_service.first); - its_entry->set_instance(its_instance.first); - its_entry->set_major_version(its_info->get_major()); - its_entry->set_minor_version(its_info->get_minor()); - its_entry->set_ttl(its_info->get_ttl()); - - std::shared_ptr < endpoint > its_endpoint = - its_info->get_endpoint(true); - if (its_endpoint) { - insert_option(_message, its_entry, unicast_, - its_endpoint->get_local_port(), true); - if (0 == its_info->get_ttl()) { - host_->del_routing_info(its_service.first, - its_instance.first, true); - } - } - - its_endpoint = its_info->get_endpoint(false); - if (its_endpoint) { - insert_option(_message, its_entry, unicast_, - its_endpoint->get_local_port(), false); - if (0 == its_info->get_ttl()) { - host_->del_routing_info(its_service.first, - its_instance.first, false); - } - } - } else { - VSOMEIP_ERROR << "Failed to create service entry."; - } + insert_offer_service(_message, its_service.first, + its_instance.first, its_instance.second); } } } @@ -391,7 +394,7 @@ void service_discovery_impl::insert_subscription( void service_discovery_impl::insert_subscription_ack( std::shared_ptr &_message, service_t _service, instance_t _instance, eventgroup_t _eventgroup, - std::shared_ptr &_info) { + std::shared_ptr &_info, ttl_t _ttl) { std::shared_ptr < eventgroupentry_impl > its_entry = _message->create_eventgroup_entry(); its_entry->set_type(entry_type_e::SUBSCRIBE_EVENTGROUP_ACK); @@ -399,7 +402,8 @@ void service_discovery_impl::insert_subscription_ack( its_entry->set_instance(_instance); its_entry->set_eventgroup(_eventgroup); its_entry->set_major_version(_info->get_major()); - its_entry->set_ttl(_info->get_ttl()); + // SWS_SD_00315 + its_entry->set_ttl(_ttl); boost::asio::ip::address its_address; uint16_t its_port; @@ -408,8 +412,29 @@ void service_discovery_impl::insert_subscription_ack( } } -void service_discovery_impl::send(const std::string &_name, - bool _is_announcing) { +void service_discovery_impl::insert_subscription_nack( + std::shared_ptr &_message, service_t _service, + instance_t _instance, eventgroup_t _eventgroup, + std::shared_ptr &_info) { + std::shared_ptr < eventgroupentry_impl > its_entry = + _message->create_eventgroup_entry(); + // SWS_SD_00316 and SWS_SD_00385 + its_entry->set_type(entry_type_e::STOP_SUBSCRIBE_EVENTGROUP_ACK); + its_entry->set_service(_service); + its_entry->set_instance(_instance); + its_entry->set_eventgroup(_eventgroup); + its_entry->set_major_version(_info->get_major()); + // SWS_SD_00432 + its_entry->set_ttl(0x0); + + boost::asio::ip::address its_address; + uint16_t its_port; + if (_info->get_multicast(its_address, its_port)) { + insert_option(_message, its_entry, its_address, its_port, false); + } +} + +void service_discovery_impl::send(bool _is_announcing) { std::shared_ptr < runtime > its_runtime = runtime_.lock(); if (!its_runtime) @@ -420,13 +445,13 @@ void service_discovery_impl::send(const std::string &_name, // TODO: optimize building of SD message (common options, utilize the two runs) - // If we are the default group and not in main phase, include "FindOffer"-entries - if (_name == "default" && !_is_announcing) { + // If we are not in main phase, include "FindOffer"-entries + if (!_is_announcing) { insert_find_entries(its_message, requested_); } // Always include the "OfferService"-entries for the service group - services_t its_offers = host_->get_offered_services(_name); + services_t its_offers = host_->get_offered_services(); insert_offer_entries(its_message, its_offers); // Serialize and send @@ -451,6 +476,13 @@ void service_discovery_impl::on_message(const byte_t *_data, length_t _length) { std::shared_ptr < message_impl > its_message(deserializer_->deserialize_sd_message()); if (its_message) { + // ignore all messages which are sent with invalid header fields + if(!check_static_header_fields(its_message)) { + return; + } + ttl_t expired = stop_ttl_timer(); + smallest_ttl_ = host_->update_routing_info(expired); + std::vector < std::shared_ptr > its_options = its_message->get_options(); for (auto its_entry : its_message->get_entries()) { @@ -466,35 +498,42 @@ void service_discovery_impl::on_message(const byte_t *_data, length_t _length) { process_eventgroupentry(its_eventgroup_entry, its_options); } } + start_ttl_timer(); + } else { + VSOMEIP_ERROR << "service_discovery_impl::on_message: deserialization error."; + return; } } -void service_discovery_impl::on_offer_change(const std::string &_name) { - if (_name == "default") { - default_->process(ev_offer_change()); - } else { - auto found_group = additional_.find(_name); - if (found_group != additional_.end()) { - found_group->second->process(ev_offer_change()); - } - } +void service_discovery_impl::on_offer_change() { + default_->process(ev_offer_change()); } // Entry processing void service_discovery_impl::process_serviceentry( std::shared_ptr &_entry, const std::vector > &_options) { + + // Read service info from entry + entry_type_e its_type = _entry->get_type(); service_t its_service = _entry->get_service(); instance_t its_instance = _entry->get_instance(); major_version_t its_major = _entry->get_major_version(); minor_version_t its_minor = _entry->get_minor_version(); ttl_t its_ttl = _entry->get_ttl(); + // Read address info from options + boost::asio::ip::address its_reliable_address; + uint16_t its_reliable_port(ILLEGAL_PORT); + + boost::asio::ip::address its_unreliable_address; + uint16_t its_unreliable_port(ILLEGAL_PORT); + + for (auto i : { 1, 2 }) { - for (auto its_index : _entry->get_options(i)) { - std::vector < byte_t > its_option_address; - uint16_t its_option_port = VSOMEIP_INVALID_PORT; + for (auto its_index : _entry->get_options(uint8_t(i))) { std::shared_ptr < option_impl > its_option = _options[its_index]; + switch (its_option->get_type()) { case option_type_e::IP4_ENDPOINT: { std::shared_ptr < ipv4_option_impl > its_ipv4_option = @@ -503,12 +542,15 @@ void service_discovery_impl::process_serviceentry( boost::asio::ip::address_v4 its_ipv4_address( its_ipv4_option->get_address()); - boost::asio::ip::address its_address(its_ipv4_address); - its_option_port = its_ipv4_option->get_port(); - handle_service_availability(its_service, its_instance, - its_major, its_minor, its_ttl, its_address, - its_option_port, !its_ipv4_option->is_udp()); + if (its_ipv4_option->get_layer_four_protocol() + == layer_four_protocol_e::UDP) { + its_unreliable_address = its_ipv4_address; + its_unreliable_port = its_ipv4_option->get_port(); + } else { + its_reliable_address = its_ipv4_address; + its_reliable_port = its_ipv4_option->get_port(); + } break; } case option_type_e::IP6_ENDPOINT: { @@ -518,24 +560,211 @@ void service_discovery_impl::process_serviceentry( boost::asio::ip::address_v6 its_ipv6_address( its_ipv6_option->get_address()); - boost::asio::ip::address its_address(its_ipv6_address); - its_option_port = its_ipv6_option->get_port(); - handle_service_availability(its_service, its_instance, - its_major, its_minor, its_ttl, its_address, - its_option_port, !its_ipv6_option->is_udp()); + if (its_ipv6_option->get_layer_four_protocol() + == layer_four_protocol_e::UDP) { + its_unreliable_address = its_ipv6_address; + its_unreliable_port = its_ipv6_option->get_port(); + } else { + its_reliable_address = its_ipv6_address; + its_reliable_port = its_ipv6_option->get_port(); + } break; } case option_type_e::IP4_MULTICAST: case option_type_e::IP6_MULTICAST: VSOMEIP_ERROR << "Invalid service option (Multicast)"; break; + case option_type_e::UNKNOWN: default: - VSOMEIP_WARNING << "Unsupported service option"; + VSOMEIP_ERROR << "Unsupported service option"; break; } } } + + if (0 < its_ttl) { + switch(its_type) { + case entry_type_e::FIND_SERVICE: + process_findservice_serviceentry(its_service, its_instance, + its_major, its_minor); + break; + case entry_type_e::OFFER_SERVICE: + process_offerservice_serviceentry(its_service, its_instance, + its_major, its_minor, its_ttl, + its_reliable_address, its_reliable_port, + its_unreliable_address, its_unreliable_port); + break; + case entry_type_e::UNKNOWN: + default: + VSOMEIP_ERROR << "Unsupported serviceentry type"; + } + + } else { + unsubscribe_all(its_service, its_instance); + host_->del_routing_info(its_service, its_instance, + (its_reliable_port != ILLEGAL_PORT), + (its_unreliable_port != ILLEGAL_PORT)); + } +} + +void service_discovery_impl::process_offerservice_serviceentry( + service_t _service, instance_t _instance, major_version_t _major, + minor_version_t _minor, ttl_t _ttl, + const boost::asio::ip::address &_reliable_address, + uint16_t _reliable_port, + const boost::asio::ip::address &_unreliable_address, + uint16_t _unreliable_port) { + std::shared_ptr < runtime > its_runtime = runtime_.lock(); + if (!its_runtime) + return; + + host_->add_routing_info(_service, _instance, + _major, _minor, _ttl, + _reliable_address, _reliable_port, + _unreliable_address, _unreliable_port); + + std::lock_guard its_lock(subscribed_mutex_); + auto found_service = subscribed_.find(_service); + if (found_service != subscribed_.end()) { + auto found_instance = found_service->second.find(_instance); + if (found_instance != found_service->second.end()) { + if (0 < found_instance->second.size()) { + std::shared_ptr its_message + = its_runtime->create_message(); + + for (auto its_eventgroup : found_instance->second) { + for (auto its_client : its_eventgroup.second) { + std::shared_ptr its_subscription(its_client.second); + if (its_subscription->is_acknowledged()) { + its_subscription->set_endpoint( + host_->find_or_create_remote_client(_service, + _instance, true, its_client.first), true); + its_subscription->set_endpoint( + host_->find_or_create_remote_client(_service, + _instance, false, its_client.first), false); + + // TODO: consume major & ttl + insert_subscription(its_message, + _service, _instance, + its_eventgroup.first, + its_subscription); + + its_subscription->set_acknowledged(false); + } + } + } + + if (0 < its_message->get_entries().size()) { + std::shared_ptr its_target; + session_t its_session(0); + if (_reliable_port != ILLEGAL_PORT) { + its_target = endpoint_definition::get( + _reliable_address, port_, reliable_); + its_session = get_session(_reliable_address); + } else if (_unreliable_port != ILLEGAL_PORT) { + its_target = endpoint_definition::get( + _unreliable_address, port_, reliable_); + its_session = get_session(_unreliable_address); + } + + if (its_target) { + its_message->set_session(its_session); + serializer_->serialize(its_message.get()); + if (host_->send_to(its_target, + serializer_->get_data(), + serializer_->get_size())) { + increment_session(its_target->get_address()); + } + serializer_->reset(); + } + } + } + } + } +} + +void service_discovery_impl::process_findservice_serviceentry( + service_t _service, instance_t _instance, major_version_t _major, + minor_version_t _minor) { + services_t offered_services = host_->get_offered_services(); + auto found_service = offered_services.find(_service); + if (found_service != offered_services.end()) { + if (_instance != ANY_INSTANCE) { + auto found_instance = found_service->second.find(_instance); + if (found_instance != found_service->second.end()) { + std::shared_ptr its_info = found_instance->second; + send_unicast_offer_service(its_info, _service, _instance, + _major, _minor); + } + } else { + // send back all available instances + for (const auto &found_instance : found_service->second) { + send_unicast_offer_service(found_instance.second, _service, + _instance, _major, _minor); + } + } + } +} + +void service_discovery_impl::send_unicast_offer_service( + const std::shared_ptr &_info, service_t _service, + instance_t _instance, major_version_t _major, minor_version_t _minor) { + if (_major == ANY_MAJOR || _major == _info->get_major()) { + if (_minor == 0xFFFFFFFF || _minor == _info->get_minor()) { + std::shared_ptr its_runtime = runtime_.lock(); + if (!its_runtime) { + return; + } + std::shared_ptr its_message = + its_runtime->create_message(); + insert_offer_service(its_message, _service, _instance, _info); + + serialize_and_send(its_message, get_current_remote_address()); + } + } +} + +void service_discovery_impl::insert_offer_service( + std::shared_ptr < message_impl > _message, service_t _service, + instance_t _instance, const std::shared_ptr &_info) { + std::shared_ptr < serviceentry_impl > its_entry = + _message->create_service_entry(); + if (its_entry) { + its_entry->set_type(entry_type_e::OFFER_SERVICE); + its_entry->set_service(_service); + its_entry->set_instance(_instance); + its_entry->set_major_version(_info->get_major()); + its_entry->set_minor_version(_info->get_minor()); + + ttl_t its_ttl = _info->get_ttl(); + if (its_ttl > 0) + its_ttl = ttl_; + its_entry->set_ttl(its_ttl); + + std::shared_ptr < endpoint > its_endpoint = + _info->get_endpoint(true); + if (its_endpoint) { + insert_option(_message, its_entry, unicast_, + its_endpoint->get_local_port(), true); + if (0 == _info->get_ttl()) { + host_->del_routing_info(_service, + _instance, true, false); + } + } + + its_endpoint = _info->get_endpoint(false); + if (its_endpoint) { + insert_option(_message, its_entry, unicast_, + its_endpoint->get_local_port(), false); + if (0 == _info->get_ttl()) { + host_->del_routing_info(_service, + _instance, false, true); + } + } + } else { + VSOMEIP_ERROR << "Failed to create service entry."; + } } void service_discovery_impl::process_eventgroupentry( @@ -548,27 +777,74 @@ void service_discovery_impl::process_eventgroupentry( major_version_t its_major = _entry->get_major_version(); ttl_t its_ttl = _entry->get_ttl(); + if (_entry->get_owning_message()->get_return_code() != return_code) { + VSOMEIP_ERROR << "Invalid return code in SD header"; + send_eventgroup_subscription_nack(its_service, its_instance, + its_eventgroup, its_major); + return; + } + + if(its_type == entry_type_e::SUBSCRIBE_EVENTGROUP) { + if (_entry->get_num_options(1) == 0 + && _entry->get_num_options(2) == 0) { + VSOMEIP_ERROR << "Invalid number of options in SubscribeEventGroup entry"; + send_eventgroup_subscription_nack(its_service, its_instance, + its_eventgroup, its_major); + return; + } + if(_entry->get_owning_message()->get_options_length() < 12) { + VSOMEIP_ERROR << "Invalid options length in SD message"; + send_eventgroup_subscription_nack(its_service, its_instance, + its_eventgroup, its_major); + return; + } + if (_options.size() + < (_entry->get_num_options(1) + _entry->get_num_options(2))) { + VSOMEIP_ERROR << "Fewer options in SD message than " + "referenced in EventGroup entry"; + send_eventgroup_subscription_nack(its_service, its_instance, + its_eventgroup, its_major); + return; + } + } + boost::asio::ip::address its_reliable_address; - uint16_t its_reliable_port = VSOMEIP_INVALID_PORT; + uint16_t its_reliable_port(ILLEGAL_PORT); boost::asio::ip::address its_unreliable_address; - uint16_t its_unreliable_port = VSOMEIP_INVALID_PORT; + uint16_t its_unreliable_port(ILLEGAL_PORT); for (auto i : { 1, 2 }) { - for (auto its_index : _entry->get_options(i)) { - std::vector < byte_t > its_option_address; - std::shared_ptr < option_impl > its_option = _options[its_index]; + for (auto its_index : _entry->get_options(uint8_t(i))) { + std::shared_ptr < option_impl > its_option; + try { + its_option = _options.at(its_index); + } catch(const std::out_of_range& e) { + VSOMEIP_ERROR << "Fewer options in SD message than " + "referenced in EventGroup entry for " + "option run number: " << i; + if (entry_type_e::SUBSCRIBE_EVENTGROUP == its_type) { + send_eventgroup_subscription_nack(its_service, its_instance, + its_eventgroup, its_major); + } + return; + } switch (its_option->get_type()) { case option_type_e::IP4_ENDPOINT: { - if (entry_type_e::SUBSCRIBE_EVENTGROUP == _entry->get_type()) { + if (entry_type_e::SUBSCRIBE_EVENTGROUP == its_type) { std::shared_ptr < ipv4_option_impl > its_ipv4_option = std::dynamic_pointer_cast < ipv4_option_impl > (its_option); boost::asio::ip::address_v4 its_ipv4_address( its_ipv4_option->get_address()); - + if (!check_layer_four_protocol(its_ipv4_option)) { + send_eventgroup_subscription_nack(its_service, + its_instance, its_eventgroup, its_major); + return; + } // TODO: add error handling (port already set) here - if (its_ipv4_option->is_udp()) { + if (its_ipv4_option->get_layer_four_protocol() + == layer_four_protocol_e::UDP) { its_unreliable_address = its_ipv4_address; its_unreliable_port = its_ipv4_option->get_port(); } else { @@ -582,20 +858,25 @@ void service_discovery_impl::process_eventgroupentry( break; } case option_type_e::IP6_ENDPOINT: { - if (entry_type_e::SUBSCRIBE_EVENTGROUP == _entry->get_type()) { + if (entry_type_e::SUBSCRIBE_EVENTGROUP == its_type) { std::shared_ptr < ipv6_option_impl > its_ipv6_option = std::dynamic_pointer_cast < ipv6_option_impl > (its_option); boost::asio::ip::address_v6 its_ipv6_address( its_ipv6_option->get_address()); - + if (!check_layer_four_protocol(its_ipv6_option)) { + send_eventgroup_subscription_nack(its_service, + its_instance, its_eventgroup, its_major); + return; + } // TODO: add error handling (port already set) here - if (its_ipv6_option->is_udp()) { + if (its_ipv6_option->get_layer_four_protocol() + == layer_four_protocol_e::UDP) { its_unreliable_address = its_ipv6_address; its_unreliable_port = its_ipv6_option->get_port(); } else { - its_unreliable_address = its_ipv6_address; + its_reliable_address = its_ipv6_address; its_reliable_port = its_ipv6_option->get_port(); } } else { @@ -605,8 +886,7 @@ void service_discovery_impl::process_eventgroupentry( break; } case option_type_e::IP4_MULTICAST: - if (entry_type_e::SUBSCRIBE_EVENTGROUP_ACK - == _entry->get_type()) { + if (entry_type_e::SUBSCRIBE_EVENTGROUP_ACK == its_type) { std::shared_ptr < ipv4_option_impl > its_ipv4_option = std::dynamic_pointer_cast < ipv4_option_impl > (its_option); @@ -622,8 +902,7 @@ void service_discovery_impl::process_eventgroupentry( } break; case option_type_e::IP6_MULTICAST: - if (entry_type_e::SUBSCRIBE_EVENTGROUP_ACK - == _entry->get_type()) { + if (entry_type_e::SUBSCRIBE_EVENTGROUP_ACK == its_type) { std::shared_ptr < ipv6_option_impl > its_ipv6_option = std::dynamic_pointer_cast < ipv6_option_impl > (its_option); @@ -638,8 +917,11 @@ void service_discovery_impl::process_eventgroupentry( << "Invalid eventgroup option (IPv6 Multicast)"; } break; + case option_type_e::UNKNOWN: default: VSOMEIP_WARNING << "Unsupported eventgroup option"; + send_eventgroup_subscription_nack(its_service, its_instance, + its_eventgroup, its_major); break; } } @@ -648,7 +930,7 @@ void service_discovery_impl::process_eventgroupentry( if (entry_type_e::SUBSCRIBE_EVENTGROUP == its_type) { handle_eventgroup_subscription(its_service, its_instance, its_eventgroup, its_major, its_ttl, - (its_reliable_port != VSOMEIP_INVALID_PORT ? + (its_reliable_port != ILLEGAL_PORT ? its_reliable_address : its_unreliable_address), its_reliable_port, its_unreliable_port); } else { @@ -658,78 +940,6 @@ void service_discovery_impl::process_eventgroupentry( } } -void service_discovery_impl::handle_service_availability(service_t _service, - instance_t _instance, major_version_t _major, minor_version_t _minor, - ttl_t _ttl, const boost::asio::ip::address &_address, uint16_t _port, - bool _reliable) { - - std::shared_ptr < runtime > its_runtime = runtime_.lock(); - if (!its_runtime) - return; - - if (0 < _ttl) { - host_->add_routing_info(_service, _instance, _major, _minor, _ttl, - _address, _port, _reliable); - - auto found_service = subscribed_.find(_service); - if (found_service != subscribed_.end()) { - auto found_instance = found_service->second.find(_instance); - if (found_instance != found_service->second.end()) { - if (0 < found_instance->second.size()) { - std::shared_ptr < message_impl > its_message = - its_runtime->create_message(); - for (auto its_eventgroup : found_instance->second) { - for (auto its_client : its_eventgroup.second) { - std::shared_ptr < subscription - > its_subscription(its_client.second); - if (!its_subscription->is_acknowleged()) { - its_subscription->set_endpoint( - host_->find_or_create_remote_client(_service, - _instance, true, its_client.first), true); - its_subscription->set_endpoint( - host_->find_or_create_remote_client(_service, - _instance, false, its_client.first), false); - - // TODO: consume major & ttl - insert_subscription(its_message, _service, - _instance, its_eventgroup.first, - its_subscription); - } - } - - } - - if (0 < its_message->get_entries().size()) { - its_message->set_session(get_session(_address)); - serializer_->serialize(its_message.get()); - if (host_->send_to( - std::make_shared < endpoint_definition - > (_address, port_, reliable_), - serializer_->get_data(), - serializer_->get_size())) { - increment_session(_address); - } - serializer_->reset(); - } - } - } - } - } else { - auto found_service = subscribed_.find(_service); - if (found_service != subscribed_.end()) { - auto found_instance = found_service->second.find(_instance); - if (found_instance != found_service->second.end()) { - for (auto &its_eventgroup : found_instance->second) { - for (auto its_client : its_eventgroup.second) { - its_client.second->set_acknowledged(false); - } - } - } - } - host_->del_routing_info(_service, _instance, _reliable); - } -} - void service_discovery_impl::handle_eventgroup_subscription(service_t _service, instance_t _instance, eventgroup_t _eventgroup, major_version_t _major, ttl_t _ttl, const boost::asio::ip::address &_address, @@ -746,51 +956,67 @@ void service_discovery_impl::handle_eventgroup_subscription(service_t _service, _service, _instance, _eventgroup); bool is_nack(false); - std::shared_ptr < endpoint_definition > its_subscriber; - std::shared_ptr < endpoint_definition > its_target; - - // Could not find eventgroup --> send Nack - if (!its_info || _major > its_info->get_major() - || _ttl > its_info->get_ttl()) { + std::shared_ptr < endpoint_definition > its_reliable_subscriber, + its_unreliable_subscriber; + std::shared_ptr < endpoint_definition > its_reliable_target, + its_unreliable_target; + + // Could not find eventgroup or wrong version + if (!its_info || _major != its_info->get_major()) { + // Create a temporary info object with TTL=0 --> send NACK its_info = std::make_shared < eventgroupinfo > (_major, 0); is_nack = true; + insert_subscription_nack(its_message, _service, _instance, _eventgroup, + its_info); + serialize_and_send(its_message, _address); + //TODO add check if required tcp connection is open + return; } else { boost::asio::ip::address its_target_address; uint16_t its_target_port; - if (VSOMEIP_INVALID_PORT != _unreliable_port) { - its_subscriber = std::make_shared < endpoint_definition - > (_address, _unreliable_port, false); + if (ILLEGAL_PORT != _unreliable_port) { + its_unreliable_subscriber = endpoint_definition::get( + _address, _unreliable_port, false); if (its_info->get_multicast(its_target_address, its_target_port)) { - its_target = std::make_shared < endpoint_definition - > (its_target_address, its_target_port, false); + its_unreliable_target = endpoint_definition::get( + its_target_address, its_target_port, false); } else { - its_target = its_subscriber; + its_unreliable_target = its_unreliable_subscriber; } - } else { - its_subscriber = std::make_shared < endpoint_definition - > (_address, _reliable_port, true); - its_target = its_subscriber; } + if (ILLEGAL_PORT != _reliable_port) { + its_reliable_subscriber = endpoint_definition::get( + _address, _reliable_port, true); + its_reliable_target = its_reliable_subscriber; + } + } + + if (_ttl == 0) { // --> unsubscribe + if (its_unreliable_target) { + host_->on_unsubscribe(_service, _instance, _eventgroup, its_unreliable_target); + } + if (its_reliable_target) { + host_->on_unsubscribe(_service, _instance, _eventgroup, its_reliable_target); + } + return; } insert_subscription_ack(its_message, _service, _instance, _eventgroup, - its_info); + its_info, _ttl); - its_message->set_session(get_session(_address)); - serializer_->serialize(its_message.get()); - if (host_->send_to( - std::make_shared < endpoint_definition - > (_address, port_, reliable_), serializer_->get_data(), - serializer_->get_size())) { - increment_session(_address); - } - serializer_->reset(); + serialize_and_send(its_message, _address); // Finally register the new subscriber and send him all the fields(!) if (!is_nack) { - host_->on_subscribe(_service, _instance, _eventgroup, - its_subscriber, its_target); + if (its_unreliable_target && its_unreliable_subscriber) { + host_->on_subscribe(_service, _instance, _eventgroup, + its_unreliable_subscriber, its_unreliable_target); + } + if (its_reliable_target && its_reliable_subscriber) { + host_->on_subscribe(_service, _instance, _eventgroup, + its_reliable_subscriber, its_reliable_target); + } } } } @@ -799,6 +1025,9 @@ void service_discovery_impl::handle_eventgroup_subscription_ack( service_t _service, instance_t _instance, eventgroup_t _eventgroup, major_version_t _major, ttl_t _ttl, const boost::asio::ip::address &_address, uint16_t _port) { + (void)_major; + (void)_ttl; + auto found_service = subscribed_.find(_service); if (found_service != subscribed_.end()) { auto found_instance = found_service->second.find(_instance); @@ -818,5 +1047,96 @@ void service_discovery_impl::handle_eventgroup_subscription_ack( } } +void service_discovery_impl::serialize_and_send( + std::shared_ptr _message, + const boost::asio::ip::address &_address) { + _message->set_session(get_session(_address)); + if(!serializer_->serialize(_message.get())) { + VSOMEIP_ERROR << "service_discovery_impl::serialize_and_send: serialization error."; + return; + } + if (host_->send_to(endpoint_definition::get(_address, port_, reliable_), + serializer_->get_data(), serializer_->get_size())) { + increment_session(_address); + } + serializer_->reset(); +} + +void service_discovery_impl::start_ttl_timer() { + ttl_timer_.expires_from_now(std::chrono::seconds(smallest_ttl_)); + ttl_timer_.async_wait( + std::bind(&service_discovery_impl::check_ttl, shared_from_this(), + std::placeholders::_1)); +} + +ttl_t service_discovery_impl::stop_ttl_timer() { + ttl_t remaining = ttl_t(std::chrono::duration_cast< + std::chrono::seconds + >(ttl_timer_.expires_from_now()).count()); + ttl_timer_.cancel(); + return (smallest_ttl_ - remaining); +} + +void service_discovery_impl::check_ttl(const boost::system::error_code &_error) { + if (!_error) { + smallest_ttl_ = host_->update_routing_info(smallest_ttl_); + start_ttl_timer(); + } +} + +boost::asio::ip::address service_discovery_impl::get_current_remote_address() const { + if (reliable_) { + return std::static_pointer_cast(endpoint_)->get_remote().address(); + } else { + return std::static_pointer_cast(endpoint_)->get_remote().address(); + } +} + +bool service_discovery_impl::check_static_header_fields( + const std::shared_ptr &_message) const { + if(_message->get_protocol_version() != protocol_version) { + VSOMEIP_ERROR << "Invalid protocol version in SD header"; + return false; + } + if(_message->get_interface_version() != interface_version) { + VSOMEIP_ERROR << "Invalid interface version in SD header"; + return false; + } + if(_message->get_message_type() != message_type) { + VSOMEIP_ERROR << "Invalid message type in SD header"; + return false; + } + return true; +} + +void service_discovery_impl::send_eventgroup_subscription_nack( + service_t _service, instance_t _instance, eventgroup_t _eventgroup, major_version_t _major) { + std::shared_ptr its_runtime = runtime_.lock(); + if (!its_runtime) { + return; + } + std::shared_ptr its_message = its_runtime->create_message(); + if (its_message) { + std::shared_ptr its_info = host_->find_eventgroup( + _service, _instance, _eventgroup); + if(!its_info) { + // Create a temporary info object with TTL=0 + its_info = std::make_shared < eventgroupinfo > (_major, 0); + } + insert_subscription_nack(its_message, _service, _instance, _eventgroup, + its_info); + serialize_and_send(its_message, get_current_remote_address()); + } +} + +bool service_discovery_impl::check_layer_four_protocol( + const std::shared_ptr _ip_option) const { + if (_ip_option->get_layer_four_protocol() == layer_four_protocol_e::UNKNOWN) { + VSOMEIP_ERROR << "Invalid layer 4 protocol in IP endpoint option"; + return false; + } + return true; +} + } // namespace sd } // namespace vsomeip diff --git a/implementation/service_discovery/src/subscription.cpp b/implementation/service_discovery/src/subscription.cpp index 4b823be..76b9c9f 100644 --- a/implementation/service_discovery/src/subscription.cpp +++ b/implementation/service_discovery/src/subscription.cpp @@ -10,10 +10,10 @@ namespace sd { subscription::subscription(major_version_t _major, ttl_t _ttl, std::shared_ptr _reliable, - std::shared_ptr _unreliable, - client_t _target) - : major_(_major), ttl_(_ttl), reliable_(_reliable), unreliable_( - _unreliable), is_acknowledged_(false) { + std::shared_ptr _unreliable) + : major_(_major), ttl_(_ttl), + reliable_(_reliable), unreliable_(_unreliable), + is_acknowledged_(true) { } subscription::~subscription() { @@ -43,7 +43,7 @@ void subscription::set_endpoint(std::shared_ptr _endpoint, unreliable_ = _endpoint; } -bool subscription::is_acknowleged() const { +bool subscription::is_acknowledged() const { return is_acknowledged_; } diff --git a/implementation/utility/include/byteorder.hpp b/implementation/utility/include/byteorder.hpp index 55088f1..baea175 100644 --- a/implementation/utility/include/byteorder.hpp +++ b/implementation/utility/include/byteorder.hpp @@ -17,37 +17,37 @@ #if __BYTE_ORDER == __LITTLE_ENDIAN -#define VSOMEIP_BYTES_TO_WORD(x0, x1) ((x0) << 8 | (x1)) -#define VSOMEIP_BYTES_TO_LONG(x0, x1, x2, x3) ((x0) << 24 | (x1) << 16 | (x2) << 8 | (x3)) +#define VSOMEIP_BYTES_TO_WORD(x0, x1) (uint16_t((x0) << 8 | (x1))) +#define VSOMEIP_BYTES_TO_LONG(x0, x1, x2, x3) (uint32_t((x0) << 24 | (x1) << 16 | (x2) << 8 | (x3))) -#define VSOMEIP_WORDS_TO_LONG(x0, x1) ((x0) << 16 | (x1)) +#define VSOMEIP_WORDS_TO_LONG(x0, x1) (uint32_t((x0) << 16 | (x1))) -#define VSOMEIP_WORD_BYTE0(x) ((x) & 0xFF) -#define VSOMEIP_WORD_BYTE1(x) ((x) >> 8) +#define VSOMEIP_WORD_BYTE0(x) (uint8_t((x) & 0xFF)) +#define VSOMEIP_WORD_BYTE1(x) (uint8_t((x) >> 8)) -#define VSOMEIP_LONG_BYTE0(x) ((x) & 0xFF) -#define VSOMEIP_LONG_BYTE1(x) (((x) >> 8) & 0xFF) -#define VSOMEIP_LONG_BYTE2(x) (((x) >> 16) & 0xFF) -#define VSOMEIP_LONG_BYTE3(x) (((x) >> 24) & 0xFF) +#define VSOMEIP_LONG_BYTE0(x) (uint8_t((x) & 0xFF)) +#define VSOMEIP_LONG_BYTE1(x) (uint8_t(((x) >> 8) & 0xFF)) +#define VSOMEIP_LONG_BYTE2(x) (uint8_t(((x) >> 16) & 0xFF)) +#define VSOMEIP_LONG_BYTE3(x) (uint8_t(((x) >> 24) & 0xFF)) -#define VSOMEIP_LONG_WORD0(x) ((x) & 0xFFFF) -#define VSOMEIP_LONG_WORD1(x) (((x) >> 16) & 0xFFFF) +#define VSOMEIP_LONG_WORD0(x) (uint16_t((x) & 0xFFFF)) +#define VSOMEIP_LONG_WORD1(x) (uint16_t(((x) >> 16) & 0xFFFF)) #elif __BYTE_ORDER == __BIG_ENDIAN -#define VSOMEIP_BYTES_TO_WORD(x0, x1) ((x1) << 8 | (x0)) -#define VSOMEIP_BYTES_TO_LONG(x0, x1, x2, x3) ((x3) << 24 | (x2) << 16 | (x1) << 8 | (x0)) +#define VSOMEIP_BYTES_TO_WORD(x0, x1) (uint16_t((x1) << 8 | (x0))) +#define VSOMEIP_BYTES_TO_LONG(x0, x1, x2, x3) (uint32_t((x3) << 24 | (x2) << 16 | (x1) << 8 | (x0))) -#define VSOMEIP_WORD_BYTE0(x) ((x) >> 8) -#define VSOMEIP_WORD_BYTE1(x) ((x) & 0xFF) +#define VSOMEIP_WORD_BYTE0(x) (uint8_t((x) >> 8)) +#define VSOMEIP_WORD_BYTE1(x) (uint8_t((x) & 0xFF)) -#define VSOMEIP_LONG_BYTE0(x) (((x) >> 24) & 0xFF) -#define VSOMEIP_LONG_BYTE1(x) (((x) >> 16) & 0xFF) -#define VSOMEIP_LONG_BYTE2(x) (((x) >> 8) & 0xFF) -#define VSOMEIP_LONG_BYTE3(x) ((x) & 0xFF) +#define VSOMEIP_LONG_BYTE0(x) (uint8_t(((x) >> 24) & 0xFF)) +#define VSOMEIP_LONG_BYTE1(x) (uint8_t(((x) >> 16) & 0xFF)) +#define VSOMEIP_LONG_BYTE2(x) (uint8_t(((x) >> 8) & 0xFF)) +#define VSOMEIP_LONG_BYTE3(x) (uint8_t((x) & 0xFF)) -#define VSOMEIP_LONG_WORD0(x) ((((x) >> 16) & 0xFFFF) -#define VSOMEIP_LONG_WORD1(x) (((x) & 0xFFFF) +#define VSOMEIP_LONG_WORD0(x) (uint16_t((((x) >> 16) & 0xFFFF)) +#define VSOMEIP_LONG_WORD1(x) (uint16_t(((x) & 0xFFFF)) #else diff --git a/implementation/utility/include/utility.hpp b/implementation/utility/include/utility.hpp index 000ca9b..a366075 100644 --- a/implementation/utility/include/utility.hpp +++ b/implementation/utility/include/utility.hpp @@ -61,7 +61,7 @@ public: static uint32_t get_message_size(const byte_t *_data, uint32_t _size); static inline uint32_t get_message_size(std::vector &_data) { if (_data.size() > 0) { - return (get_message_size(&_data[0], _data.size())); + return (get_message_size(&_data[0], uint32_t(_data.size()))); } return 0; } @@ -69,6 +69,17 @@ 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 struct configuration_data_t *the_configuration_data__; + static bool auto_configuration_init(); + static void auto_configuration_exit(); + + static bool is_routing_manager_host__; + static bool is_routing_manager_host(); + + static client_t get_client_id(); }; } // namespace vsomeip diff --git a/implementation/utility/src/utility.cpp b/implementation/utility/src/utility.cpp index 28eef27..e2cbde4 100644 --- a/implementation/utility/src/utility.cpp +++ b/implementation/utility/src/utility.cpp @@ -8,15 +8,21 @@ #include #else #include +#include #endif #include +#ifndef WIN32 +#include +#endif + #include -#include #include "../include/byteorder.hpp" #include "../include/utility.hpp" +#include "../../configuration/include/internal.hpp" +#include "../../logging/include/logger.hpp" namespace vsomeip { @@ -83,4 +89,84 @@ bool utility::exists(const std::string &_path) { return (stat(_path.c_str(), &its_stat) == 0); } +bool utility::is_file(const std::string &_path) { + struct stat its_stat; + if (stat(_path.c_str(), &its_stat) == 0) { + if (its_stat.st_mode & S_IFREG) + return true; + } + return false; +} + +bool utility::is_folder(const std::string &_path) { + struct stat its_stat; + if (stat(_path.c_str(), &its_stat) == 0) { + if (its_stat.st_mode & S_IFDIR) + return true; + } + return false; +} + +configuration_data_t *utility::the_configuration_data__(nullptr); +bool utility::is_routing_manager_host__(false); + +bool utility::auto_configuration_init() { +#ifndef WIN32 + int its_descriptor = shm_open(VSOMEIP_SHM_NAME, O_RDWR|O_CREAT|O_EXCL, 0660); + if (its_descriptor > -1) { + if (0 == ftruncate(its_descriptor, sizeof(configuration_data_t))) { + void *its_segment = mmap(0, sizeof(configuration_data_t), + PROT_READ | PROT_WRITE, MAP_SHARED, + its_descriptor, 0); + the_configuration_data__ + = reinterpret_cast(its_segment); + if (the_configuration_data__ != nullptr) { + std::lock_guard its_lock(the_configuration_data__->mutex_); + the_configuration_data__->ref_ = 0; + the_configuration_data__->next_client_id_ = (VSOMEIP_DIAGNOSIS_ADDRESS << 8); + is_routing_manager_host__ = true; + } + } else { + // TODO: an error message + } + } else { + its_descriptor = shm_open(VSOMEIP_SHM_NAME, O_RDWR, 0660); + if (its_descriptor > -1) { + void *its_segment = mmap(0, sizeof(configuration_data_t), + PROT_READ | PROT_WRITE, MAP_SHARED, + its_descriptor, 0); + the_configuration_data__ + = reinterpret_cast(its_segment); + } else { + // TODO: an error message + } + } +#endif + return (the_configuration_data__ != nullptr); +} + +void utility::auto_configuration_exit() { +#ifndef WIN32 + if (the_configuration_data__) { + munmap(the_configuration_data__, sizeof(configuration_data_t)); + if (is_routing_manager_host__) { + shm_unlink(VSOMEIP_SHM_NAME); + } + } +#endif +} + +client_t utility::get_client_id() { + if (the_configuration_data__ != nullptr) { + std::lock_guard its_lock(the_configuration_data__->mutex_); + the_configuration_data__->next_client_id_++; + return the_configuration_data__->next_client_id_; + } + return VSOMEIP_DIAGNOSIS_ADDRESS; +} + +bool utility::is_routing_manager_host() { + return is_routing_manager_host__; +} + } // namespace vsomeip diff --git a/interface/vsomeip/application.hpp b/interface/vsomeip/application.hpp index 98ee93d..f08a91d 100644 --- a/interface/vsomeip/application.hpp +++ b/interface/vsomeip/application.hpp @@ -7,6 +7,7 @@ #define VSOMEIP_APPLICATION_HPP #include +#include #include #include @@ -15,18 +16,20 @@ namespace vsomeip { +class configuration; class event; class payload; class application { public: - virtual ~application() { - } + virtual ~application() {} // get name virtual const std::string & get_name() const = 0; virtual client_t get_client() const = 0; + virtual void set_configuration(const std::shared_ptr _configuration) = 0; + // Lifecycle virtual bool init() = 0; virtual void start() = 0; @@ -35,56 +38,71 @@ public: // Provide services virtual void offer_service(service_t _service, instance_t _instance, major_version_t _major = DEFAULT_MAJOR, minor_version_t _minor = - DEFAULT_MINOR, ttl_t _ttl = DEFAULT_TTL) = 0; + DEFAULT_MINOR) = 0; virtual void stop_offer_service(service_t _service, instance_t _instance) = 0; + virtual void offer_event(service_t _service, + instance_t _instance, event_t _event, + std::set _eventgroups, + bool _is_field) = 0; + virtual void stop_offer_event(service_t _service, + instance_t _instance, event_t _event) = 0; + // Consume services virtual void request_service(service_t _service, instance_t _instance, - bool _has_selective = false, major_version_t _major = ANY_MAJOR, - minor_version_t _minor = ANY_MINOR, ttl_t _ttl = ANY_TTL) = 0; - + major_version_t _major = ANY_MAJOR, + minor_version_t _minor = ANY_MINOR, + bool _use_exclusive_proxy = false) = 0; virtual void release_service(service_t _service, instance_t _instance) = 0; + virtual void request_event(service_t _service, instance_t _instance, + event_t _event, std::set _eventgroups, + bool _is_field) = 0; + virtual void release_event(service_t _service, instance_t _instance, + event_t _event) = 0; + virtual void subscribe(service_t _service, instance_t _instance, - eventgroup_t _eventgroup, major_version_t _major = ANY_MAJOR, - ttl_t _ttl = ANY_TTL) = 0; + eventgroup_t _eventgroup, major_version_t _major = DEFAULT_MAJOR) = 0; virtual void unsubscribe(service_t _service, instance_t _instance, eventgroup_t _eventgroup) = 0; - virtual bool is_available(service_t _service, instance_t _instance) = 0; + virtual bool is_available(service_t _service, instance_t _instance) const = 0; // Send a message virtual void send(std::shared_ptr _message, bool _flush = true) = 0; - // Notify subscribers in case an event payload changes + // Set a field or fire an event virtual void notify(service_t _service, instance_t _instance, event_t _event, std::shared_ptr _payload) const = 0; virtual void notify_one(service_t _service, instance_t _instance, - event_t _event, std::shared_ptr _payload, client_t _client) const = 0; + event_t _event, std::shared_ptr _payload, + client_t _client) const = 0; - // Receive events (Non-SOME/IP) - virtual void register_event_handler(event_handler_t _handler) = 0; - virtual void unregister_event_handler() = 0; + // [Un]Register handler for state change events + virtual void register_state_handler(state_handler_t _handler) = 0; + virtual void unregister_state_handler() = 0; - // Receive messages + // [Un]Register message handler for a method/an event/field virtual void register_message_handler(service_t _service, instance_t _instance, method_t _method, message_handler_t _handler) = 0; virtual void unregister_message_handler(service_t _service, instance_t _instance, method_t _method) = 0; - // Receive availability + // [Un]Register handler for availability reporting virtual void register_availability_handler(service_t _service, instance_t _instance, availability_handler_t _handler) = 0; virtual void unregister_availability_handler(service_t _service, instance_t _instance) = 0; + // [Un]Register handler for subscriptions virtual void register_subscription_handler(service_t _service, - instance_t _instance, eventgroup_t _eventgroup, subscription_handler_t _handler) = 0; + instance_t _instance, eventgroup_t _eventgroup, + subscription_handler_t _handler) = 0; virtual void unregister_subscription_handler(service_t _service, instance_t _instance, eventgroup_t _eventgroup) = 0; }; diff --git a/interface/vsomeip/configuration.hpp b/interface/vsomeip/configuration.hpp deleted file mode 100644 index 7eb81fc..0000000 --- a/interface/vsomeip/configuration.hpp +++ /dev/null @@ -1,93 +0,0 @@ -// Copyright (C) 2014-2015 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_CONFIGURATION_HPP -#define VSOMEIP_CONFIGURATION_HPP - -#include -#include -#include -#include - -#include -#include - -#include -#include -#include - -namespace vsomeip { - -class event; - -class VSOMEIP_EXPORT configuration { -public: - static configuration * get(const std::string &_path = - VSOMEIP_DEFAULT_CONFIGURATION_FILE_PATH); - virtual ~configuration() { - } - - virtual bool load(const std::string &_path) = 0; - - virtual const boost::asio::ip::address & get_unicast() const = 0; - virtual bool is_v4() const = 0; - virtual bool is_v6() const = 0; - - virtual bool has_console_log() const = 0; - virtual bool has_file_log() const = 0; - virtual bool has_dlt_log() const = 0; - virtual const std::string & get_logfile() const = 0; - virtual boost::log::trivial::severity_level get_loglevel() const = 0; - - virtual const std::string & get_routing_host() const = 0; - - virtual bool is_service_discovery_enabled() const = 0; - virtual const std::string & get_service_discovery_multicast() const = 0; - virtual uint16_t get_service_discovery_port() const = 0; - virtual const std::string & get_service_discovery_protocol() const = 0; - - virtual std::string get_group(service_t _service, - instance_t _instance) const = 0; - virtual std::set get_servicegroups() const = 0; - - virtual bool is_local_servicegroup(const std::string &_name) const = 0; - virtual int32_t get_min_initial_delay(const std::string &_name) const = 0; - virtual int32_t get_max_initial_delay(const std::string &_name) const = 0; - virtual int32_t get_repetition_base_delay( - const std::string &_name) const = 0; - virtual uint8_t get_repetition_max(const std::string &_name) const = 0; - virtual int32_t get_cyclic_offer_delay(const std::string &_name) const = 0; - virtual int32_t get_cyclic_request_delay( - const std::string &_name) const = 0; - - virtual std::string get_unicast(service_t _service, - instance_t _instance) const = 0; - virtual std::string get_multicast_address(service_t _service, - instance_t _instance) const = 0; - virtual uint16_t get_multicast_port(service_t _service, - instance_t _instance) const = 0; - virtual uint16_t get_multicast_group(service_t _service, - instance_t _instance) const = 0; - virtual uint16_t get_reliable_port(service_t _service, - instance_t _instance) const = 0; - virtual bool has_enabled_magic_cookies(std::string _address, - uint16_t _port) const = 0; - virtual uint16_t get_unreliable_port(service_t _service, - instance_t _instance) const = 0; - - virtual std::set > get_remote_services() const = 0; - - virtual std::map > > > get_eventgroups() const = 0; - virtual std::map > > get_events() const = 0; - virtual void set_event(std::shared_ptr &_event) const = 0; - - virtual client_t get_id(const std::string &_name) const = 0; - virtual std::size_t get_num_dispatchers(const std::string &_name) const = 0; -}; - -} // namespace vsomeip - -#endif // VSOMEIP_CONFIGURATION_HPP diff --git a/interface/vsomeip/constants.hpp b/interface/vsomeip/constants.hpp index fb947b8..8062b12 100644 --- a/interface/vsomeip/constants.hpp +++ b/interface/vsomeip/constants.hpp @@ -13,9 +13,9 @@ namespace vsomeip { -const major_version_t DEFAULT_MAJOR = 0x01; +const major_version_t DEFAULT_MAJOR = 0x00; const minor_version_t DEFAULT_MINOR = 0x000000; -const ttl_t DEFAULT_TTL = 0xFFFFFF; // basically means "forever" +const ttl_t DEFAULT_TTL = 0xFFFFFF; // "until next reboot" const std::string DEFAULT_MULTICAST = "224.0.0.0"; const uint16_t DEFAULT_PORT = 30500; @@ -26,7 +26,8 @@ const instance_t ANY_INSTANCE = 0xFFFF; const method_t ANY_METHOD = 0xFFFF; const major_version_t ANY_MAJOR = 0xFF; const minor_version_t ANY_MINOR = 0xFFFFFF; -const ttl_t ANY_TTL = 1; + +const eventgroup_t DEFAULT_EVENTGROUP = 0x0001; const byte_t MAGIC_COOKIE_CLIENT_MESSAGE = 0x00; const byte_t MAGIC_COOKIE_SERVICE_MESSAGE = 0x80; diff --git a/interface/vsomeip/defines.hpp b/interface/vsomeip/defines.hpp index 598bb25..d384d50 100644 --- a/interface/vsomeip/defines.hpp +++ b/interface/vsomeip/defines.hpp @@ -6,14 +6,6 @@ #ifndef VSOMEIP_DEFINES_HPP #define VSOMEIP_DEFINES_HPP -#define VSOMEIP_ENV_APPLICATION_NAME "VSOMEIP_APPLICATION_NAME" -#define VSOMEIP_ENV_CONFIGURATION_FILE_PATH "VSOMEIP_CONFIGURATION_FILE" - -#define VSOMEIP_DEFAULT_CONFIGURATION_FILE_PATH "/etc/vsomeip.json" -#define VSOMEIP_LOCAL_CONFIGURATION_FILE_PATH "./vsomeip.json" - -#define VSOMEIP_BASE_PATH "/tmp/vsomeip-" - #define VSOMEIP_PROTOCOL_VERSION 0x1 #define VSOMEIP_MAX_LOCAL_MESSAGE_SIZE 32768 diff --git a/interface/vsomeip/deserializable.hpp b/interface/vsomeip/deserializable.hpp deleted file mode 100644 index fb11dfd..0000000 --- a/interface/vsomeip/deserializable.hpp +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (C) 2014-2015 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_DESERIALIZABLE_HPP -#define VSOMEIP_DESERIALIZABLE_HPP - -#include - -namespace vsomeip { - -class deserializer; - -class deserializable { -public: - VSOMEIP_EXPORT virtual ~deserializable() { - } - VSOMEIP_EXPORT virtual bool deserialize(deserializer *_from) = 0; -}; - -} // namespace vsomeip - -#endif // VSOMEIP_SERIALIZABLE_HPP diff --git a/interface/vsomeip/enumeration_types.hpp b/interface/vsomeip/enumeration_types.hpp index 51c3df1..8be8413 100644 --- a/interface/vsomeip/enumeration_types.hpp +++ b/interface/vsomeip/enumeration_types.hpp @@ -10,9 +10,9 @@ namespace vsomeip { -enum class event_type_e : uint8_t { - ET_REGISTERED = 0x0, - ET_DEREGISTERED = 0x1 +enum class state_type_e : uint8_t { + ST_REGISTERED = 0x0, + ST_DEREGISTERED = 0x1 }; // SIP_RPC_684 diff --git a/interface/vsomeip/handler.hpp b/interface/vsomeip/handler.hpp index 29df46a..a703569 100644 --- a/interface/vsomeip/handler.hpp +++ b/interface/vsomeip/handler.hpp @@ -15,7 +15,7 @@ namespace vsomeip { class message; -typedef std::function< void (event_type_e) > event_handler_t; +typedef std::function< void (state_type_e) > state_handler_t; typedef std::function< void (const std::shared_ptr< message > &) > message_handler_t; typedef std::function< void (service_t, instance_t, bool) > availability_handler_t; typedef std::function< bool (client_t, bool) > subscription_handler_t; diff --git a/interface/vsomeip/internal/deserializable.hpp b/interface/vsomeip/internal/deserializable.hpp new file mode 100644 index 0000000..fb11dfd --- /dev/null +++ b/interface/vsomeip/internal/deserializable.hpp @@ -0,0 +1,24 @@ +// Copyright (C) 2014-2015 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_DESERIALIZABLE_HPP +#define VSOMEIP_DESERIALIZABLE_HPP + +#include + +namespace vsomeip { + +class deserializer; + +class deserializable { +public: + VSOMEIP_EXPORT virtual ~deserializable() { + } + VSOMEIP_EXPORT virtual bool deserialize(deserializer *_from) = 0; +}; + +} // namespace vsomeip + +#endif // VSOMEIP_SERIALIZABLE_HPP diff --git a/interface/vsomeip/internal/serializable.hpp b/interface/vsomeip/internal/serializable.hpp new file mode 100644 index 0000000..4c22bf7 --- /dev/null +++ b/interface/vsomeip/internal/serializable.hpp @@ -0,0 +1,30 @@ +// Copyright (C) 2014-2015 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_SERIALIZABLE_HPP +#define VSOMEIP_SERIALIZABLE_HPP + +#include + +namespace vsomeip { + +class serializer; + +/** + * Abstract base class for element that can be serialized. + */ +class serializable { +public: + VSOMEIP_EXPORT virtual ~serializable() {} + + /** + * \brief serialize the content of the object + */ + VSOMEIP_EXPORT virtual bool serialize(serializer *_to) const = 0; +}; + +} // namespace vsomeip + +#endif // VSOMEIP_SERIALIZABLE_HPP diff --git a/interface/vsomeip/logger.hpp b/interface/vsomeip/logger.hpp deleted file mode 100644 index 555f15e..0000000 --- a/interface/vsomeip/logger.hpp +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright (C) 2014-2015 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_LOGGER_HPP -#define VSOMEIP_LOGGER_HPP - -#include - -#ifdef WIN32 -#include -#endif - -#include - -#include -#include - -namespace vsomeip { - -class VSOMEIP_EXPORT logger { -public: - static std::shared_ptr get(); - - virtual ~logger() { - } - - virtual boost::log::sources::severity_logger< - boost::log::trivial::severity_level> & get_internal() = 0; -}; - -#define VSOMEIP_FATAL BOOST_LOG_SEV(vsomeip::logger::get()->get_internal(), \ - boost::log::trivial::severity_level::fatal) -#define VSOMEIP_ERROR BOOST_LOG_SEV(vsomeip::logger::get()->get_internal(), \ - boost::log::trivial::severity_level::error) -#define VSOMEIP_WARNING BOOST_LOG_SEV(vsomeip::logger::get()->get_internal(), \ - boost::log::trivial::severity_level::warning) -#define VSOMEIP_INFO BOOST_LOG_SEV(vsomeip::logger::get()->get_internal(), \ - boost::log::trivial::severity_level::info) -#define VSOMEIP_DEBUG BOOST_LOG_SEV(vsomeip::logger::get()->get_internal(), \ - boost::log::trivial::severity_level::debug) -#define VSOMEIP_TRACE BOOST_LOG_SEV(vsomeip::logger::get()->get_internal(), \ - boost::log::trivial::severity_level::trace) - -} // namespace vsomeip - -#endif // VSOMEIP_LOGGER_HPP diff --git a/interface/vsomeip/message_base.hpp b/interface/vsomeip/message_base.hpp index 9b464c7..225ec19 100644 --- a/interface/vsomeip/message_base.hpp +++ b/interface/vsomeip/message_base.hpp @@ -9,8 +9,9 @@ #include #include #include -#include -#include + +#include +#include namespace vsomeip { diff --git a/interface/vsomeip/payload.hpp b/interface/vsomeip/payload.hpp index 9c85906..693d5ba 100644 --- a/interface/vsomeip/payload.hpp +++ b/interface/vsomeip/payload.hpp @@ -9,9 +9,10 @@ #include #include -#include #include -#include + +#include +#include namespace vsomeip { diff --git a/interface/vsomeip/runtime.hpp b/interface/vsomeip/runtime.hpp index cb3f6f6..fb9c2ab 100644 --- a/interface/vsomeip/runtime.hpp +++ b/interface/vsomeip/runtime.hpp @@ -11,7 +11,6 @@ #include #include - #include namespace vsomeip { @@ -28,7 +27,7 @@ public: } virtual std::shared_ptr create_application( - const std::string &_name = "") const = 0; + const std::string &_name = "") = 0; virtual std::shared_ptr create_message( bool _reliable = false) const = 0; @@ -44,6 +43,9 @@ public: const byte_t *_data, uint32_t _size) const = 0; virtual std::shared_ptr create_payload( const std::vector &_data) const = 0; + + virtual std::shared_ptr get_application( + const std::string &_name) const = 0; }; } // namespace vsomeip diff --git a/interface/vsomeip/serializable.hpp b/interface/vsomeip/serializable.hpp deleted file mode 100644 index 4cab10f..0000000 --- a/interface/vsomeip/serializable.hpp +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright (C) 2014-2015 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_SERIALIZABLE_HPP -#define VSOMEIP_SERIALIZABLE_HPP - -#include - -namespace vsomeip { - -class serializer; - -class serializable { -public: - VSOMEIP_EXPORT virtual ~serializable() { - } - - VSOMEIP_EXPORT virtual bool serialize(serializer *_to) const = 0; -}; - -} // namespace vsomeip - -#endif // VSOMEIP_SERIALIZABLE_HPP diff --git a/interface/vsomeip/vsomeip.hpp b/interface/vsomeip/vsomeip.hpp index 9d7cb56..3ee5819 100644 --- a/interface/vsomeip/vsomeip.hpp +++ b/interface/vsomeip/vsomeip.hpp @@ -6,10 +6,13 @@ #ifndef VSOMEIP_VSOMEIP_HPP #define VSOMEIP_VSOMEIP_HPP +/** + * \brief The central vsomeip header. Include this to use vsomeip. + */ + #include #include #include -#include #include #include #include diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index c944610..43254a5 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -14,523 +14,955 @@ include_directories( set(TEST_LINK_LIBRARIES gtest) # Function to copy files into the build directory (or anywhere else) +# On unixoid systems this function will create symlinks instead # SOURCE_PATH: Path to the file which should be copied # DESTINATION_PATH: destination file # TARGET_TO_DEPEND: The copying of the file will be added as # a dependency to this target function(copy_to_builddir SOURCE_PATH DESTINATION_PATH TARGET_TO_DEPEND) - ADD_CUSTOM_COMMAND( - OUTPUT "${DESTINATION_PATH}" - COMMAND ${CMAKE_COMMAND} -E copy "${SOURCE_PATH}" "${DESTINATION_PATH}" - DEPENDS "${SOURCE_PATH}" - COMMENT "Copying \"${SOURCE_PATH}\" into build directory" - ) + if(${CMAKE_SYSTEM_NAME} MATCHES "Windows" OR NOT ${TEST_SYMLINK_CONFIG_FILES}) + ADD_CUSTOM_COMMAND( + OUTPUT "${DESTINATION_PATH}" + COMMAND ${CMAKE_COMMAND} -E copy "${SOURCE_PATH}" "${DESTINATION_PATH}" + DEPENDS "${SOURCE_PATH}" + COMMENT "Copying \"${SOURCE_PATH}\" into build directory" + ) + else() + if(${TEST_SYMLINK_CONFIG_FILES_RELATIVE}) + ADD_CUSTOM_COMMAND( + OUTPUT "${DESTINATION_PATH}" + # Create a relative link + COMMAND ln -s -r "${SOURCE_PATH}" "${DESTINATION_PATH}" + DEPENDS "${SOURCE_PATH}" + COMMENT "Symlinking \"${SOURCE_PATH}\" into build directory" + ) + else() + ADD_CUSTOM_COMMAND( + OUTPUT "${DESTINATION_PATH}" + # Create an absolute link + COMMAND ${CMAKE_COMMAND} -E create_symlink "${SOURCE_PATH}" "${DESTINATION_PATH}" + DEPENDS "${SOURCE_PATH}" + COMMENT "Symlinking \"${SOURCE_PATH}\" into build directory" + ) + endif() + endif() # Add a random number to the end of the string to avoid problems with # duplicate filenames set(FILENAME "") get_filename_component(FILENAME ${SOURCE_PATH} NAME ) string(RANDOM LENGTH 4 ALPHABET 0123456789 RANDOMNUMBER) - ADD_CUSTOM_TARGET(copy_${FILENAME}_${RANDOMNUMBER} - DEPENDS "${DESTINATION_PATH}" - ) - ADD_DEPENDENCIES(${TARGET_TO_DEPEND} copy_${FILENAME}_${RANDOMNUMBER}) + if (${CMAKE_SYSTEM_NAME} MATCHES "Windows") + ADD_CUSTOM_TARGET(copy_${FILENAME}_${RANDOMNUMBER} + DEPENDS "${DESTINATION_PATH}" + ) + ADD_DEPENDENCIES(${TARGET_TO_DEPEND} copy_${FILENAME}_${RANDOMNUMBER}) + else() + ADD_CUSTOM_TARGET(symlink_${FILENAME}_${RANDOMNUMBER} + DEPENDS "${DESTINATION_PATH}" + ) + ADD_DEPENDENCIES(${TARGET_TO_DEPEND} symlink_${FILENAME}_${RANDOMNUMBER}) + endif() endfunction() ############################################################################## # configuration-test ############################################################################## +if(NOT ${TESTS_BAT}) + set(TEST_CONFIGURATION configuration-test) + + add_executable(${TEST_CONFIGURATION} configuration_tests/configuration-test.cpp) + target_link_libraries(${TEST_CONFIGURATION} + vsomeip + ${Boost_LIBRARIES} + ${DL_LIBRARY} + ) + + # The following will make sure that ${TEST_CONFIGURATION_CONFIG_FILE} is copied + # from the config folder into the test folder in the builddirectory + # This makes it possible to call the configuration test within the build directory + set(TEST_CONFIGURATION_CONFIG_FILE configuration-test.json) + set(TEST_CONFIGURATION_DEPRECATED_CONFIG_FILE configuration-test-deprecated.json) + copy_to_builddir(${PROJECT_SOURCE_DIR}/test/configuration_tests/${TEST_CONFIGURATION_CONFIG_FILE} + ${PROJECT_BINARY_DIR}/test/${TEST_CONFIGURATION_CONFIG_FILE} + ${TEST_CONFIGURATION} + ) + copy_to_builddir(${PROJECT_SOURCE_DIR}/test/configuration_tests/${TEST_CONFIGURATION_DEPRECATED_CONFIG_FILE} + ${PROJECT_BINARY_DIR}/test/${TEST_CONFIGURATION_DEPRECATED_CONFIG_FILE} + ${TEST_CONFIGURATION} + ) +endif() +############################################################################## +# application test +############################################################################## +if(NOT ${TESTS_BAT}) + set(TEST_APPLICATION application_test) + + add_executable(${TEST_APPLICATION} application_tests/${TEST_APPLICATION}.cpp) + target_link_libraries(${TEST_APPLICATION} + vsomeip + ${Boost_LIBRARIES} + ${DL_LIBRARY} + ${TEST_LINK_LIBRARIES} + ) -set(TEST_CONFIGURATION configuration-test) - -add_executable(${TEST_CONFIGURATION} configuration-test.cpp) -target_link_libraries(${TEST_CONFIGURATION} - vsomeip - ${Boost_LIBRARIES} - ${DL_LIBRARY} -) + set(TEST_APPLICATION_CONFIGURATION_FILE ${TEST_APPLICATION}.json) + copy_to_builddir(${PROJECT_SOURCE_DIR}/test/application_tests/${TEST_APPLICATION_CONFIGURATION_FILE} + ${PROJECT_BINARY_DIR}/test/${TEST_APPLICATION_CONFIGURATION_FILE} + ${TEST_APPLICATION} + ) -# The following will make sure that ${TEST_CONFIGURATION_CONFIG_FILE} is copied -# from the config folder into the test folder in the builddirectory -# This makes it possible to call the configuration test within the build directory -set(TEST_CONFIGURATION_CONFIG_FILE vsomeip-test.json) -copy_to_builddir(${PROJECT_SOURCE_DIR}/config/${TEST_CONFIGURATION_CONFIG_FILE} - ${PROJECT_BINARY_DIR}/test/${TEST_CONFIGURATION_CONFIG_FILE} - ${TEST_CONFIGURATION} -) + set(TEST_APPLICATION_NO_DISPATCH_CONFIGURATION_FILE ${TEST_APPLICATION}_no_dispatch_threads.json) + 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_STARTER ${TEST_APPLICATION}_starter.sh) + copy_to_builddir(${PROJECT_SOURCE_DIR}/test/application_tests/${TEST_APPLICATION_STARTER} + ${PROJECT_BINARY_DIR}/test/${TEST_APPLICATION_STARTER} + ${TEST_APPLICATION} + ) +endif() ############################################################################## # magic-cookies-test-client ############################################################################## -set(TEST_MAGIC_COOKIES_NAME magic_cookies_test) - -set(TEST_MAGIC_COOKIES_CLIENT magic-cookies-test-client) -add_executable(${TEST_MAGIC_COOKIES_CLIENT} magic-cookies-test-client.cpp) -target_link_libraries(${TEST_MAGIC_COOKIES_CLIENT} - vsomeip - ${Boost_LIBRARIES} - ${DL_LIBRARY} - ${CMAKE_THREAD_LIBS_INIT} -) -add_dependencies(${TEST_MAGIC_COOKIES_CLIENT} response-sample) - -# Copy config file for client into $BUILDDIR/test -set(TEST_MAGIC_COOKIES_CLIENT_CONFIG_FILE vsomeip-magic-cookies-client.json) -copy_to_builddir(${PROJECT_SOURCE_DIR}/config/${TEST_MAGIC_COOKIES_CLIENT_CONFIG_FILE} - ${PROJECT_BINARY_DIR}/test/${TEST_MAGIC_COOKIES_CLIENT_CONFIG_FILE} - ${TEST_MAGIC_COOKIES_CLIENT} -) +if(NOT ${TESTS_BAT}) + set(TEST_MAGIC_COOKIES_NAME magic_cookies_test) + + set(TEST_MAGIC_COOKIES_CLIENT ${TEST_MAGIC_COOKIES_NAME}_client) + add_executable(${TEST_MAGIC_COOKIES_CLIENT} magic_cookies_tests/${TEST_MAGIC_COOKIES_CLIENT}.cpp) + target_link_libraries(${TEST_MAGIC_COOKIES_CLIENT} + vsomeip + ${Boost_LIBRARIES} + ${DL_LIBRARY} + ${CMAKE_THREAD_LIBS_INIT} + ) -# Copy bashscript to start client into $BUILDDIR/test -set(TEST_MAGIC_COOKIES_CLIENT_UNDERSCORE magic_cookies_test_client) -set(TEST_MAGIC_COOKIES_CLIENT_START_SCRIPT ${TEST_MAGIC_COOKIES_CLIENT_UNDERSCORE}_start.sh) -copy_to_builddir(${PROJECT_SOURCE_DIR}/test/${TEST_MAGIC_COOKIES_CLIENT_START_SCRIPT} - ${PROJECT_BINARY_DIR}/test/${TEST_MAGIC_COOKIES_CLIENT_START_SCRIPT} - ${TEST_MAGIC_COOKIES_CLIENT} -) + set(TEST_MAGIC_COOKIES_SERVICE ${TEST_MAGIC_COOKIES_NAME}_service) + add_executable(${TEST_MAGIC_COOKIES_SERVICE} magic_cookies_tests/${TEST_MAGIC_COOKIES_SERVICE}.cpp) + target_link_libraries(${TEST_MAGIC_COOKIES_SERVICE} + vsomeip + ${Boost_LIBRARIES} + ${DL_LIBRARY} + ${CMAKE_THREAD_LIBS_INIT} + ) -set(TEST_MAGIC_COOKIES_SERVICE magic_cookies_test_service) + # Copy config file for client into $BUILDDIR/test + set(TEST_MAGIC_COOKIES_CLIENT_CONFIG_FILE ${TEST_MAGIC_COOKIES_CLIENT}.json) + configure_file( + ${PROJECT_SOURCE_DIR}/test/magic_cookies_tests/conf/${TEST_MAGIC_COOKIES_CLIENT_CONFIG_FILE}.in + ${PROJECT_SOURCE_DIR}/test/magic_cookies_tests/${TEST_MAGIC_COOKIES_CLIENT_CONFIG_FILE} + @ONLY) + copy_to_builddir(${PROJECT_SOURCE_DIR}/test/magic_cookies_tests/${TEST_MAGIC_COOKIES_CLIENT_CONFIG_FILE} + ${PROJECT_BINARY_DIR}/test/${TEST_MAGIC_COOKIES_CLIENT_CONFIG_FILE} + ${TEST_MAGIC_COOKIES_CLIENT} + ) -# Copy config file for service into $BUILDDIR/test -set(TEST_MAGIC_COOKIES_SERVICE_CONFIG_FILE vsomeip-magic-cookies-service.json) -copy_to_builddir(${PROJECT_SOURCE_DIR}/config/${TEST_MAGIC_COOKIES_SERVICE_CONFIG_FILE} - ${PROJECT_BINARY_DIR}/test/${TEST_MAGIC_COOKIES_SERVICE_CONFIG_FILE} - ${TEST_MAGIC_COOKIES_CLIENT} -) + # Copy bashscript to start client into $BUILDDIR/test + set(TEST_MAGIC_COOKIES_CLIENT_START_SCRIPT ${TEST_MAGIC_COOKIES_CLIENT}_start.sh) + copy_to_builddir(${PROJECT_SOURCE_DIR}/test/magic_cookies_tests/${TEST_MAGIC_COOKIES_CLIENT_START_SCRIPT} + ${PROJECT_BINARY_DIR}/test/${TEST_MAGIC_COOKIES_CLIENT_START_SCRIPT} + ${TEST_MAGIC_COOKIES_CLIENT} + ) -# Copy bashscript to start service into $BUILDDIR/test -set(TEST_MAGIC_COOKIES_SERVICE_START_SCRIPT ${TEST_MAGIC_COOKIES_SERVICE}_start.sh) -copy_to_builddir(${PROJECT_SOURCE_DIR}/test/${TEST_MAGIC_COOKIES_SERVICE_START_SCRIPT} - ${PROJECT_BINARY_DIR}/test/${TEST_MAGIC_COOKIES_SERVICE_START_SCRIPT} - ${TEST_MAGIC_COOKIES_CLIENT} -) + set(TEST_MAGIC_COOKIES_SERVICE magic_cookies_test_service) + # Copy config file for service into $BUILDDIR/test + set(TEST_MAGIC_COOKIES_SERVICE_CONFIG_FILE ${TEST_MAGIC_COOKIES_SERVICE}.json) + configure_file( + ${PROJECT_SOURCE_DIR}/test/magic_cookies_tests/conf/${TEST_MAGIC_COOKIES_SERVICE_CONFIG_FILE}.in + ${PROJECT_SOURCE_DIR}/test/magic_cookies_tests/${TEST_MAGIC_COOKIES_SERVICE_CONFIG_FILE} + @ONLY) + copy_to_builddir(${PROJECT_SOURCE_DIR}/test/magic_cookies_tests/${TEST_MAGIC_COOKIES_SERVICE_CONFIG_FILE} + ${PROJECT_BINARY_DIR}/test/${TEST_MAGIC_COOKIES_SERVICE_CONFIG_FILE} + ${TEST_MAGIC_COOKIES_SERVICE} + ) -# Copy bashscript to start client and server $BUILDDIR/test -set(TEST_MAGIC_COOKIES_STARTER ${TEST_MAGIC_COOKIES_NAME}_starter.sh) -copy_to_builddir(${PROJECT_SOURCE_DIR}/test/${TEST_MAGIC_COOKIES_STARTER} - ${PROJECT_BINARY_DIR}/test/${TEST_MAGIC_COOKIES_STARTER} - ${TEST_MAGIC_COOKIES_CLIENT} -) + # Copy bashscript to start service into $BUILDDIR/test + set(TEST_MAGIC_COOKIES_SERVICE_START_SCRIPT ${TEST_MAGIC_COOKIES_SERVICE}_start.sh) + copy_to_builddir(${PROJECT_SOURCE_DIR}/test/magic_cookies_tests/${TEST_MAGIC_COOKIES_SERVICE_START_SCRIPT} + ${PROJECT_BINARY_DIR}/test/${TEST_MAGIC_COOKIES_SERVICE_START_SCRIPT} + ${TEST_MAGIC_COOKIES_CLIENT} + ) + # Copy bashscript to start client and server $BUILDDIR/test + set(TEST_MAGIC_COOKIES_STARTER ${TEST_MAGIC_COOKIES_NAME}_starter.sh) + copy_to_builddir(${PROJECT_SOURCE_DIR}/test/magic_cookies_tests/${TEST_MAGIC_COOKIES_STARTER} + ${PROJECT_BINARY_DIR}/test/${TEST_MAGIC_COOKIES_STARTER} + ${TEST_MAGIC_COOKIES_CLIENT} + ) +endif() ############################################################################## # someip-header-factory-test ############################################################################## -set(TEST_HEADER_FACTORY_NAME header_factory_test) - -set(TEST_HEADER_FACTORY header_factory_test) -add_executable(${TEST_HEADER_FACTORY} header_factory_tests/header_factory_test.cpp) -target_link_libraries(${TEST_HEADER_FACTORY} - vsomeip - ${Boost_LIBRARIES} - ${DL_LIBRARY} - ${CMAKE_THREAD_LIBS_INIT} - ${TEST_LINK_LIBRARIES} -) - -############################################################################## -# Now comes the second part of the header factory test which consists of ouf -# a client and a service both with settings file and bash scripts to start them -set(TEST_HEADER_FACTORY_CLIENT header_factory_test_client) -add_executable(${TEST_HEADER_FACTORY_CLIENT} header_factory_tests/${TEST_HEADER_FACTORY_CLIENT}.cpp) -target_link_libraries(${TEST_HEADER_FACTORY_CLIENT} - vsomeip - ${Boost_LIBRARIES} - ${DL_LIBRARY} - ${CMAKE_THREAD_LIBS_INIT} - ${TEST_LINK_LIBRARIES} -) +if(NOT ${TESTS_BAT}) + set(TEST_HEADER_FACTORY_NAME header_factory_test) + + set(TEST_HEADER_FACTORY header_factory_test) + add_executable(${TEST_HEADER_FACTORY} header_factory_tests/header_factory_test.cpp) + target_link_libraries(${TEST_HEADER_FACTORY} + vsomeip + ${Boost_LIBRARIES} + ${DL_LIBRARY} + ${CMAKE_THREAD_LIBS_INIT} + ${TEST_LINK_LIBRARIES} + ) -# Copy config file for client into $BUILDDIR/test -set(TEST_HEADER_FACTORY_CLIENT_CONFIG_FILE ${TEST_HEADER_FACTORY_CLIENT}.json) -copy_to_builddir(${PROJECT_SOURCE_DIR}/test/header_factory_tests/${TEST_HEADER_FACTORY_CLIENT_CONFIG_FILE} - ${PROJECT_BINARY_DIR}/test/${TEST_HEADER_FACTORY_CLIENT_CONFIG_FILE} - ${TEST_HEADER_FACTORY_CLIENT} -) + ############################################################################## + # Now comes the second part of the header factory test which consists of ouf + # a client and a service both with settings file and bash scripts to start them + set(TEST_HEADER_FACTORY_CLIENT header_factory_test_client) + add_executable(${TEST_HEADER_FACTORY_CLIENT} header_factory_tests/${TEST_HEADER_FACTORY_CLIENT}.cpp) + target_link_libraries(${TEST_HEADER_FACTORY_CLIENT} + vsomeip + ${Boost_LIBRARIES} + ${DL_LIBRARY} + ${CMAKE_THREAD_LIBS_INIT} + ${TEST_LINK_LIBRARIES} + ) -# Copy bashscript to start client into $BUILDDIR/test -set(TEST_HEADER_FACTORY_CLIENT_START_SCRIPT ${TEST_HEADER_FACTORY_CLIENT}_start.sh) -copy_to_builddir(${PROJECT_SOURCE_DIR}/test/header_factory_tests/${TEST_HEADER_FACTORY_CLIENT_START_SCRIPT} - ${PROJECT_BINARY_DIR}/test/${TEST_HEADER_FACTORY_CLIENT_START_SCRIPT} - ${TEST_HEADER_FACTORY_CLIENT} -) + # Copy config file for client into $BUILDDIR/test + set(TEST_HEADER_FACTORY_CLIENT_CONFIG_FILE ${TEST_HEADER_FACTORY_CLIENT}.json) + copy_to_builddir(${PROJECT_SOURCE_DIR}/test/header_factory_tests/${TEST_HEADER_FACTORY_CLIENT_CONFIG_FILE} + ${PROJECT_BINARY_DIR}/test/${TEST_HEADER_FACTORY_CLIENT_CONFIG_FILE} + ${TEST_HEADER_FACTORY_CLIENT} + ) -set(TEST_HEADER_FACTORY_SERVICE header_factory_test_service) -add_executable(${TEST_HEADER_FACTORY_SERVICE} header_factory_tests/${TEST_HEADER_FACTORY_SERVICE}.cpp) -target_link_libraries(${TEST_HEADER_FACTORY_SERVICE} - vsomeip - ${Boost_LIBRARIES} - ${DL_LIBRARY} - ${CMAKE_THREAD_LIBS_INIT} - ${TEST_LINK_LIBRARIES} -) + # Copy bashscript to start client into $BUILDDIR/test + set(TEST_HEADER_FACTORY_CLIENT_START_SCRIPT ${TEST_HEADER_FACTORY_CLIENT}_start.sh) + copy_to_builddir(${PROJECT_SOURCE_DIR}/test/header_factory_tests/${TEST_HEADER_FACTORY_CLIENT_START_SCRIPT} + ${PROJECT_BINARY_DIR}/test/${TEST_HEADER_FACTORY_CLIENT_START_SCRIPT} + ${TEST_HEADER_FACTORY_CLIENT} + ) -# Copy config file for service into $BUILDDIR/test -set(TEST_HEADER_FACTORY_SERVICE_CONFIG_FILE ${TEST_HEADER_FACTORY_SERVICE}.json) -copy_to_builddir(${PROJECT_SOURCE_DIR}/test/header_factory_tests/${TEST_HEADER_FACTORY_SERVICE_CONFIG_FILE} - ${PROJECT_BINARY_DIR}/test/${TEST_HEADER_FACTORY_SERVICE_CONFIG_FILE} - ${TEST_HEADER_FACTORY_SERVICE} -) + set(TEST_HEADER_FACTORY_SERVICE header_factory_test_service) + add_executable(${TEST_HEADER_FACTORY_SERVICE} header_factory_tests/${TEST_HEADER_FACTORY_SERVICE}.cpp) + target_link_libraries(${TEST_HEADER_FACTORY_SERVICE} + vsomeip + ${Boost_LIBRARIES} + ${DL_LIBRARY} + ${CMAKE_THREAD_LIBS_INIT} + ${TEST_LINK_LIBRARIES} + ) -# Copy bashscript to start service into $BUILDDIR/test -set(TEST_HEADER_FACTORY_SERVICE_START_SCRIPT ${TEST_HEADER_FACTORY_SERVICE}_start.sh) -copy_to_builddir(${PROJECT_SOURCE_DIR}/test/header_factory_tests/${TEST_HEADER_FACTORY_SERVICE_START_SCRIPT} - ${PROJECT_BINARY_DIR}/test/${TEST_HEADER_FACTORY_SERVICE_START_SCRIPT} - ${TEST_HEADER_FACTORY_SERVICE} -) + # Copy config file for service into $BUILDDIR/test + set(TEST_HEADER_FACTORY_SERVICE_CONFIG_FILE ${TEST_HEADER_FACTORY_SERVICE}.json) + copy_to_builddir(${PROJECT_SOURCE_DIR}/test/header_factory_tests/${TEST_HEADER_FACTORY_SERVICE_CONFIG_FILE} + ${PROJECT_BINARY_DIR}/test/${TEST_HEADER_FACTORY_SERVICE_CONFIG_FILE} + ${TEST_HEADER_FACTORY_SERVICE} + ) -# Copy bashscript to start client and server $BUILDDIR/test -set(TEST_HEADER_FACTORY_STARTER header_factory_test_send_receive_starter.sh) -copy_to_builddir(${PROJECT_SOURCE_DIR}/test/header_factory_tests/${TEST_HEADER_FACTORY_STARTER} - ${PROJECT_BINARY_DIR}/test/${TEST_HEADER_FACTORY_STARTER} - ${TEST_HEADER_FACTORY_CLIENT} -) + # Copy bashscript to start service into $BUILDDIR/test + set(TEST_HEADER_FACTORY_SERVICE_START_SCRIPT ${TEST_HEADER_FACTORY_SERVICE}_start.sh) + copy_to_builddir(${PROJECT_SOURCE_DIR}/test/header_factory_tests/${TEST_HEADER_FACTORY_SERVICE_START_SCRIPT} + ${PROJECT_BINARY_DIR}/test/${TEST_HEADER_FACTORY_SERVICE_START_SCRIPT} + ${TEST_HEADER_FACTORY_SERVICE} + ) + # Copy bashscript to start client and server $BUILDDIR/test + set(TEST_HEADER_FACTORY_STARTER header_factory_test_send_receive_starter.sh) + copy_to_builddir(${PROJECT_SOURCE_DIR}/test/header_factory_tests/${TEST_HEADER_FACTORY_STARTER} + ${PROJECT_BINARY_DIR}/test/${TEST_HEADER_FACTORY_STARTER} + ${TEST_HEADER_FACTORY_CLIENT} + ) +endif() ############################################################################## # routing-test ############################################################################## -set(TEST_LOCAL_ROUTING_NAME local_routing_test) -set(TEST_LOCAL_ROUTING_SERVICE local_routing_test_service) +if(NOT ${TESTS_BAT}) + set(TEST_LOCAL_ROUTING_NAME local_routing_test) -add_executable(${TEST_LOCAL_ROUTING_SERVICE} routing_tests/${TEST_LOCAL_ROUTING_SERVICE}.cpp) -target_link_libraries(${TEST_LOCAL_ROUTING_SERVICE} - vsomeip - ${Boost_LIBRARIES} - ${DL_LIBRARY} - ${TEST_LINK_LIBRARIES} -) + set(TEST_LOCAL_ROUTING_SERVICE local_routing_test_service) + add_executable(${TEST_LOCAL_ROUTING_SERVICE} routing_tests/${TEST_LOCAL_ROUTING_SERVICE}.cpp) + target_link_libraries(${TEST_LOCAL_ROUTING_SERVICE} + vsomeip + ${Boost_LIBRARIES} + ${DL_LIBRARY} + ${TEST_LINK_LIBRARIES} + ) -# Copy config file for service into $BUILDDIR/test -set(TEST_LOCAL_ROUTING_SERVICE_CONFIG_FILE ${TEST_LOCAL_ROUTING_SERVICE}.json) -copy_to_builddir(${PROJECT_SOURCE_DIR}/test/routing_tests/${TEST_LOCAL_ROUTING_SERVICE_CONFIG_FILE} - ${PROJECT_BINARY_DIR}/test/${TEST_LOCAL_ROUTING_SERVICE_CONFIG_FILE} - ${TEST_LOCAL_ROUTING_SERVICE} -) + # Copy config file for service into $BUILDDIR/test + set(TEST_LOCAL_ROUTING_SERVICE_CONFIG_FILE ${TEST_LOCAL_ROUTING_SERVICE}.json) + copy_to_builddir(${PROJECT_SOURCE_DIR}/test/routing_tests/${TEST_LOCAL_ROUTING_SERVICE_CONFIG_FILE} + ${PROJECT_BINARY_DIR}/test/${TEST_LOCAL_ROUTING_SERVICE_CONFIG_FILE} + ${TEST_LOCAL_ROUTING_SERVICE} + ) -# Copy bashscript to start service into $BUILDDIR/test -set(TEST_LOCAL_ROUTING_SERVICE_START_SCRIPT ${TEST_LOCAL_ROUTING_SERVICE}_start.sh) -copy_to_builddir(${PROJECT_SOURCE_DIR}/test/routing_tests/${TEST_LOCAL_ROUTING_SERVICE_START_SCRIPT} - ${PROJECT_BINARY_DIR}/test/${TEST_LOCAL_ROUTING_SERVICE_START_SCRIPT} - ${TEST_LOCAL_ROUTING_SERVICE} -) + # Copy bashscript to start service into $BUILDDIR/test + set(TEST_LOCAL_ROUTING_SERVICE_START_SCRIPT ${TEST_LOCAL_ROUTING_SERVICE}_start.sh) + copy_to_builddir(${PROJECT_SOURCE_DIR}/test/routing_tests/${TEST_LOCAL_ROUTING_SERVICE_START_SCRIPT} + ${PROJECT_BINARY_DIR}/test/${TEST_LOCAL_ROUTING_SERVICE_START_SCRIPT} + ${TEST_LOCAL_ROUTING_SERVICE} + ) -set(TEST_LOCAL_ROUTING_CLIENT local_routing_test_client) + set(TEST_LOCAL_ROUTING_CLIENT local_routing_test_client) + add_executable(${TEST_LOCAL_ROUTING_CLIENT} routing_tests/${TEST_LOCAL_ROUTING_CLIENT}.cpp) + target_link_libraries(${TEST_LOCAL_ROUTING_CLIENT} + vsomeip + ${Boost_LIBRARIES} + ${DL_LIBRARY} + ${TEST_LINK_LIBRARIES} + ) -add_executable(${TEST_LOCAL_ROUTING_CLIENT} routing_tests/${TEST_LOCAL_ROUTING_CLIENT}.cpp) -target_link_libraries(${TEST_LOCAL_ROUTING_CLIENT} - vsomeip - ${Boost_LIBRARIES} - ${DL_LIBRARY} - ${TEST_LINK_LIBRARIES} -) + # Copy config file for client into $BUILDDIR/test + set(TEST_LOCAL_ROUTING_CLIENT_CONFIG_FILE ${TEST_LOCAL_ROUTING_CLIENT}.json) + copy_to_builddir(${PROJECT_SOURCE_DIR}/test/routing_tests/${TEST_LOCAL_ROUTING_CLIENT_CONFIG_FILE} + ${PROJECT_BINARY_DIR}/test/${TEST_LOCAL_ROUTING_CLIENT_CONFIG_FILE} + ${TEST_LOCAL_ROUTING_CLIENT} + ) -# Copy config file for client into $BUILDDIR/test -set(TEST_LOCAL_ROUTING_CLIENT_CONFIG_FILE ${TEST_LOCAL_ROUTING_CLIENT}.json) -copy_to_builddir(${PROJECT_SOURCE_DIR}/test/routing_tests/${TEST_LOCAL_ROUTING_CLIENT_CONFIG_FILE} - ${PROJECT_BINARY_DIR}/test/${TEST_LOCAL_ROUTING_CLIENT_CONFIG_FILE} - ${TEST_LOCAL_ROUTING_CLIENT} -) + # Copy bashscript to start client into $BUILDDIR/test + set(TEST_LOCAL_ROUTING_CLIENT_START_SCRIPT ${TEST_LOCAL_ROUTING_CLIENT}_start.sh) + copy_to_builddir(${PROJECT_SOURCE_DIR}/test/routing_tests/${TEST_LOCAL_ROUTING_CLIENT_START_SCRIPT} + ${PROJECT_BINARY_DIR}/test/${TEST_LOCAL_ROUTING_CLIENT_START_SCRIPT} + ${TEST_LOCAL_ROUTING_CLIENT} + ) -# Copy bashscript to start client into $BUILDDIR/test -set(TEST_LOCAL_ROUTING_CLIENT_START_SCRIPT ${TEST_LOCAL_ROUTING_CLIENT}_start.sh) -copy_to_builddir(${PROJECT_SOURCE_DIR}/test/routing_tests/${TEST_LOCAL_ROUTING_CLIENT_START_SCRIPT} - ${PROJECT_BINARY_DIR}/test/${TEST_LOCAL_ROUTING_CLIENT_START_SCRIPT} - ${TEST_LOCAL_ROUTING_CLIENT} -) + # Copy bashscript to start client and server $BUILDDIR/test + set(TEST_LOCAL_ROUTING_STARTER local_routing_test_starter.sh) + 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} + ) -# Copy bashscript to start client and server $BUILDDIR/test -set(TEST_LOCAL_ROUTING_STARTER local_routing_test_starter.sh) -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} -) + ############################################################################## + set(TEST_EXTERNAL_LOCAL_ROUTING_NAME external_local_routing_test) + set(TEST_EXTERNAL_LOCAL_ROUTING_SERVICE external_local_routing_test_service) + add_executable(${TEST_EXTERNAL_LOCAL_ROUTING_SERVICE} routing_tests/${TEST_EXTERNAL_LOCAL_ROUTING_SERVICE}.cpp) + target_link_libraries(${TEST_EXTERNAL_LOCAL_ROUTING_SERVICE} + vsomeip + ${Boost_LIBRARIES} + ${DL_LIBRARY} + ${TEST_LINK_LIBRARIES} + ) -############################################################################## + # Copy config file for service into $BUILDDIR/test + set(TEST_EXTERNAL_LOCAL_ROUTING_SERVICE_CONFIG_FILE ${TEST_EXTERNAL_LOCAL_ROUTING_SERVICE}.json) + configure_file( + ${PROJECT_SOURCE_DIR}/test/routing_tests/conf/${TEST_EXTERNAL_LOCAL_ROUTING_SERVICE_CONFIG_FILE}.in + ${PROJECT_SOURCE_DIR}/test/routing_tests/${TEST_EXTERNAL_LOCAL_ROUTING_SERVICE_CONFIG_FILE} + @ONLY) + copy_to_builddir( + ${PROJECT_SOURCE_DIR}/test/routing_tests/${TEST_EXTERNAL_LOCAL_ROUTING_SERVICE_CONFIG_FILE} + ${PROJECT_BINARY_DIR}/test/${TEST_EXTERNAL_LOCAL_ROUTING_SERVICE_CONFIG_FILE} + ${TEST_EXTERNAL_LOCAL_ROUTING_SERVICE} + ) -set(TEST_EXTERNAL_LOCAL_ROUTING_NAME external_local_routing_test) + # Copy bashscript to start service into $BUILDDIR/test + set(TEST_EXTERNAL_LOCAL_ROUTING_SERVICE_START_SCRIPT ${TEST_EXTERNAL_LOCAL_ROUTING_SERVICE}_start.sh) + copy_to_builddir( + ${PROJECT_SOURCE_DIR}/test/routing_tests/${TEST_EXTERNAL_LOCAL_ROUTING_SERVICE_START_SCRIPT} + ${PROJECT_BINARY_DIR}/test/${TEST_EXTERNAL_LOCAL_ROUTING_SERVICE_START_SCRIPT} + ${TEST_EXTERNAL_LOCAL_ROUTING_SERVICE} + ) -set(TEST_EXTERNAL_LOCAL_ROUTING_SERVICE external_local_routing_test_service) -add_executable(${TEST_EXTERNAL_LOCAL_ROUTING_SERVICE} routing_tests/${TEST_EXTERNAL_LOCAL_ROUTING_SERVICE}.cpp) -target_link_libraries(${TEST_EXTERNAL_LOCAL_ROUTING_SERVICE} - vsomeip - ${Boost_LIBRARIES} - ${DL_LIBRARY} - ${TEST_LINK_LIBRARIES} -) + # Copy bashscript to start external client into $BUILDDIR/test + set(TEST_EXTERNAL_LOCAL_ROUTING_CLIENT external_local_routing_test_client_external) + set(TEST_EXTERNAL_LOCAL_ROUTING_CLIENT_START_SCRIPT ${TEST_EXTERNAL_LOCAL_ROUTING_CLIENT}_start.sh) + copy_to_builddir( + ${PROJECT_SOURCE_DIR}/test/routing_tests/${TEST_EXTERNAL_LOCAL_ROUTING_CLIENT_START_SCRIPT} + ${PROJECT_BINARY_DIR}/test/${TEST_EXTERNAL_LOCAL_ROUTING_CLIENT_START_SCRIPT} + ${TEST_EXTERNAL_LOCAL_ROUTING_SERVICE} + ) -# Copy config file for service into $BUILDDIR/test -set(TEST_EXTERNAL_LOCAL_ROUTING_SERVICE_CONFIG_FILE ${TEST_EXTERNAL_LOCAL_ROUTING_SERVICE}.json) -copy_to_builddir( - ${PROJECT_SOURCE_DIR}/test/routing_tests/${TEST_EXTERNAL_LOCAL_ROUTING_SERVICE_CONFIG_FILE} - ${PROJECT_BINARY_DIR}/test/${TEST_EXTERNAL_LOCAL_ROUTING_SERVICE_CONFIG_FILE} - ${TEST_EXTERNAL_LOCAL_ROUTING_SERVICE} -) + # Copy config file for client into $BUILDDIR/test + set(TEST_EXTERNAL_LOCAL_ROUTING_CLIENT_CONFIG_FILE ${TEST_EXTERNAL_LOCAL_ROUTING_CLIENT}.json) + configure_file( + ${PROJECT_SOURCE_DIR}/test/routing_tests/conf/${TEST_EXTERNAL_LOCAL_ROUTING_CLIENT_CONFIG_FILE}.in + ${PROJECT_SOURCE_DIR}/test/routing_tests/${TEST_EXTERNAL_LOCAL_ROUTING_CLIENT_CONFIG_FILE} + @ONLY) + copy_to_builddir(${PROJECT_SOURCE_DIR}/test/routing_tests/${TEST_EXTERNAL_LOCAL_ROUTING_CLIENT_CONFIG_FILE} + ${PROJECT_BINARY_DIR}/test/${TEST_EXTERNAL_LOCAL_ROUTING_CLIENT_CONFIG_FILE} + ${TEST_EXTERNAL_LOCAL_ROUTING_SERVICE} + ) -# Copy bashscript to start service into $BUILDDIR/test -set(TEST_EXTERNAL_LOCAL_ROUTING_SERVICE_START_SCRIPT ${TEST_EXTERNAL_LOCAL_ROUTING_SERVICE}_start.sh) -copy_to_builddir( - ${PROJECT_SOURCE_DIR}/test/routing_tests/${TEST_EXTERNAL_LOCAL_ROUTING_SERVICE_START_SCRIPT} - ${PROJECT_BINARY_DIR}/test/${TEST_EXTERNAL_LOCAL_ROUTING_SERVICE_START_SCRIPT} - ${TEST_EXTERNAL_LOCAL_ROUTING_SERVICE} -) + # Copy bashscript to start client and server $BUILDDIR/test + set(TEST_EXTERNAL_LOCAL_ROUTING_STARTER external_local_routing_test_starter.sh) + copy_to_builddir(${PROJECT_SOURCE_DIR}/test/routing_tests/${TEST_EXTERNAL_LOCAL_ROUTING_STARTER} + ${PROJECT_BINARY_DIR}/test/${TEST_EXTERNAL_LOCAL_ROUTING_STARTER} + ${TEST_EXTERNAL_LOCAL_ROUTING_SERVICE} + ) +else() + set(TEST_LOCAL_ROUTING_NAME local_routing_test) + + set(TEST_LOCAL_ROUTING_SERVICE local_routing_test_service) + add_executable(${TEST_LOCAL_ROUTING_SERVICE} routing_tests/${TEST_LOCAL_ROUTING_SERVICE}.cpp) + target_link_libraries(${TEST_LOCAL_ROUTING_SERVICE} + vsomeip + ${Boost_LIBRARIES} + ${DL_LIBRARY} + ${TEST_LINK_LIBRARIES} + ) -# Copy bashscript to start external client into $BUILDDIR/test -set(TEST_EXTERNAL_LOCAL_ROUTING_CLIENT external_local_routing_test_client_external) -set(TEST_EXTERNAL_LOCAL_ROUTING_CLIENT_START_SCRIPT ${TEST_EXTERNAL_LOCAL_ROUTING_CLIENT}_start.sh) -copy_to_builddir( - ${PROJECT_SOURCE_DIR}/test/routing_tests/${TEST_EXTERNAL_LOCAL_ROUTING_CLIENT_START_SCRIPT} - ${PROJECT_BINARY_DIR}/test/${TEST_EXTERNAL_LOCAL_ROUTING_CLIENT_START_SCRIPT} - ${TEST_EXTERNAL_LOCAL_ROUTING_SERVICE} -) + # Copy config file for service into $BUILDDIR/test + set(TEST_LOCAL_ROUTING_SERVICE_CONFIG_FILE ${TEST_LOCAL_ROUTING_SERVICE}.json) + copy_to_builddir(${PROJECT_SOURCE_DIR}/test/routing_tests/${TEST_LOCAL_ROUTING_SERVICE_CONFIG_FILE} + ${PROJECT_BINARY_DIR}/test/${TEST_LOCAL_ROUTING_SERVICE_CONFIG_FILE} + ${TEST_LOCAL_ROUTING_SERVICE} + ) -# Copy config file for client into $BUILDDIR/test -set(TEST_EXTERNAL_LOCAL_ROUTING_CLIENT_CONFIG_FILE ${TEST_EXTERNAL_LOCAL_ROUTING_CLIENT}.json) -copy_to_builddir(${PROJECT_SOURCE_DIR}/test/routing_tests/${TEST_EXTERNAL_LOCAL_ROUTING_CLIENT_CONFIG_FILE} - ${PROJECT_BINARY_DIR}/test/${TEST_EXTERNAL_LOCAL_ROUTING_CLIENT_CONFIG_FILE} - ${TEST_EXTERNAL_LOCAL_ROUTING_SERVICE} -) + # Copy bashscript to start service into $BUILDDIR/test + set(TEST_LOCAL_ROUTING_SERVICE_START_SCRIPT ${TEST_LOCAL_ROUTING_SERVICE}_start.sh) + copy_to_builddir(${PROJECT_SOURCE_DIR}/test/routing_tests/${TEST_LOCAL_ROUTING_SERVICE_START_SCRIPT} + ${PROJECT_BINARY_DIR}/test/${TEST_LOCAL_ROUTING_SERVICE_START_SCRIPT} + ${TEST_LOCAL_ROUTING_SERVICE} + ) -# Copy bashscript to start client and server $BUILDDIR/test -set(TEST_EXTERNAL_LOCAL_ROUTING_STARTER external_local_routing_test_starter.sh) -copy_to_builddir(${PROJECT_SOURCE_DIR}/test/routing_tests/${TEST_EXTERNAL_LOCAL_ROUTING_STARTER} - ${PROJECT_BINARY_DIR}/test/${TEST_EXTERNAL_LOCAL_ROUTING_STARTER} - ${TEST_EXTERNAL_LOCAL_ROUTING_SERVICE} -) + set(TEST_LOCAL_ROUTING_CLIENT local_routing_test_client) + add_executable(${TEST_LOCAL_ROUTING_CLIENT} routing_tests/${TEST_LOCAL_ROUTING_CLIENT}.cpp) + target_link_libraries(${TEST_LOCAL_ROUTING_CLIENT} + vsomeip + ${Boost_LIBRARIES} + ${DL_LIBRARY} + ${TEST_LINK_LIBRARIES} + ) + + # Copy config file for client into $BUILDDIR/test + set(TEST_LOCAL_ROUTING_CLIENT_CONFIG_FILE ${TEST_LOCAL_ROUTING_CLIENT}.json) + copy_to_builddir(${PROJECT_SOURCE_DIR}/test/routing_tests/${TEST_LOCAL_ROUTING_CLIENT_CONFIG_FILE} + ${PROJECT_BINARY_DIR}/test/${TEST_LOCAL_ROUTING_CLIENT_CONFIG_FILE} + ${TEST_LOCAL_ROUTING_CLIENT} + ) + + # Copy bashscript to start client into $BUILDDIR/test + set(TEST_LOCAL_ROUTING_CLIENT_START_SCRIPT ${TEST_LOCAL_ROUTING_CLIENT}_start.sh) + copy_to_builddir(${PROJECT_SOURCE_DIR}/test/routing_tests/${TEST_LOCAL_ROUTING_CLIENT_START_SCRIPT} + ${PROJECT_BINARY_DIR}/test/${TEST_LOCAL_ROUTING_CLIENT_START_SCRIPT} + ${TEST_LOCAL_ROUTING_CLIENT} + ) + # Copy bashscript to start client and server $BUILDDIR/test + set(TEST_LOCAL_ROUTING_STARTER local_routing_test_starter.sh) + 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} + ) +endif() ############################################################################## # payload-test ############################################################################## -set(TEST_LOCAL_PAYLOAD_NAME local_payload_test) +if(NOT ${TESTS_BAT}) + set(TEST_LOCAL_PAYLOAD_NAME local_payload_test) -set(TEST_PAYLOAD_SERVICE payload_test_service) -add_executable(${TEST_PAYLOAD_SERVICE} payload_tests/${TEST_PAYLOAD_SERVICE}.cpp) -target_link_libraries(${TEST_PAYLOAD_SERVICE} - vsomeip - ${Boost_LIBRARIES} - ${DL_LIBRARY} - ${TEST_LINK_LIBRARIES} -) + set(TEST_PAYLOAD_SERVICE payload_test_service) + add_executable(${TEST_PAYLOAD_SERVICE} payload_tests/${TEST_PAYLOAD_SERVICE}.cpp) + target_link_libraries(${TEST_PAYLOAD_SERVICE} + vsomeip + ${Boost_LIBRARIES} + ${DL_LIBRARY} + ${TEST_LINK_LIBRARIES} + ) -# Copy config file for service into $BUILDDIR/test -set(TEST_LOCAL_PAYLOAD_SERVICE_CONFIG_FILE local_${TEST_PAYLOAD_SERVICE}.json) -copy_to_builddir( - ${PROJECT_SOURCE_DIR}/test/payload_tests/${TEST_LOCAL_PAYLOAD_SERVICE_CONFIG_FILE} - ${PROJECT_BINARY_DIR}/test/${TEST_LOCAL_PAYLOAD_SERVICE_CONFIG_FILE} - ${TEST_PAYLOAD_SERVICE} -) + # Copy config file for service into $BUILDDIR/test + set(TEST_LOCAL_PAYLOAD_SERVICE_CONFIG_FILE local_${TEST_PAYLOAD_SERVICE}.json) + copy_to_builddir( + ${PROJECT_SOURCE_DIR}/test/payload_tests/${TEST_LOCAL_PAYLOAD_SERVICE_CONFIG_FILE} + ${PROJECT_BINARY_DIR}/test/${TEST_LOCAL_PAYLOAD_SERVICE_CONFIG_FILE} + ${TEST_PAYLOAD_SERVICE} + ) -# Copy bashscript to start service into $BUILDDIR/test -set(TEST_LOCAL_PAYLOAD_SERVICE_START_SCRIPT local_${TEST_PAYLOAD_SERVICE}_start.sh) -copy_to_builddir( - ${PROJECT_SOURCE_DIR}/test/payload_tests/${TEST_LOCAL_PAYLOAD_SERVICE_START_SCRIPT} - ${PROJECT_BINARY_DIR}/test/${TEST_LOCAL_PAYLOAD_SERVICE_START_SCRIPT} - ${TEST_PAYLOAD_SERVICE} -) + # Copy bashscript to start service into $BUILDDIR/test + set(TEST_LOCAL_PAYLOAD_SERVICE_START_SCRIPT local_${TEST_PAYLOAD_SERVICE}_start.sh) + copy_to_builddir( + ${PROJECT_SOURCE_DIR}/test/payload_tests/${TEST_LOCAL_PAYLOAD_SERVICE_START_SCRIPT} + ${PROJECT_BINARY_DIR}/test/${TEST_LOCAL_PAYLOAD_SERVICE_START_SCRIPT} + ${TEST_PAYLOAD_SERVICE} + ) -set(TEST_PAYLOAD_CLIENT payload_test_client) + set(TEST_PAYLOAD_CLIENT payload_test_client) + add_executable(${TEST_PAYLOAD_CLIENT} + payload_tests/${TEST_PAYLOAD_CLIENT}.cpp + payload_tests/stopwatch.cpp + ) + target_link_libraries(${TEST_PAYLOAD_CLIENT} + vsomeip + ${Boost_LIBRARIES} + ${DL_LIBRARY} + ${TEST_LINK_LIBRARIES} + ) -add_executable(${TEST_PAYLOAD_CLIENT} - payload_tests/${TEST_PAYLOAD_CLIENT}.cpp - payload_tests/stopwatch.cpp -) -target_link_libraries(${TEST_PAYLOAD_CLIENT} - vsomeip - ${Boost_LIBRARIES} - ${DL_LIBRARY} - ${TEST_LINK_LIBRARIES} -) + # Copy config file for client into $BUILDDIR/test + set(TEST_LOCAL_PAYLOAD_CLIENT_CONFIG_FILE local_${TEST_PAYLOAD_CLIENT}.json) + copy_to_builddir( + ${PROJECT_SOURCE_DIR}/test/payload_tests/${TEST_LOCAL_PAYLOAD_CLIENT_CONFIG_FILE} + ${PROJECT_BINARY_DIR}/test/${TEST_LOCAL_PAYLOAD_CLIENT_CONFIG_FILE} + ${TEST_PAYLOAD_CLIENT} + ) -# Copy config file for client into $BUILDDIR/test -set(TEST_LOCAL_PAYLOAD_CLIENT_CONFIG_FILE local_${TEST_PAYLOAD_CLIENT}.json) -copy_to_builddir( - ${PROJECT_SOURCE_DIR}/test/payload_tests/${TEST_LOCAL_PAYLOAD_CLIENT_CONFIG_FILE} - ${PROJECT_BINARY_DIR}/test/${TEST_LOCAL_PAYLOAD_CLIENT_CONFIG_FILE} - ${TEST_PAYLOAD_CLIENT} -) + # Copy bashscript to start client into $BUILDDIR/test + set(TEST_LOCAL_PAYLOAD_CLIENT_START_SCRIPT local_${TEST_PAYLOAD_CLIENT}_start.sh) + copy_to_builddir( + ${PROJECT_SOURCE_DIR}/test/payload_tests/${TEST_LOCAL_PAYLOAD_CLIENT_START_SCRIPT} + ${PROJECT_BINARY_DIR}/test/${TEST_LOCAL_PAYLOAD_CLIENT_START_SCRIPT} + ${TEST_PAYLOAD_CLIENT} + ) -# Copy bashscript to start client into $BUILDDIR/test -set(TEST_LOCAL_PAYLOAD_CLIENT_START_SCRIPT local_${TEST_PAYLOAD_CLIENT}_start.sh) -copy_to_builddir( - ${PROJECT_SOURCE_DIR}/test/payload_tests/${TEST_LOCAL_PAYLOAD_CLIENT_START_SCRIPT} - ${PROJECT_BINARY_DIR}/test/${TEST_LOCAL_PAYLOAD_CLIENT_START_SCRIPT} - ${TEST_PAYLOAD_CLIENT} -) + # Copy bashscript to start client and server $BUILDDIR/test + set(TEST_LOCAL_PAYLOAD_STARTER local_payload_test_starter.sh) + copy_to_builddir(${PROJECT_SOURCE_DIR}/test/payload_tests/${TEST_LOCAL_PAYLOAD_STARTER} + ${PROJECT_BINARY_DIR}/test/${TEST_LOCAL_PAYLOAD_STARTER} + ${TEST_PAYLOAD_CLIENT} + ) -# Copy bashscript to start client and server $BUILDDIR/test -set(TEST_LOCAL_PAYLOAD_STARTER local_payload_test_starter.sh) -copy_to_builddir(${PROJECT_SOURCE_DIR}/test/payload_tests/${TEST_LOCAL_PAYLOAD_STARTER} - ${PROJECT_BINARY_DIR}/test/${TEST_LOCAL_PAYLOAD_STARTER} - ${TEST_PAYLOAD_CLIENT} -) + ############################################################################## + set(TEST_EXTERNAL_LOCAL_PAYLOAD_NAME external_local_payload_test) + set(TEST_EXTERNAL_LOCAL_PAYLOAD_SERVICE external_local_payload_test_service) + + # Copy config file for service into $BUILDDIR/test + set(TEST_EXTERNAL_LOCAL_PAYLOAD_SERVICE_CONFIG_FILE ${TEST_EXTERNAL_LOCAL_PAYLOAD_SERVICE}.json) + configure_file( + ${PROJECT_SOURCE_DIR}/test/payload_tests/conf/${TEST_EXTERNAL_LOCAL_PAYLOAD_SERVICE_CONFIG_FILE}.in + ${PROJECT_SOURCE_DIR}/test/payload_tests/${TEST_EXTERNAL_LOCAL_PAYLOAD_SERVICE_CONFIG_FILE} + @ONLY) + copy_to_builddir( + ${PROJECT_SOURCE_DIR}/test/payload_tests/${TEST_EXTERNAL_LOCAL_PAYLOAD_SERVICE_CONFIG_FILE} + ${PROJECT_BINARY_DIR}/test/${TEST_EXTERNAL_LOCAL_PAYLOAD_SERVICE_CONFIG_FILE} + ${TEST_PAYLOAD_SERVICE} + ) -############################################################################## -set(TEST_EXTERNAL_LOCAL_PAYLOAD_NAME external_local_payload_test) + # Copy bashscript to start service into $BUILDDIR/test + set(TEST_EXTERNAL_LOCAL_PAYLOAD_SERVICE_START_SCRIPT ${TEST_EXTERNAL_LOCAL_PAYLOAD_SERVICE}_start.sh) + copy_to_builddir( + ${PROJECT_SOURCE_DIR}/test/payload_tests/${TEST_EXTERNAL_LOCAL_PAYLOAD_SERVICE_START_SCRIPT} + ${PROJECT_BINARY_DIR}/test/${TEST_EXTERNAL_LOCAL_PAYLOAD_SERVICE_START_SCRIPT} + ${TEST_PAYLOAD_SERVICE} + ) -set(TEST_EXTERNAL_LOCAL_PAYLOAD_SERVICE external_local_payload_test_service) + set(TEST_EXTERNAL_LOCAL_PAYLOAD_CLIENT_LOCAL external_local_payload_test_client_local) + + # Copy config file for client into $BUILDDIR/test + set(TEST_EXTERNAL_LOCAL_PAYLOAD_CLIENT_CONFIG_FILE ${TEST_EXTERNAL_LOCAL_PAYLOAD_CLIENT_LOCAL}.json) + configure_file( + ${PROJECT_SOURCE_DIR}/test/payload_tests/conf/${TEST_EXTERNAL_LOCAL_PAYLOAD_CLIENT_CONFIG_FILE}.in + ${PROJECT_SOURCE_DIR}/test/payload_tests/${TEST_EXTERNAL_LOCAL_PAYLOAD_CLIENT_CONFIG_FILE} + @ONLY) + copy_to_builddir( + ${PROJECT_SOURCE_DIR}/test/payload_tests/${TEST_EXTERNAL_LOCAL_PAYLOAD_CLIENT_CONFIG_FILE} + ${PROJECT_BINARY_DIR}/test/${TEST_EXTERNAL_LOCAL_PAYLOAD_CLIENT_CONFIG_FILE} + ${TEST_PAYLOAD_CLIENT} + ) -# Copy config file for service into $BUILDDIR/test -set(TEST_EXTERNAL_LOCAL_PAYLOAD_SERVICE_CONFIG_FILE ${TEST_EXTERNAL_LOCAL_PAYLOAD_SERVICE}.json) -copy_to_builddir( - ${PROJECT_SOURCE_DIR}/test/payload_tests/${TEST_EXTERNAL_LOCAL_PAYLOAD_SERVICE_CONFIG_FILE} - ${PROJECT_BINARY_DIR}/test/${TEST_EXTERNAL_LOCAL_PAYLOAD_SERVICE_CONFIG_FILE} - ${TEST_PAYLOAD_SERVICE} -) + # Copy bashscript to start client into $BUILDDIR/test + set(TEST_EXTERNAL_LOCAL_PAYLOAD_CLIENT_LOCAL_START_SCRIPT ${TEST_EXTERNAL_LOCAL_PAYLOAD_CLIENT_LOCAL}_start.sh) + copy_to_builddir( + ${PROJECT_SOURCE_DIR}/test/payload_tests/${TEST_EXTERNAL_LOCAL_PAYLOAD_CLIENT_LOCAL_START_SCRIPT} + ${PROJECT_BINARY_DIR}/test/${TEST_EXTERNAL_LOCAL_PAYLOAD_CLIENT_LOCAL_START_SCRIPT} + ${TEST_PAYLOAD_CLIENT} + ) -# Copy bashscript to start service into $BUILDDIR/test -set(TEST_EXTERNAL_LOCAL_PAYLOAD_SERVICE_START_SCRIPT ${TEST_EXTERNAL_LOCAL_PAYLOAD_SERVICE}_start.sh) -copy_to_builddir( - ${PROJECT_SOURCE_DIR}/test/payload_tests/${TEST_EXTERNAL_LOCAL_PAYLOAD_SERVICE_START_SCRIPT} - ${PROJECT_BINARY_DIR}/test/${TEST_EXTERNAL_LOCAL_PAYLOAD_SERVICE_START_SCRIPT} - ${TEST_PAYLOAD_SERVICE} -) + # Copy bashscript to start client and server $BUILDDIR/test + set(TEST_EXTERNAL_LOCAL_PAYLOAD_CLIENT_LOCAL_NAME external_local_payload_test_client_local) + set(TEST_EXTERNAL_LOCAL_PAYLOAD_CLIENT_LOCAL_STARTER ${TEST_EXTERNAL_LOCAL_PAYLOAD_CLIENT_LOCAL_NAME}_starter.sh) + copy_to_builddir(${PROJECT_SOURCE_DIR}/test/payload_tests/${TEST_EXTERNAL_LOCAL_PAYLOAD_CLIENT_LOCAL_STARTER} + ${PROJECT_BINARY_DIR}/test/${TEST_EXTERNAL_LOCAL_PAYLOAD_CLIENT_LOCAL_STARTER} + ${TEST_PAYLOAD_CLIENT} + ) + ############################################################################## + set(TEST_EXTERNAL_LOCAL_PAYLOAD_CLIENT_EXTERNAL_NAME external_local_payload_test_client_external) + set(TEST_EXTERNAL_LOCAL_PAYLOAD_CLIENT_EXTERNAL external_local_payload_test_client_external) + + # Copy config file for client into $BUILDDIR/test + set(TEST_EXTERNAL_LOCAL_PAYLOAD_CLIENT_EXTERNAL_CONFIG_FILE ${TEST_EXTERNAL_LOCAL_PAYLOAD_CLIENT_EXTERNAL}.json) + configure_file( + ${PROJECT_SOURCE_DIR}/test/payload_tests/conf/${TEST_EXTERNAL_LOCAL_PAYLOAD_CLIENT_EXTERNAL_CONFIG_FILE}.in + ${PROJECT_SOURCE_DIR}/test/payload_tests/${TEST_EXTERNAL_LOCAL_PAYLOAD_CLIENT_EXTERNAL_CONFIG_FILE} + @ONLY) + copy_to_builddir( + ${PROJECT_SOURCE_DIR}/test/payload_tests/${TEST_EXTERNAL_LOCAL_PAYLOAD_CLIENT_EXTERNAL_CONFIG_FILE} + ${PROJECT_BINARY_DIR}/test/${TEST_EXTERNAL_LOCAL_PAYLOAD_CLIENT_EXTERNAL_CONFIG_FILE} + ${TEST_PAYLOAD_CLIENT} + ) -set(TEST_EXTERNAL_LOCAL_PAYLOAD_CLIENT_LOCAL external_local_payload_test_client_local) + # Copy bashscript to start client into $BUILDDIR/test + set(TEST_EXTERNAL_LOCAL_PAYLOAD_CLIENT_EXTERNAL_START_SCRIPT ${TEST_EXTERNAL_LOCAL_PAYLOAD_CLIENT_EXTERNAL}_start.sh) + copy_to_builddir( + ${PROJECT_SOURCE_DIR}/test/payload_tests/${TEST_EXTERNAL_LOCAL_PAYLOAD_CLIENT_EXTERNAL_START_SCRIPT} + ${PROJECT_BINARY_DIR}/test/${TEST_EXTERNAL_LOCAL_PAYLOAD_CLIENT_EXTERNAL_START_SCRIPT} + ${TEST_PAYLOAD_CLIENT} + ) -# Copy config file for client into $BUILDDIR/test -set(TEST_EXTERNAL_LOCAL_PAYLOAD_CLIENT_CONFIG_FILE ${TEST_EXTERNAL_LOCAL_PAYLOAD_CLIENT_LOCAL}.json) -copy_to_builddir( - ${PROJECT_SOURCE_DIR}/test/payload_tests/${TEST_EXTERNAL_LOCAL_PAYLOAD_CLIENT_CONFIG_FILE} - ${PROJECT_BINARY_DIR}/test/${TEST_EXTERNAL_LOCAL_PAYLOAD_CLIENT_CONFIG_FILE} - ${TEST_PAYLOAD_CLIENT} -) + set(TEST_EXTERNAL_LOCAL_PAYLOAD_SERVICE_CLIENT_EXTERNAL external_local_payload_test_service_client_external) -# Copy bashscript to start client into $BUILDDIR/test -set(TEST_EXTERNAL_LOCAL_PAYLOAD_CLIENT_LOCAL_START_SCRIPT ${TEST_EXTERNAL_LOCAL_PAYLOAD_CLIENT_LOCAL}_start.sh) -copy_to_builddir( - ${PROJECT_SOURCE_DIR}/test/payload_tests/${TEST_EXTERNAL_LOCAL_PAYLOAD_CLIENT_LOCAL_START_SCRIPT} - ${PROJECT_BINARY_DIR}/test/${TEST_EXTERNAL_LOCAL_PAYLOAD_CLIENT_LOCAL_START_SCRIPT} - ${TEST_PAYLOAD_CLIENT} -) + # Copy bashscript to start service into $BUILDDIR/test + set(TEST_EXTERNAL_LOCAL_PAYLOAD_SERVICE_CLIENTT_EXTERNAL_START_SCRIPT ${TEST_EXTERNAL_LOCAL_PAYLOAD_SERVICE_CLIENT_EXTERNAL}_start.sh) + copy_to_builddir( + ${PROJECT_SOURCE_DIR}/test/payload_tests/${TEST_EXTERNAL_LOCAL_PAYLOAD_SERVICE_CLIENTT_EXTERNAL_START_SCRIPT} + ${PROJECT_BINARY_DIR}/test/${TEST_EXTERNAL_LOCAL_PAYLOAD_SERVICE_CLIENTT_EXTERNAL_START_SCRIPT} + ${TEST_PAYLOAD_SERVICE} + ) -# Copy bashscript to start client and server $BUILDDIR/test -set(TEST_EXTERNAL_LOCAL_PAYLOAD_CLIENT_LOCAL_NAME external_local_payload_test_client_local) + # Copy bashscript to start client and server $BUILDDIR/test + set(TEST_EXTERNAL_LOCAL_PAYLOAD_CLIENT_EXTERNAL_STARTER ${TEST_EXTERNAL_LOCAL_PAYLOAD_CLIENT_EXTERNAL_NAME}_starter.sh) + copy_to_builddir(${PROJECT_SOURCE_DIR}/test/payload_tests/${TEST_EXTERNAL_LOCAL_PAYLOAD_CLIENT_EXTERNAL_STARTER} + ${PROJECT_BINARY_DIR}/test/${TEST_EXTERNAL_LOCAL_PAYLOAD_CLIENT_EXTERNAL_STARTER} + ${TEST_PAYLOAD_CLIENT} + ) -set(TEST_EXTERNAL_LOCAL_PAYLOAD_CLIENT_LOCAL_STARTER ${TEST_EXTERNAL_LOCAL_PAYLOAD_CLIENT_LOCAL_NAME}_starter.sh) -copy_to_builddir(${PROJECT_SOURCE_DIR}/test/payload_tests/${TEST_EXTERNAL_LOCAL_PAYLOAD_CLIENT_LOCAL_STARTER} - ${PROJECT_BINARY_DIR}/test/${TEST_EXTERNAL_LOCAL_PAYLOAD_CLIENT_LOCAL_STARTER} - ${TEST_PAYLOAD_CLIENT} -) + ############################################################################## + # Copy bashscript to start client and server $BUILDDIR/test + set(TEST_EXTERNAL_LOCAL_PAYLOAD_CLIENT_LOCAL_AND_EXTERNAL_NAME external_local_payload_test_client_local_and_external) + set(TEST_EXTERNAL_LOCAL_PAYLOAD_CLIENT_LOCAL_AND_EXTERNAL_STARTER ${TEST_EXTERNAL_LOCAL_PAYLOAD_CLIENT_LOCAL_AND_EXTERNAL_NAME}_starter.sh) + copy_to_builddir(${PROJECT_SOURCE_DIR}/test/payload_tests/${TEST_EXTERNAL_LOCAL_PAYLOAD_CLIENT_LOCAL_AND_EXTERNAL_STARTER} + ${PROJECT_BINARY_DIR}/test/${TEST_EXTERNAL_LOCAL_PAYLOAD_CLIENT_LOCAL_AND_EXTERNAL_STARTER} + ${TEST_PAYLOAD_CLIENT} + ) +endif() ############################################################################## +# big_payload_test +############################################################################## +if(NOT ${TESTS_BAT}) + set(TEST_BIG_PAYLOAD_NAME big_payload_test) + + set(TEST_BIG_PAYLOAD_SERVICE big_payload_test_service) + add_executable(${TEST_BIG_PAYLOAD_SERVICE} big_payload_tests/${TEST_BIG_PAYLOAD_SERVICE}.cpp) + target_link_libraries(${TEST_BIG_PAYLOAD_SERVICE} + vsomeip + ${Boost_LIBRARIES} + ${DL_LIBRARY} + ${TEST_LINK_LIBRARIES} + ) -set(TEST_EXTERNAL_LOCAL_PAYLOAD_CLIENT_EXTERNAL_NAME external_local_payload_test_client_external) + set(TEST_BIG_PAYLOAD_CLIENT big_payload_test_client) + add_executable(${TEST_BIG_PAYLOAD_CLIENT} big_payload_tests/${TEST_BIG_PAYLOAD_CLIENT}.cpp) + target_link_libraries(${TEST_BIG_PAYLOAD_CLIENT} + vsomeip + ${Boost_LIBRARIES} + ${DL_LIBRARY} + ${TEST_LINK_LIBRARIES} + ) -set(TEST_EXTERNAL_LOCAL_PAYLOAD_CLIENT_EXTERNAL external_local_payload_test_client_external) + # Copy config file for client and service into $BUILDDIR/test + set(TEST_LOCAL_BIG_PAYLOAD_CONFIG_FILE ${TEST_BIG_PAYLOAD_NAME}_local.json) + copy_to_builddir( + ${PROJECT_SOURCE_DIR}/test/big_payload_tests/${TEST_LOCAL_BIG_PAYLOAD_CONFIG_FILE} + ${PROJECT_BINARY_DIR}/test/${TEST_LOCAL_BIG_PAYLOAD_CONFIG_FILE} + ${TEST_BIG_PAYLOAD_SERVICE} + ) -# Copy config file for client into $BUILDDIR/test -set(TEST_EXTERNAL_LOCAL_PAYLOAD_CLIENT_EXTERNAL_CONFIG_FILE ${TEST_EXTERNAL_LOCAL_PAYLOAD_CLIENT_EXTERNAL}.json) -copy_to_builddir( - ${PROJECT_SOURCE_DIR}/test/payload_tests/${TEST_EXTERNAL_LOCAL_PAYLOAD_CLIENT_EXTERNAL_CONFIG_FILE} - ${PROJECT_BINARY_DIR}/test/${TEST_EXTERNAL_LOCAL_PAYLOAD_CLIENT_EXTERNAL_CONFIG_FILE} - ${TEST_PAYLOAD_CLIENT} -) + # Copy config file for client and service into $BUILDDIR/test + set(TEST_EXTERNAL_BIG_PAYLOAD_CLIENT_CONFIG_FILE ${TEST_BIG_PAYLOAD_NAME}_tcp_client.json) + configure_file( + ${PROJECT_SOURCE_DIR}/test/big_payload_tests/conf/${TEST_EXTERNAL_BIG_PAYLOAD_CLIENT_CONFIG_FILE}.in + ${PROJECT_SOURCE_DIR}/test/big_payload_tests/${TEST_EXTERNAL_BIG_PAYLOAD_CLIENT_CONFIG_FILE} + @ONLY) + copy_to_builddir( + ${PROJECT_SOURCE_DIR}/test/big_payload_tests/${TEST_EXTERNAL_BIG_PAYLOAD_CLIENT_CONFIG_FILE} + ${PROJECT_BINARY_DIR}/test/${TEST_EXTERNAL_BIG_PAYLOAD_CLIENT_CONFIG_FILE} + ${TEST_BIG_PAYLOAD_CLIENT} + ) -# Copy bashscript to start client into $BUILDDIR/test -set(TEST_EXTERNAL_LOCAL_PAYLOAD_CLIENT_EXTERNAL_START_SCRIPT ${TEST_EXTERNAL_LOCAL_PAYLOAD_CLIENT_EXTERNAL}_start.sh) -copy_to_builddir( - ${PROJECT_SOURCE_DIR}/test/payload_tests/${TEST_EXTERNAL_LOCAL_PAYLOAD_CLIENT_EXTERNAL_START_SCRIPT} - ${PROJECT_BINARY_DIR}/test/${TEST_EXTERNAL_LOCAL_PAYLOAD_CLIENT_EXTERNAL_START_SCRIPT} - ${TEST_PAYLOAD_CLIENT} -) + # Copy config file for client and service into $BUILDDIR/test + set(TEST_EXTERNAL_BIG_PAYLOAD_SERVICE_CONFIG_FILE ${TEST_BIG_PAYLOAD_NAME}_tcp_service.json) + configure_file( + ${PROJECT_SOURCE_DIR}/test/big_payload_tests/conf/${TEST_EXTERNAL_BIG_PAYLOAD_SERVICE_CONFIG_FILE}.in + ${PROJECT_SOURCE_DIR}/test/big_payload_tests/${TEST_EXTERNAL_BIG_PAYLOAD_SERVICE_CONFIG_FILE} + @ONLY) + copy_to_builddir( + ${PROJECT_SOURCE_DIR}/test/big_payload_tests/${TEST_EXTERNAL_BIG_PAYLOAD_SERVICE_CONFIG_FILE} + ${PROJECT_BINARY_DIR}/test/${TEST_EXTERNAL_BIG_PAYLOAD_SERVICE_CONFIG_FILE} + ${TEST_BIG_PAYLOAD_SERVICE} + ) -set(TEST_EXTERNAL_LOCAL_PAYLOAD_SERVICE_CLIENT_EXTERNAL external_local_payload_test_service_client_external) + # Copy bashscript to start client local to $BUILDDIR/test + set(TEST_LOCAL_BIG_PAYLOAD_CLIENT_START_SCRIPT ${TEST_BIG_PAYLOAD_NAME}_client_local_start.sh) + copy_to_builddir(${PROJECT_SOURCE_DIR}/test/big_payload_tests/${TEST_LOCAL_BIG_PAYLOAD_CLIENT_START_SCRIPT} + ${PROJECT_BINARY_DIR}/test/${TEST_LOCAL_BIG_PAYLOAD_CLIENT_START_SCRIPT} + ${TEST_BIG_PAYLOAD_CLIENT} + ) -# Copy bashscript to start service into $BUILDDIR/test -set(TEST_EXTERNAL_LOCAL_PAYLOAD_SERVICE_CLIENTT_EXTERNAL_START_SCRIPT ${TEST_EXTERNAL_LOCAL_PAYLOAD_SERVICE_CLIENT_EXTERNAL}_start.sh) -copy_to_builddir( - ${PROJECT_SOURCE_DIR}/test/payload_tests/${TEST_EXTERNAL_LOCAL_PAYLOAD_SERVICE_CLIENTT_EXTERNAL_START_SCRIPT} - ${PROJECT_BINARY_DIR}/test/${TEST_EXTERNAL_LOCAL_PAYLOAD_SERVICE_CLIENTT_EXTERNAL_START_SCRIPT} - ${TEST_PAYLOAD_SERVICE} -) + # Copy bashscript to start service local to $BUILDDIR/test + set(TEST_LOCAL_BIG_PAYLOAD_SERVICE_START_SCRIPT ${TEST_BIG_PAYLOAD_NAME}_service_local_start.sh) + copy_to_builddir(${PROJECT_SOURCE_DIR}/test/big_payload_tests/${TEST_LOCAL_BIG_PAYLOAD_SERVICE_START_SCRIPT} + ${PROJECT_BINARY_DIR}/test/${TEST_LOCAL_BIG_PAYLOAD_SERVICE_START_SCRIPT} + ${TEST_BIG_PAYLOAD_SERVICE} + ) -# Copy bashscript to start client and server $BUILDDIR/test -set(TEST_EXTERNAL_LOCAL_PAYLOAD_CLIENT_EXTERNAL_STARTER ${TEST_EXTERNAL_LOCAL_PAYLOAD_CLIENT_EXTERNAL_NAME}_starter.sh) -copy_to_builddir(${PROJECT_SOURCE_DIR}/test/payload_tests/${TEST_EXTERNAL_LOCAL_PAYLOAD_CLIENT_EXTERNAL_STARTER} - ${PROJECT_BINARY_DIR}/test/${TEST_EXTERNAL_LOCAL_PAYLOAD_CLIENT_EXTERNAL_STARTER} - ${TEST_PAYLOAD_CLIENT} -) + # Copy bashscript to start client and server $BUILDDIR/test + set(TEST_LOCAL_BIG_PAYLOAD_NAME big_payload_test_local) + set(TEST_LOCAL_BIG_PAYLOAD_STARTER ${TEST_LOCAL_BIG_PAYLOAD_NAME}_starter.sh) + copy_to_builddir(${PROJECT_SOURCE_DIR}/test/big_payload_tests/${TEST_LOCAL_BIG_PAYLOAD_STARTER} + ${PROJECT_BINARY_DIR}/test/${TEST_LOCAL_BIG_PAYLOAD_STARTER} + ${TEST_BIG_PAYLOAD_SERVICE} + ) + + # Copy bashscript to start client for external test into $BUILDDIR/test + set(TEST_EXTERNAL_BIG_PAYLOAD_NAME big_payload_test_external) + set(TEST_EXTERNAL_BIG_PAYLOAD_STARTER ${TEST_EXTERNAL_BIG_PAYLOAD_NAME}_starter.sh) + copy_to_builddir(${PROJECT_SOURCE_DIR}/test/big_payload_tests/${TEST_EXTERNAL_BIG_PAYLOAD_STARTER} + ${PROJECT_BINARY_DIR}/test/${TEST_EXTERNAL_BIG_PAYLOAD_STARTER} + ${TEST_BIG_PAYLOAD_SERVICE} + ) + + # Copy bashscript to start server for external into $BUILDDIR/test + set(TEST_EXTERNAL_BIG_PAYLOAD_NAME big_payload_test_external) + set(TEST_EXTERNAL_BIG_PAYLOAD_SERVICE_START_SCRIPT ${TEST_BIG_PAYLOAD_NAME}_service_external_start.sh) + copy_to_builddir(${PROJECT_SOURCE_DIR}/test/big_payload_tests/${TEST_EXTERNAL_BIG_PAYLOAD_SERVICE_START_SCRIPT} + ${PROJECT_BINARY_DIR}/test/${TEST_EXTERNAL_BIG_PAYLOAD_SERVICE_START_SCRIPT} + ${TEST_BIG_PAYLOAD_SERVICE} + ) + # Copy bashscript to start client for external test into $BUILDDIR/test + set(TEST_EXTERNAL_BIG_PAYLOAD_CLIENT_START_SCRIPT ${TEST_BIG_PAYLOAD_NAME}_client_start.sh) + copy_to_builddir(${PROJECT_SOURCE_DIR}/test/big_payload_tests/${TEST_EXTERNAL_BIG_PAYLOAD_CLIENT_START_SCRIPT} + ${PROJECT_BINARY_DIR}/test/${TEST_EXTERNAL_BIG_PAYLOAD_CLIENT_START_SCRIPT} + ${TEST_BIG_PAYLOAD_CLIENT} + ) +endif() + +############################################################################## +# client id tests ############################################################################## +if(NOT ${TESTS_BAT}) + set(TEST_CLIENT_ID_NAME client_id_test) + set(TEST_CLIENT_ID_SERVICE ${TEST_CLIENT_ID_NAME}_service) + add_executable(${TEST_CLIENT_ID_SERVICE} client_id_tests/${TEST_CLIENT_ID_NAME}_service.cpp) + target_link_libraries(${TEST_CLIENT_ID_SERVICE} + vsomeip + ${Boost_LIBRARIES} + ${DL_LIBRARY} + ${TEST_LINK_LIBRARIES} + ) + + # Copy config files for test into $BUILDDIR/test + set(TEST_CLIENT_ID_DIFF_IDS_DIFF_PORTS_MASTER_CONFIG_FILE + ${TEST_CLIENT_ID_NAME}_diff_client_ids_diff_ports_master.json) + configure_file( + ${PROJECT_SOURCE_DIR}/test/client_id_tests/conf/${TEST_CLIENT_ID_DIFF_IDS_DIFF_PORTS_MASTER_CONFIG_FILE}.in + ${PROJECT_SOURCE_DIR}/test/client_id_tests/${TEST_CLIENT_ID_DIFF_IDS_DIFF_PORTS_MASTER_CONFIG_FILE} + @ONLY) + copy_to_builddir( + ${PROJECT_SOURCE_DIR}/test/client_id_tests/${TEST_CLIENT_ID_DIFF_IDS_DIFF_PORTS_MASTER_CONFIG_FILE} + ${PROJECT_BINARY_DIR}/test/${TEST_CLIENT_ID_DIFF_IDS_DIFF_PORTS_MASTER_CONFIG_FILE} + ${TEST_CLIENT_ID_SERVICE} + ) -# Copy bashscript to start client and server $BUILDDIR/test -set(TEST_EXTERNAL_LOCAL_PAYLOAD_CLIENT_LOCAL_AND_EXTERNAL_NAME external_local_payload_test_client_local_and_external) + set(TEST_CLIENT_ID_DIFF_IDS_DIFF_PORTS_SLAVE_CONFIG_FILE + ${TEST_CLIENT_ID_NAME}_diff_client_ids_diff_ports_slave.json) + configure_file( + ${PROJECT_SOURCE_DIR}/test/client_id_tests/conf/${TEST_CLIENT_ID_DIFF_IDS_DIFF_PORTS_SLAVE_CONFIG_FILE}.in + ${PROJECT_SOURCE_DIR}/test/client_id_tests/${TEST_CLIENT_ID_DIFF_IDS_DIFF_PORTS_SLAVE_CONFIG_FILE} + @ONLY) + copy_to_builddir( + ${PROJECT_SOURCE_DIR}/test/client_id_tests/${TEST_CLIENT_ID_DIFF_IDS_DIFF_PORTS_SLAVE_CONFIG_FILE} + ${PROJECT_BINARY_DIR}/test/${TEST_CLIENT_ID_DIFF_IDS_DIFF_PORTS_SLAVE_CONFIG_FILE} + ${TEST_CLIENT_ID_SERVICE} + ) -set(TEST_EXTERNAL_LOCAL_PAYLOAD_CLIENT_LOCAL_AND_EXTERNAL_STARTER ${TEST_EXTERNAL_LOCAL_PAYLOAD_CLIENT_LOCAL_AND_EXTERNAL_NAME}_starter.sh) -copy_to_builddir(${PROJECT_SOURCE_DIR}/test/payload_tests/${TEST_EXTERNAL_LOCAL_PAYLOAD_CLIENT_LOCAL_AND_EXTERNAL_STARTER} - ${PROJECT_BINARY_DIR}/test/${TEST_EXTERNAL_LOCAL_PAYLOAD_CLIENT_LOCAL_AND_EXTERNAL_STARTER} - ${TEST_PAYLOAD_CLIENT} -) + set(TEST_CLIENT_ID_DIFF_IDS_SAME_PORTS_MASTER_CONFIG_FILE + ${TEST_CLIENT_ID_NAME}_diff_client_ids_same_ports_master.json) + configure_file( + ${PROJECT_SOURCE_DIR}/test/client_id_tests/conf/${TEST_CLIENT_ID_DIFF_IDS_SAME_PORTS_MASTER_CONFIG_FILE}.in + ${PROJECT_SOURCE_DIR}/test/client_id_tests/${TEST_CLIENT_ID_DIFF_IDS_SAME_PORTS_MASTER_CONFIG_FILE} + @ONLY) + copy_to_builddir( + ${PROJECT_SOURCE_DIR}/test/client_id_tests/${TEST_CLIENT_ID_DIFF_IDS_SAME_PORTS_MASTER_CONFIG_FILE} + ${PROJECT_BINARY_DIR}/test/${TEST_CLIENT_ID_DIFF_IDS_SAME_PORTS_MASTER_CONFIG_FILE} + ${TEST_CLIENT_ID_SERVICE} + ) + + set(TEST_CLIENT_ID_DIFF_IDS_SAME_PORTS_SLAVE_CONFIG_FILE + ${TEST_CLIENT_ID_NAME}_diff_client_ids_same_ports_slave.json) + configure_file( + ${PROJECT_SOURCE_DIR}/test/client_id_tests/conf/${TEST_CLIENT_ID_DIFF_IDS_SAME_PORTS_SLAVE_CONFIG_FILE}.in + ${PROJECT_SOURCE_DIR}/test/client_id_tests/${TEST_CLIENT_ID_DIFF_IDS_SAME_PORTS_SLAVE_CONFIG_FILE} + @ONLY) + copy_to_builddir( + ${PROJECT_SOURCE_DIR}/test/client_id_tests/${TEST_CLIENT_ID_DIFF_IDS_SAME_PORTS_SLAVE_CONFIG_FILE} + ${PROJECT_BINARY_DIR}/test/${TEST_CLIENT_ID_DIFF_IDS_SAME_PORTS_SLAVE_CONFIG_FILE} + ${TEST_CLIENT_ID_SERVICE} + ) + + set(TEST_CLIENT_ID_SAME_IDS_SAME_PORTS_MASTER_CONFIG_FILE + ${TEST_CLIENT_ID_NAME}_same_client_ids_same_ports_master.json) + configure_file( + ${PROJECT_SOURCE_DIR}/test/client_id_tests/conf/${TEST_CLIENT_ID_SAME_IDS_SAME_PORTS_MASTER_CONFIG_FILE}.in + ${PROJECT_SOURCE_DIR}/test/client_id_tests/${TEST_CLIENT_ID_SAME_IDS_SAME_PORTS_MASTER_CONFIG_FILE} + @ONLY) + copy_to_builddir( + ${PROJECT_SOURCE_DIR}/test/client_id_tests/${TEST_CLIENT_ID_SAME_IDS_SAME_PORTS_MASTER_CONFIG_FILE} + ${PROJECT_BINARY_DIR}/test/${TEST_CLIENT_ID_SAME_IDS_SAME_PORTS_MASTER_CONFIG_FILE} + ${TEST_CLIENT_ID_SERVICE} + ) + + set(TEST_CLIENT_ID_SAME_IDS_SAME_PORTS_SLAVE_CONFIG_FILE + ${TEST_CLIENT_ID_NAME}_same_client_ids_same_ports_slave.json) + configure_file( + ${PROJECT_SOURCE_DIR}/test/client_id_tests/conf/${TEST_CLIENT_ID_SAME_IDS_SAME_PORTS_SLAVE_CONFIG_FILE}.in + ${PROJECT_SOURCE_DIR}/test/client_id_tests/${TEST_CLIENT_ID_SAME_IDS_SAME_PORTS_SLAVE_CONFIG_FILE} + @ONLY) + copy_to_builddir( + ${PROJECT_SOURCE_DIR}/test/client_id_tests/${TEST_CLIENT_ID_SAME_IDS_SAME_PORTS_SLAVE_CONFIG_FILE} + ${PROJECT_BINARY_DIR}/test/${TEST_CLIENT_ID_SAME_IDS_SAME_PORTS_SLAVE_CONFIG_FILE} + ${TEST_CLIENT_ID_SERVICE} + ) + + set(TEST_CLIENT_ID_SAME_IDS_DIFF_PORTS_MASTER_CONFIG_FILE + ${TEST_CLIENT_ID_NAME}_same_client_ids_diff_ports_master.json) + configure_file( + ${PROJECT_SOURCE_DIR}/test/client_id_tests/conf/${TEST_CLIENT_ID_SAME_IDS_DIFF_PORTS_MASTER_CONFIG_FILE}.in + ${PROJECT_SOURCE_DIR}/test/client_id_tests/${TEST_CLIENT_ID_SAME_IDS_DIFF_PORTS_MASTER_CONFIG_FILE} + @ONLY) + copy_to_builddir( + ${PROJECT_SOURCE_DIR}/test/client_id_tests/${TEST_CLIENT_ID_SAME_IDS_DIFF_PORTS_MASTER_CONFIG_FILE} + ${PROJECT_BINARY_DIR}/test/${TEST_CLIENT_ID_SAME_IDS_DIFF_PORTS_MASTER_CONFIG_FILE} + ${TEST_CLIENT_ID_SERVICE} + ) + + set(TEST_CLIENT_ID_SAME_IDS_DIFF_PORTS_SLAVE_CONFIG_FILE + ${TEST_CLIENT_ID_NAME}_same_client_ids_diff_ports_slave.json) + configure_file( + ${PROJECT_SOURCE_DIR}/test/client_id_tests/conf/${TEST_CLIENT_ID_SAME_IDS_DIFF_PORTS_SLAVE_CONFIG_FILE}.in + ${PROJECT_SOURCE_DIR}/test/client_id_tests/${TEST_CLIENT_ID_SAME_IDS_DIFF_PORTS_SLAVE_CONFIG_FILE} + @ONLY) + copy_to_builddir( + ${PROJECT_SOURCE_DIR}/test/client_id_tests/${TEST_CLIENT_ID_SAME_IDS_DIFF_PORTS_SLAVE_CONFIG_FILE} + ${PROJECT_BINARY_DIR}/test/${TEST_CLIENT_ID_SAME_IDS_DIFF_PORTS_SLAVE_CONFIG_FILE} + ${TEST_CLIENT_ID_SERVICE} + ) + + # copy starter scripts into builddir + set(TEST_CLIENT_ID_MASTER_STARTER ${TEST_CLIENT_ID_NAME}_master_starter.sh) + copy_to_builddir(${PROJECT_SOURCE_DIR}/test/client_id_tests/${TEST_CLIENT_ID_MASTER_STARTER} + ${PROJECT_BINARY_DIR}/test/${TEST_CLIENT_ID_MASTER_STARTER} + ${TEST_CLIENT_ID_SERVICE} + ) + set(TEST_CLIENT_ID_SLAVE_STARTER ${TEST_CLIENT_ID_NAME}_slave_starter.sh) + copy_to_builddir(${PROJECT_SOURCE_DIR}/test/client_id_tests/${TEST_CLIENT_ID_SLAVE_STARTER} + ${PROJECT_BINARY_DIR}/test/${TEST_CLIENT_ID_SLAVE_STARTER} + ${TEST_CLIENT_ID_SERVICE} + ) +endif() ############################################################################## # Add for every test a dependency to gtest ############################################################################## -add_dependencies(${TEST_CONFIGURATION} gtest) -add_dependencies(${TEST_MAGIC_COOKIES_CLIENT} gtest) -add_dependencies(${TEST_HEADER_FACTORY} gtest) -add_dependencies(${TEST_HEADER_FACTORY_CLIENT} gtest) -add_dependencies(${TEST_HEADER_FACTORY_SERVICE} gtest) -add_dependencies(${TEST_LOCAL_ROUTING_SERVICE} gtest) -add_dependencies(${TEST_LOCAL_ROUTING_CLIENT} gtest) -add_dependencies(${TEST_EXTERNAL_LOCAL_ROUTING_SERVICE} gtest) -add_dependencies(${TEST_PAYLOAD_SERVICE} gtest) -add_dependencies(${TEST_PAYLOAD_CLIENT} gtest) +if(NOT ${TESTS_BAT}) + add_dependencies(${TEST_CONFIGURATION} gtest) + add_dependencies(${TEST_APPLICATION} gtest) + add_dependencies(${TEST_MAGIC_COOKIES_CLIENT} gtest) + add_dependencies(${TEST_MAGIC_COOKIES_SERVICE} gtest) + add_dependencies(${TEST_HEADER_FACTORY} gtest) + add_dependencies(${TEST_HEADER_FACTORY_CLIENT} gtest) + add_dependencies(${TEST_HEADER_FACTORY_SERVICE} gtest) + add_dependencies(${TEST_LOCAL_ROUTING_SERVICE} gtest) + add_dependencies(${TEST_LOCAL_ROUTING_CLIENT} gtest) + add_dependencies(${TEST_EXTERNAL_LOCAL_ROUTING_SERVICE} gtest) + add_dependencies(${TEST_PAYLOAD_SERVICE} gtest) + add_dependencies(${TEST_PAYLOAD_CLIENT} gtest) + add_dependencies(${TEST_BIG_PAYLOAD_SERVICE} gtest) + add_dependencies(${TEST_BIG_PAYLOAD_CLIENT} gtest) + add_dependencies(${TEST_CLIENT_ID_SERVICE} gtest) +else() + add_dependencies(${TEST_LOCAL_ROUTING_SERVICE} gtest) + add_dependencies(${TEST_LOCAL_ROUTING_CLIENT} gtest) +endif() ############################################################################## # Add tests to the target build_tests ############################################################################## -add_dependencies(build_tests ${TEST_CONFIGURATION}) -add_dependencies(build_tests ${TEST_MAGIC_COOKIES_CLIENT}) -add_dependencies(build_tests ${TEST_HEADER_FACTORY}) -add_dependencies(build_tests ${TEST_HEADER_FACTORY_CLIENT}) -add_dependencies(build_tests ${TEST_HEADER_FACTORY_SERVICE}) -add_dependencies(build_tests ${TEST_LOCAL_ROUTING_SERVICE}) -add_dependencies(build_tests ${TEST_LOCAL_ROUTING_CLIENT}) -add_dependencies(build_tests ${TEST_EXTERNAL_LOCAL_ROUTING_SERVICE}) -add_dependencies(build_tests ${TEST_PAYLOAD_SERVICE}) -add_dependencies(build_tests ${TEST_PAYLOAD_CLIENT}) +if(NOT ${TESTS_BAT}) + add_dependencies(build_tests ${TEST_CONFIGURATION}) + add_dependencies(build_tests ${TEST_APPLICATION}) + add_dependencies(build_tests ${TEST_MAGIC_COOKIES_CLIENT}) + add_dependencies(build_tests ${TEST_MAGIC_COOKIES_SERVICE}) + add_dependencies(build_tests ${TEST_HEADER_FACTORY}) + add_dependencies(build_tests ${TEST_HEADER_FACTORY_CLIENT}) + add_dependencies(build_tests ${TEST_HEADER_FACTORY_SERVICE}) + add_dependencies(build_tests ${TEST_LOCAL_ROUTING_SERVICE}) + add_dependencies(build_tests ${TEST_LOCAL_ROUTING_CLIENT}) + add_dependencies(build_tests ${TEST_EXTERNAL_LOCAL_ROUTING_SERVICE}) + add_dependencies(build_tests ${TEST_PAYLOAD_SERVICE}) + add_dependencies(build_tests ${TEST_PAYLOAD_CLIENT}) + add_dependencies(build_tests ${TEST_BIG_PAYLOAD_SERVICE}) + add_dependencies(build_tests ${TEST_BIG_PAYLOAD_CLIENT}) + add_dependencies(build_tests ${TEST_CLIENT_ID_SERVICE}) +else() + add_dependencies(build_tests ${TEST_LOCAL_ROUTING_SERVICE}) + add_dependencies(build_tests ${TEST_LOCAL_ROUTING_CLIENT}) +endif() + + ############################################################################## # Add tests ############################################################################## -add_test(NAME ${TEST_CONFIGURATION} - COMMAND ${TEST_CONFIGURATION} --someip ${TEST_CONFIGURATION_CONFIG_FILE} -) +if(NOT ${TESTS_BAT}) + add_test(NAME ${TEST_CONFIGURATION} + COMMAND ${TEST_CONFIGURATION} --someip ${TEST_CONFIGURATION_CONFIG_FILE} + ) + add_test(NAME ${TEST_CONFIGURATION}_deprecated_config_file + COMMAND ${TEST_CONFIGURATION} --someip ${TEST_CONFIGURATION_DEPRECATED_CONFIG_FILE} + ) -add_test(NAME ${TEST_MAGIC_COOKIES_NAME} - COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_MAGIC_COOKIES_STARTER} -) -set_tests_properties(${TEST_MAGIC_COOKIES_NAME} PROPERTIES TIMEOUT 60) + # application test + add_test(NAME ${TEST_APPLICATION} + COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_APPLICATION_STARTER} + ) + set_tests_properties(${TEST_APPLICATION} PROPERTIES TIMEOUT 20) -# Header/Factory tets -add_test(NAME ${TEST_HEADER_FACTORY_NAME} COMMAND ${TEST_HEADER_FACTORY}) -add_test(NAME ${TEST_HEADER_FACTORY_NAME}_send_receive - COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_HEADER_FACTORY_STARTER} -) + # magic cookies test + add_test(NAME ${TEST_MAGIC_COOKIES_NAME} + COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_MAGIC_COOKIES_STARTER} + ) + set_tests_properties(${TEST_MAGIC_COOKIES_NAME} PROPERTIES TIMEOUT 60) -# Routing tests -add_test(NAME ${TEST_LOCAL_ROUTING_NAME} - COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_LOCAL_ROUTING_STARTER} -) -add_test(NAME ${TEST_EXTERNAL_LOCAL_ROUTING_NAME} - COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_EXTERNAL_LOCAL_ROUTING_STARTER} -) -set_tests_properties(${TEST_EXTERNAL_LOCAL_ROUTING_NAME} PROPERTIES TIMEOUT 60) + # Header/Factory tets + add_test(NAME ${TEST_HEADER_FACTORY_NAME} COMMAND ${TEST_HEADER_FACTORY}) + add_test(NAME ${TEST_HEADER_FACTORY_NAME}_send_receive + COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_HEADER_FACTORY_STARTER} + ) -# Payload tests -add_test(NAME ${TEST_LOCAL_PAYLOAD_NAME} - COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_LOCAL_PAYLOAD_STARTER} -) -add_test(NAME ${TEST_EXTERNAL_LOCAL_PAYLOAD_CLIENT_LOCAL_NAME} - COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_EXTERNAL_LOCAL_PAYLOAD_CLIENT_LOCAL_STARTER} -) -add_test(NAME ${TEST_EXTERNAL_LOCAL_PAYLOAD_CLIENT_EXTERNAL_NAME} - COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_EXTERNAL_LOCAL_PAYLOAD_CLIENT_EXTERNAL_STARTER} -) -set_tests_properties(${TEST_EXTERNAL_LOCAL_PAYLOAD_CLIENT_EXTERNAL_NAME} PROPERTIES TIMEOUT 240) -add_test(NAME ${TEST_EXTERNAL_LOCAL_PAYLOAD_CLIENT_LOCAL_AND_EXTERNAL_NAME} - COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_EXTERNAL_LOCAL_PAYLOAD_CLIENT_LOCAL_AND_EXTERNAL_STARTER} -) -set_tests_properties(${TEST_EXTERNAL_LOCAL_PAYLOAD_CLIENT_EXTERNAL_NAME} PROPERTIES TIMEOUT 240) + # Routing tests + add_test(NAME ${TEST_LOCAL_ROUTING_NAME} + COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_LOCAL_ROUTING_STARTER} + ) + + add_test(NAME ${TEST_EXTERNAL_LOCAL_ROUTING_NAME} + COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_EXTERNAL_LOCAL_ROUTING_STARTER} + ) + set_tests_properties(${TEST_EXTERNAL_LOCAL_ROUTING_NAME} PROPERTIES TIMEOUT 60) + + # Payload tests + add_test(NAME ${TEST_LOCAL_PAYLOAD_NAME} + COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_LOCAL_PAYLOAD_STARTER} + ) + add_test(NAME ${TEST_EXTERNAL_LOCAL_PAYLOAD_CLIENT_LOCAL_NAME} + COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_EXTERNAL_LOCAL_PAYLOAD_CLIENT_LOCAL_STARTER} + ) + add_test(NAME ${TEST_EXTERNAL_LOCAL_PAYLOAD_CLIENT_EXTERNAL_NAME} + COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_EXTERNAL_LOCAL_PAYLOAD_CLIENT_EXTERNAL_STARTER} + ) + set_tests_properties(${TEST_EXTERNAL_LOCAL_PAYLOAD_CLIENT_EXTERNAL_NAME} PROPERTIES TIMEOUT 240) + add_test(NAME ${TEST_EXTERNAL_LOCAL_PAYLOAD_CLIENT_LOCAL_AND_EXTERNAL_NAME} + COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_EXTERNAL_LOCAL_PAYLOAD_CLIENT_LOCAL_AND_EXTERNAL_STARTER} + ) + set_tests_properties(${TEST_EXTERNAL_LOCAL_PAYLOAD_CLIENT_EXTERNAL_NAME} PROPERTIES TIMEOUT 240) + + # big payload tests + add_test(NAME ${TEST_LOCAL_BIG_PAYLOAD_NAME} + COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_LOCAL_BIG_PAYLOAD_STARTER} + ) + set_tests_properties(${TEST_LOCAL_BIG_PAYLOAD_NAME} PROPERTIES TIMEOUT 60) + add_test(NAME ${TEST_EXTERNAL_BIG_PAYLOAD_NAME} + COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_EXTERNAL_BIG_PAYLOAD_STARTER} + ) + set_tests_properties(${TEST_EXTERNAL_BIG_PAYLOAD_NAME} PROPERTIES TIMEOUT 60) + + # client id tests + add_test(NAME ${TEST_CLIENT_ID_NAME}_diff_client_ids_diff_ports + COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_CLIENT_ID_MASTER_STARTER} ${TEST_CLIENT_ID_DIFF_IDS_DIFF_PORTS_MASTER_CONFIG_FILE}) + set_tests_properties(${TEST_CLIENT_ID_NAME}_diff_client_ids_diff_ports PROPERTIES TIMEOUT 60) + add_test(NAME ${TEST_CLIENT_ID_NAME}_diff_client_ids_same_ports + COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_CLIENT_ID_MASTER_STARTER} ${TEST_CLIENT_ID_DIFF_IDS_SAME_PORTS_MASTER_CONFIG_FILE}) + set_tests_properties(${TEST_CLIENT_ID_NAME}_diff_client_ids_same_ports PROPERTIES TIMEOUT 60) +else() + # Routing tests + add_test(NAME ${TEST_LOCAL_ROUTING_NAME} + COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_LOCAL_ROUTING_STARTER} + ) +endif() diff --git a/test/application_tests/application_test.cpp b/test/application_tests/application_test.cpp new file mode 100644 index 0000000..d52e0a1 --- /dev/null +++ b/test/application_tests/application_test.cpp @@ -0,0 +1,174 @@ +// Copyright (C) 2015 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 +#include + +#include + +#include + +#include "someip_test_globals.hpp" + +using namespace vsomeip; + +class someip_application_test: public ::testing::Test { + +protected: + void SetUp() { + app_ = runtime::get()->create_application("application_test"); + app_->init(); + } + + std::shared_ptr app_; +}; + +/** + * @test Start and stop application + */ +TEST_F(someip_application_test, start_stop_application) +{ + std::thread t([&](){ + app_->start(); + }); + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + app_->stop(); + t.join(); +} + +/** + * @test Start and stop application multiple times + */ +TEST_F(someip_application_test, start_stop_application_multiple) +{ + for (int i = 0; i < 10; ++i) { + std::thread t([&]() { + app_->start(); + }); + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + app_->stop(); + t.join(); + } +} + +/** + * @test Try to start an already running application again + */ +TEST_F(someip_application_test, restart_without_stopping) +{ + std::thread t([&]() { + app_->start(); + + }); + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + VSOMEIP_WARNING << "An error message should appear now"; + // should print error + app_->start(); + app_->stop(); + t.join(); +} + +/** + * @test Try to stop a running application twice + */ +TEST_F(someip_application_test, stop_application_twice) +{ + std::thread t([&]() { + app_->start(); + + }); + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + + app_->stop(); + t.join(); + app_->stop(); +} + +class someip_application_shutdown_test: public ::testing::Test { + +protected: + void SetUp() { + is_registered_ = false; + + app_ = runtime::get()->create_application("application_test"); + app_->init(); + + app_->register_message_handler(vsomeip_test::TEST_SERVICE_SERVICE_ID, + vsomeip_test::TEST_SERVICE_INSTANCE_ID, + vsomeip_test::TEST_SERVICE_METHOD_ID_SHUTDOWN, + std::bind(&someip_application_shutdown_test::on_message_shutdown, this, + std::placeholders::_1)); + + app_->register_state_handler( + std::bind(&someip_application_shutdown_test::on_state, this, + std::placeholders::_1)); + shutdown_thread_ = std::thread(&someip_application_shutdown_test::send_shutdown_message, this); + + app_->start(); + } + + void TearDown() { + shutdown_thread_.join(); + app_->stop(); + } + + void on_state(vsomeip::state_type_e _state) { + if(_state == vsomeip::state_type_e::ST_REGISTERED) + { + app_->offer_service(vsomeip_test::TEST_SERVICE_SERVICE_ID, vsomeip_test::TEST_SERVICE_INSTANCE_ID); + std::lock_guard its_lock(mutex_); + is_registered_ = true; + cv_.notify_one(); + } + } + + void on_message_shutdown(const std::shared_ptr& _request) + { + (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_->stop(); + } + + void send_shutdown_message() { + std::unique_lock its_lock(mutex_); + while(!is_registered_) { + cv_.wait(its_lock); + } + std::shared_ptr r = runtime::get()->create_request(); + r->set_service(vsomeip_test::TEST_SERVICE_SERVICE_ID); + r->set_instance(vsomeip_test::TEST_SERVICE_INSTANCE_ID); + r->set_method(vsomeip_test::TEST_SERVICE_METHOD_ID_SHUTDOWN); + app_->send(r); + } + + bool is_registered_; + std::shared_ptr app_; + std::condition_variable cv_; + std::mutex mutex_; + std::thread shutdown_thread_; +}; + +/** + * @test Stop the application through a method invoked from a dispatcher thread + */ +TEST_F(someip_application_shutdown_test, stop_application_from_dispatcher_thread) { + +} + +#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.json b/test/application_tests/application_test.json new file mode 100644 index 0000000..a50eb35 --- /dev/null +++ b/test/application_tests/application_test.json @@ -0,0 +1,45 @@ +{ + "unicast":"127.0.0.1", + "logging": + { + "level":"warning", + "console":"true", + "file": + { + "enable":"false", + "path":"/tmp/someip.log" + }, + "dlt":"false" + }, + "applications": + [ + { + "name":"application_test", + "id":"0x7788", + "num_dispatchers":"5" + } + ], + "services": + [ + { + "service":"0x1234", + "instance":"0x5678", + "reliable":"30503" + } + ], + "routing":"application_test", + "service-discovery": + { + "enable":"true", + "multicast":"224.0.0.1", + "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/test/application_tests/application_test_no_dispatch_threads.json b/test/application_tests/application_test_no_dispatch_threads.json new file mode 100644 index 0000000..d2f9569 --- /dev/null +++ b/test/application_tests/application_test_no_dispatch_threads.json @@ -0,0 +1,37 @@ +{ + "unicast":"127.0.0.1", + "logging": + { + "level":"warning", + "console":"true", + "file": + { + "enable":"false", + "path":"/tmp/someip.log" + }, + "dlt":"false" + }, + "applications": + [ + { + "name":"application_test", + "id":"0x7788" + } + ], + "services": + [ + { + "service":"0x1234", + "instance":"0x5678", + "reliable":"30503" + } + ], + "routing":"application_test", + "service-discovery": + { + "enable":"true", + "multicast":"224.0.0.1", + "port":"30490", + "protocol":"udp" + } +} diff --git a/test/application_tests/application_test_starter.sh b/test/application_tests/application_test_starter.sh new file mode 100755 index 0000000..2968393 --- /dev/null +++ b/test/application_tests/application_test_starter.sh @@ -0,0 +1,31 @@ +#!/bin/bash +# Copyright (C) 2015 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_no_dispatch_threads.json +./application_test + +if [ $? -ne 0 ] +then + ((FAIL+=1)) +fi + +export VSOMEIP_CONFIGURATION=application_test.json +./application_test + +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/big_payload_tests/big_payload_test_client.cpp b/test/big_payload_tests/big_payload_test_client.cpp new file mode 100644 index 0000000..4f96c1c --- /dev/null +++ b/test/big_payload_tests/big_payload_test_client.cpp @@ -0,0 +1,185 @@ +// Copyright (C) 2015 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 "big_payload_test_client.hpp" +#include "big_payload_test_globals.hpp" + +big_payload_test_client::big_payload_test_client(bool _use_tcp) : + app_(vsomeip::runtime::get()->create_application()), + request_(vsomeip::runtime::get()->create_request(_use_tcp)), + running_(true), + blocked_(false), + is_available_(false), + number_of_messages_to_send_(vsomeip_test::NUMBER_OF_MESSAGES_TO_SEND), + number_of_sent_messages_(0), + number_of_acknowledged_messages_(0), + sender_(std::bind(&big_payload_test_client::run, this)) +{ +} + +void big_payload_test_client::init() +{ + app_->init(); + + app_->register_state_handler( + std::bind(&big_payload_test_client::on_state, this, + std::placeholders::_1)); + + app_->register_message_handler(vsomeip::ANY_SERVICE, + vsomeip_test::TEST_SERVICE_INSTANCE_ID, vsomeip::ANY_METHOD, + std::bind(&big_payload_test_client::on_message, this, + std::placeholders::_1)); + + app_->register_availability_handler(vsomeip_test::TEST_SERVICE_SERVICE_ID, + vsomeip_test::TEST_SERVICE_INSTANCE_ID, + std::bind(&big_payload_test_client::on_availability, this, + std::placeholders::_1, std::placeholders::_2, + std::placeholders::_3)); +} + +void big_payload_test_client::start() +{ + VSOMEIP_INFO << "Starting..."; + app_->start(); +} + +void big_payload_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_->stop(); +} + +void big_payload_test_client::join_sender_thread(){ + sender_.join(); + + ASSERT_EQ(number_of_sent_messages_, number_of_acknowledged_messages_); +} + +void big_payload_test_client::on_state(vsomeip::state_type_e _state) +{ + if(_state == vsomeip::state_type_e::ST_REGISTERED) + { + app_->request_service(vsomeip_test::TEST_SERVICE_SERVICE_ID, + vsomeip_test::TEST_SERVICE_INSTANCE_ID, false); + } +} + +void big_payload_test_client::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."); + + if(vsomeip_test::TEST_SERVICE_SERVICE_ID == _service + && vsomeip_test::TEST_SERVICE_INSTANCE_ID == _instance) + { + if(is_available_ && !_is_available) + { + is_available_ = false; + } + else if(_is_available && !is_available_) + { + is_available_ = true; + send(); + } + } +} + +void big_payload_test_client::on_message(const std::shared_ptr& _response) +{ + VSOMEIP_INFO << "Received a response from Service [" << std::setw(4) + << std::setfill('0') << std::hex << _response->get_service() << "." + << std::setw(4) << std::setfill('0') << std::hex + << _response->get_instance() << "] to Client/Session [" + << std::setw(4) << std::setfill('0') << std::hex + << _response->get_client() << "/" << std::setw(4) + << std::setfill('0') << std::hex << _response->get_session() + << "] size: " << std::dec << _response->get_payload()->get_length(); + + ASSERT_EQ(_response->get_payload()->get_length(), big_payload_test::BIG_PAYLOAD_SIZE); + + bool check(true); + vsomeip::length_t len = _response->get_payload()->get_length(); + vsomeip::byte_t* datap = _response->get_payload()->get_data(); + for(unsigned int i = 0; i < len; ++i) { + check = check && datap[i] == big_payload_test::DATA_SERVICE_TO_CLIENT; + } + if(!check) { + GTEST_FATAL_FAILURE_("wrong data transmitted"); + } + number_of_acknowledged_messages_++; + send(); +} + +void big_payload_test_client::send() +{ + std::lock_guard its_lock(mutex_); + blocked_ = true; + condition_.notify_one(); +} + +void big_payload_test_client::run() +{ + std::unique_lock its_lock(mutex_); + while (!blocked_) + { + condition_.wait(its_lock); + } + blocked_ = false; + request_->set_service(vsomeip_test::TEST_SERVICE_SERVICE_ID); + request_->set_instance(vsomeip_test::TEST_SERVICE_INSTANCE_ID); + request_->set_method(vsomeip_test::TEST_SERVICE_METHOD_ID); + + std::shared_ptr< vsomeip::payload > its_payload = vsomeip::runtime::get()->create_payload(); + std::vector< vsomeip::byte_t > its_payload_data; + for (unsigned int i = 0; i < big_payload_test::BIG_PAYLOAD_SIZE; ++i) { + its_payload_data.push_back(big_payload_test::DATA_CLIENT_TO_SERVICE); + } + its_payload->set_data(its_payload_data); + request_->set_payload(its_payload); + + for (unsigned int i = 0; i < number_of_messages_to_send_; i++) + { + app_->send(request_, true); + VSOMEIP_INFO << "Client/Session [" << std::setw(4) << std::setfill('0') + << std::hex << request_->get_client() << "/" << std::setw(4) + << std::setfill('0') << std::hex << request_->get_session() + << "] sent a request to Service [" << std::setw(4) + << std::setfill('0') << std::hex << request_->get_service() + << "." << std::setw(4) << std::setfill('0') << std::hex + << request_->get_instance() << "]"; + number_of_sent_messages_++; + while(!blocked_) { + condition_.wait(its_lock); + } + blocked_ = false; + } + ASSERT_EQ(number_of_sent_messages_, number_of_acknowledged_messages_); + stop(); +} + +TEST(someip_big_payload_test, send_ten_messages_to_service) +{ + bool use_tcp = true; + big_payload_test_client test_client_(use_tcp); + test_client_.init(); + test_client_.start(); + test_client_.join_sender_thread(); +} + +#ifndef WIN32 +int main(int argc, char** argv) +{ + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} +#endif diff --git a/test/big_payload_tests/big_payload_test_client.hpp b/test/big_payload_tests/big_payload_test_client.hpp new file mode 100644 index 0000000..f1ee7c2 --- /dev/null +++ b/test/big_payload_tests/big_payload_test_client.hpp @@ -0,0 +1,49 @@ +// Copyright (C) 2015 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 BIGPAYLOADTESTCLIENT_HPP_ +#define BIGPAYLOADTESTCLIENT_HPP_ + +#include + +#include + +#include +#include +#include +#include + +#include "../someip_test_globals.hpp" + +class big_payload_test_client +{ +public: + big_payload_test_client(bool _use_tcp); + void init(); + void start(); + void stop(); + void join_sender_thread(); + void on_state(vsomeip::state_type_e _state); + void on_availability(vsomeip::service_t _service, + vsomeip::instance_t _instance, bool _is_available); + void on_message(const std::shared_ptr &_response); + void send(); + void run(); + +private: + std::shared_ptr app_; + std::shared_ptr request_; + std::mutex mutex_; + std::condition_variable condition_; + bool running_; + bool blocked_; + bool is_available_; + std::uint32_t number_of_messages_to_send_; + std::uint32_t number_of_sent_messages_; + std::uint32_t number_of_acknowledged_messages_; + std::thread sender_; +}; + +#endif /* BIGPAYLOADTESTCLIENT_HPP_ */ diff --git a/test/big_payload_tests/big_payload_test_client_local_start.sh b/test/big_payload_tests/big_payload_test_client_local_start.sh new file mode 100755 index 0000000..f834d78 --- /dev/null +++ b/test/big_payload_tests/big_payload_test_client_local_start.sh @@ -0,0 +1,10 @@ +#!/bin/bash +# Copyright (C) 2015 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/. + +# Start the client +export VSOMEIP_APPLICATION_NAME=big_payload_test_client +export VSOMEIP_CONFIGURATION=big_payload_test_local.json +./big_payload_test_client diff --git a/test/big_payload_tests/big_payload_test_client_start.sh b/test/big_payload_tests/big_payload_test_client_start.sh new file mode 100755 index 0000000..025b5bc --- /dev/null +++ b/test/big_payload_tests/big_payload_test_client_start.sh @@ -0,0 +1,10 @@ +#!/bin/bash +# Copyright (C) 2015 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/. + +# Start the client +export VSOMEIP_APPLICATION_NAME=big_payload_test_client +export VSOMEIP_CONFIGURATION=big_payload_test_tcp_client.json +./big_payload_test_client diff --git a/test/big_payload_tests/big_payload_test_external_starter.sh b/test/big_payload_tests/big_payload_test_external_starter.sh new file mode 100755 index 0000000..6550adc --- /dev/null +++ b/test/big_payload_tests/big_payload_test_external_starter.sh @@ -0,0 +1,48 @@ +#!/bin/bash +# Copyright (C) 2015 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 successfully. + +FAIL=0 + +# Start the client +export VSOMEIP_CONFIGURATION=big_payload_test_tcp_client.json +export VSOMEIP_APPLICATION_NAME=big_payload_test_client +./big_payload_test_client & + +cat < + +namespace big_payload_test { + constexpr std::uint32_t BIG_PAYLOAD_SIZE = 1024*600; + constexpr vsomeip::byte_t DATA_SERVICE_TO_CLIENT = 0xAA; + constexpr vsomeip::byte_t DATA_CLIENT_TO_SERVICE = 0xFF; +} + +#endif /* BIG_PAYLOAD_TEST_GLOBALS_HPP_ */ diff --git a/test/big_payload_tests/big_payload_test_local.json b/test/big_payload_tests/big_payload_test_local.json new file mode 100644 index 0000000..aa7b3ea --- /dev/null +++ b/test/big_payload_tests/big_payload_test_local.json @@ -0,0 +1,54 @@ +{ + "unicast":"127.0.0.1", + "logging": + { + "level":"debug", + "console":"true", + "file": + { + "enable":"false", + "path":"/tmp/vsomeip.log" + }, + "dlt":"false" + }, + "applications": + [ + { + "name":"big_payload_test_service", + "id":"0x1277" + }, + { + "name":"big_payload_test_client", + "id":"0x1344" + } + ], + "services": + [ + { + "service":"0x1234", + "instance":"0x5678" + } + ], + "payload-sizes": + [ + { + "unicast":"127.0.0.1", + "ports": + [ + { + "port":"30509", + "max-payload-size":"614400" + } + ] + } + ], + "routing":"big_payload_test_service", + "service-discovery": + { + "enable":"true", + "multicast":"224.244.224.245", + "port":"30490", + "protocol":"udp" + } +} + diff --git a/test/big_payload_tests/big_payload_test_local_starter.sh b/test/big_payload_tests/big_payload_test_local_starter.sh new file mode 100755 index 0000000..d32b6a0 --- /dev/null +++ b/test/big_payload_tests/big_payload_test_local_starter.sh @@ -0,0 +1,38 @@ +#!/bin/bash +# Copyright (C) 2015 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 successfully. + +FAIL=0 + +# Start the service +export VSOMEIP_APPLICATION_NAME=big_payload_test_service +export VSOMEIP_CONFIGURATION=big_payload_test_local.json +./big_payload_test_service & + +# Start the client +export VSOMEIP_APPLICATION_NAME=big_payload_test_client +./big_payload_test_client & + +# Wait until client and service are finished +for job in $(jobs -p) +do + # Fail gets incremented if either client or service exit + # with a non-zero exit code + wait $job || ((FAIL+=1)) +done + +# Check if client and server both exited successfully +if [ $FAIL -eq 0 ] +then + exit 0 +else + exit 1 +fi diff --git a/test/big_payload_tests/big_payload_test_service.cpp b/test/big_payload_tests/big_payload_test_service.cpp new file mode 100644 index 0000000..fecaf19 --- /dev/null +++ b/test/big_payload_tests/big_payload_test_service.cpp @@ -0,0 +1,163 @@ +// Copyright (C) 2015 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 "big_payload_test_service.hpp" + +#include "big_payload_test_globals.hpp" + +big_payload_test_service::big_payload_test_service() : + app_(vsomeip::runtime::get()->create_application()), + is_registered_(false), + blocked_(false), + number_of_received_messages_(0), + offer_thread_(std::bind(&big_payload_test_service::run, this)) +{ +} + +void big_payload_test_service::init() +{ + std::lock_guard its_lock(mutex_); + + app_->init(); + 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, + std::placeholders::_1)); + + app_->register_state_handler( + std::bind(&big_payload_test_service::on_state, this, + std::placeholders::_1)); +} + +void big_payload_test_service::start() +{ + VSOMEIP_INFO << "Starting..."; + app_->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_->stop(); +} + +void big_payload_test_service::join_offer_thread() +{ + offer_thread_.join(); +} + +void big_payload_test_service::offer() +{ + app_->offer_service(vsomeip_test::TEST_SERVICE_SERVICE_ID, vsomeip_test::TEST_SERVICE_INSTANCE_ID); +} + +void big_payload_test_service::stop_offer() +{ + app_->stop_offer_service(vsomeip_test::TEST_SERVICE_SERVICE_ID, vsomeip_test::TEST_SERVICE_INSTANCE_ID); +} + +void big_payload_test_service::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) + { + if(!is_registered_) + { + is_registered_ = true; + std::lock_guard its_lock(mutex_); + blocked_ = true; + // "start" the run method thread + condition_.notify_one(); + } + } + else + { + is_registered_ = false; + } +} + +void big_payload_test_service::on_message(const std::shared_ptr& _request) +{ + VSOMEIP_INFO << "Received a message with Client/Session [" << std::setw(4) + << std::setfill('0') << std::hex << _request->get_client() << "/" + << std::setw(4) << std::setfill('0') << std::hex + << _request->get_session() << "] size: " << std::dec + << _request->get_payload()->get_length(); + + ASSERT_EQ(_request->get_payload()->get_length(), big_payload_test::BIG_PAYLOAD_SIZE); + bool check(true); + vsomeip::length_t len = _request->get_payload()->get_length(); + vsomeip::byte_t* datap = _request->get_payload()->get_data(); + for(unsigned int i = 0; i < len; ++i) { + check = check && datap[i] == big_payload_test::DATA_CLIENT_TO_SERVICE; + } + if(!check) { + GTEST_FATAL_FAILURE_("wrong data transmitted"); + } + + number_of_received_messages_++; + + // send response + std::shared_ptr its_response = + vsomeip::runtime::get()->create_response(_request); + + std::shared_ptr its_payload = vsomeip::runtime::get() + ->create_payload(); + std::vector its_payload_data; + for (unsigned int i = 0; i < big_payload_test::BIG_PAYLOAD_SIZE; ++i) { + its_payload_data.push_back(big_payload_test::DATA_SERVICE_TO_CLIENT); + } + its_payload->set_data(its_payload_data); + its_response->set_payload(its_payload); + + app_->send(its_response, true); + + if(number_of_received_messages_ == vsomeip_test::NUMBER_OF_MESSAGES_TO_SEND) { + ASSERT_EQ(vsomeip_test::NUMBER_OF_MESSAGES_TO_SEND, number_of_received_messages_); + std::lock_guard its_lock(mutex_); + blocked_ = true; + condition_.notify_one(); + } +} + +void big_payload_test_service::run() +{ + std::unique_lock its_lock(mutex_); + while (!blocked_) { + condition_.wait(its_lock); + } + + offer(); + + // wait for shutdown + blocked_ = false; + while (!blocked_) { + condition_.wait(its_lock); + } + std::this_thread::sleep_for(std::chrono::seconds(3)); + app_->stop(); +} + +TEST(someip_big_payload_test, receive_ten_messages_and_send_reply) +{ + big_payload_test_service test_service; + test_service.init(); + test_service.start(); + test_service.join_offer_thread(); +} + +#ifndef WIN32 +int main(int argc, char** argv) +{ + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} +#endif diff --git a/test/big_payload_tests/big_payload_test_service.hpp b/test/big_payload_tests/big_payload_test_service.hpp new file mode 100644 index 0000000..9888f41 --- /dev/null +++ b/test/big_payload_tests/big_payload_test_service.hpp @@ -0,0 +1,43 @@ +// Copyright (C) 2015 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 BIGPAYLOADTESTSERVICE_HPP_ +#define BIGPAYLOADTESTSERVICE_HPP_ +#include + +#include + +#include +#include +#include +#include + +#include "../someip_test_globals.hpp" + +class big_payload_test_service +{ +public: + big_payload_test_service(); + void init(); + void start(); + void stop(); + void offer(); + void stop_offer(); + void join_offer_thread(); + void on_state(vsomeip::state_type_e _state); + void on_message(const std::shared_ptr &_request); + void run(); + +private: + std::shared_ptr app_; + bool is_registered_; + std::mutex mutex_; + std::condition_variable condition_; + bool blocked_; + std::uint32_t number_of_received_messages_; + std::thread offer_thread_; +}; + +#endif /* BIGPAYLOADTESTSERVICE_HPP_ */ diff --git a/test/big_payload_tests/big_payload_test_service_external_start.sh b/test/big_payload_tests/big_payload_test_service_external_start.sh new file mode 100755 index 0000000..361f106 --- /dev/null +++ b/test/big_payload_tests/big_payload_test_service_external_start.sh @@ -0,0 +1,10 @@ +#!/bin/bash +# Copyright (C) 2015 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/. + +# Start the service +export VSOMEIP_APPLICATION_NAME=big_payload_test_service +export VSOMEIP_CONFIGURATION=big_payload_test_tcp_service.json +./big_payload_test_service diff --git a/test/big_payload_tests/big_payload_test_service_local_start.sh b/test/big_payload_tests/big_payload_test_service_local_start.sh new file mode 100755 index 0000000..3aadd55 --- /dev/null +++ b/test/big_payload_tests/big_payload_test_service_local_start.sh @@ -0,0 +1,10 @@ +#!/bin/bash +# Copyright (C) 2015 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/. + +# Start the service +export VSOMEIP_APPLICATION_NAME=big_payload_test_service +export VSOMEIP_CONFIGURATION=big_payload_test_local.json +./big_payload_test_service diff --git a/test/big_payload_tests/conf/big_payload_test_tcp_client.json.in b/test/big_payload_tests/conf/big_payload_test_tcp_client.json.in new file mode 100644 index 0000000..0f23a10 --- /dev/null +++ b/test/big_payload_tests/conf/big_payload_test_tcp_client.json.in @@ -0,0 +1,43 @@ +{ + "unicast":"@TEST_IP_MASTER@", + "netmask":"255.255.255.0", + "logging": + { + "level":"info", + "console":"true", + "file": + { + "enable":"true", + "path":"/var/log/vsomeip.log" + }, + "dlt":"true" + }, + "applications": + [ + { + "name":"big_payload_test_client", + "id":"0x1343" + } + ], + "payload-sizes": + [ + { + "unicast":"@TEST_IP_SLAVE@", + "ports": + [ + { + "port":"30509", + "max-payload-size":"614400" + } + ] + } + ], + "routing":"big_payload_test_client", + "service-discovery": + { + "enable":"true", + "multicast":"224.244.224.245", + "port":"30490", + "protocol":"udp" + } +} diff --git a/test/big_payload_tests/conf/big_payload_test_tcp_service.json.in b/test/big_payload_tests/conf/big_payload_test_tcp_service.json.in new file mode 100644 index 0000000..a932d82 --- /dev/null +++ b/test/big_payload_tests/conf/big_payload_test_tcp_service.json.in @@ -0,0 +1,54 @@ +{ + "unicast":"@TEST_IP_SLAVE@", + "logging": + { + "level":"debug", + "console":"true", + "file": + { + "enable":"false", + "path":"/tmp/vsomeip.log" + }, + "dlt":"false" + }, + "applications": + [ + { + "name":"big_payload_test_service", + "id":"0x1277" + } + ], + "services": + [ + { + "service":"0x1234", + "instance":"0x5678", + "reliable": + { + "port":"30509", + "enable-magic-cookies":"false" + } + } + ], + "payload-sizes": + [ + { + "unicast":"@TEST_IP_SLAVE@", + "ports": + [ + { + "port":"30509", + "max-payload-size":"614400" + } + ] + } + ], + "routing":"big_payload_test_service", + "service-discovery": + { + "enable":"true", + "multicast":"224.244.224.245", + "port":"30490", + "protocol":"udp" + } +} diff --git a/test/client_id_tests/client_id_test_globals.hpp b/test/client_id_tests/client_id_test_globals.hpp new file mode 100644 index 0000000..30ee575 --- /dev/null +++ b/test/client_id_tests/client_id_test_globals.hpp @@ -0,0 +1,32 @@ +// Copyright (C) 2014-2015 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 CLIENT_ID_TEST_CLIENT_ID_TEST_GLOBALS_HPP_ +#define CLIENT_ID_TEST_CLIENT_ID_TEST_GLOBALS_HPP_ + +namespace client_id_test { + +struct service_info { + vsomeip::service_t service_id; + vsomeip::instance_t instance_id; + vsomeip::method_t method_id; +}; + +static constexpr std::array service_infos = {{ + // placeholder to be consistent w/ client ids, service ids, app names + { 0xFFFF, 0xFFFF, 0xFFFF }, + // node 1 + { 0x1000, 0x1, 0x1111 }, + { 0x2000, 0x1, 0x2222 }, + // node 2 + { 0x3000, 0x1, 0x3333 }, + { 0x4000, 0x1, 0x4444 }, + { 0x5000, 0x1, 0x5555 } +}}; + +static constexpr int messages_to_send = 10; +} + +#endif /* CLIENT_ID_TEST_CLIENT_ID_TEST_GLOBALS_HPP_ */ diff --git a/test/client_id_tests/client_id_test_master_starter.sh b/test/client_id_tests/client_id_test_master_starter.sh new file mode 100755 index 0000000..f8550c5 --- /dev/null +++ b/test/client_id_tests/client_id_test_master_starter.sh @@ -0,0 +1,64 @@ +#!/bin/bash +# Copyright (C) 2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +# Purpose: This script is needed to start the services with +# one command. This is necessary as ctest - which is used to run the +# tests - isn't able to start two binaries for one testcase. Therefore +# the testcase simply executes this script. This script then runs the services +# and checks that both exit successfully. + +if [ $# -lt 1 ] +then + echo "Please pass a json file to this script." + echo "For example: $0 client_id_test_diff_client_ids_diff_ports_master.json" + exit 1 +fi + +MASTER_JSON_FILE=$1 +CLIENT_JSON_FILE=${MASTER_JSON_FILE/master/slave} + +FAIL=0 + +# Start the services +export VSOMEIP_APPLICATION_NAME=client_id_test_service_one +export VSOMEIP_CONFIGURATION=$1 +./client_id_test_service 1 & + +export VSOMEIP_APPLICATION_NAME=client_id_test_service_two +export VSOMEIP_CONFIGURATION=$1 +./client_id_test_service 2 & + + + +cat < +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include "../../implementation/logging/include/logger.hpp" + +#include "client_id_test_globals.hpp" + + +class client_id_test_service { +public: + client_id_test_service(struct client_id_test::service_info _service_info) : + service_info_(_service_info), + app_(vsomeip::runtime::get()->create_application()), + blocked_(false), + 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(); + app_->register_state_handler( + std::bind(&client_id_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(&client_id_test_service::on_request, this, + std::placeholders::_1)); + app_->register_message_handler(vsomeip::ANY_SERVICE, + service_info_.instance_id, vsomeip::ANY_METHOD, + std::bind(&client_id_test_service::on_response, this, + std::placeholders::_1)); + + for(const auto& i : client_id_test::service_infos) { + if ((i.service_id == service_info_.service_id + && i.instance_id == service_info_.instance_id) + || (i.service_id == 0xFFFF && i.instance_id == 0xFFFF)) { + continue; + } + app_->register_availability_handler(i.service_id, i.instance_id, + std::bind(&client_id_test_service::on_availability, this, + std::placeholders::_1, std::placeholders::_2, + std::placeholders::_3)); + + other_services_available_[std::make_pair(i.service_id, i.instance_id)] = false; + other_services_received_response_[std::make_pair(i.service_id, i.method_id)] = 0; + } + + app_->start(); + } + + ~client_id_test_service() { + offer_thread_.join(); + stop_thread_.join(); + } + + void offer() { + app_->offer_service(service_info_.service_id, service_info_.instance_id); + } + + void stop_offer() { + app_->stop_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 its_lock(mutex_); + blocked_ = true; + condition_.notify_one(); + } + } + + void on_availability(vsomeip::service_t _service, + vsomeip::instance_t _instance, bool _is_available) { + if(_is_available) { + VSOMEIP_INFO << "Service [" + << std::setw(4) << std::setfill('0') << std::hex << _service << "." << _instance + << "] is " + << (_is_available ? "available." : "NOT available."); + + auto its_service = other_services_available_.find(std::make_pair(_service, _instance)); + if(its_service != other_services_available_.end()) { + its_service->second = true; + } + + if(std::all_of(other_services_available_.cbegin(), + other_services_available_.cend(), + [](const std::map, bool>::value_type& v) { + return v.second;})) { + std::lock_guard its_lock(mutex_); + blocked_ = true; + condition_.notify_one(); + } + } + } + + void on_request(const std::shared_ptr &_message) { + if(_message->get_message_type() == vsomeip::message_type_e::MT_REQUEST) { + VSOMEIP_DEBUG << "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() << "]"; + std::shared_ptr its_response = vsomeip::runtime::get() + ->create_response(_message); + app_->send(its_response); + } + } + + void on_response(const std::shared_ptr &_message) { + if(_message->get_message_type() == vsomeip::message_type_e::MT_RESPONSE) { + VSOMEIP_DEBUG << "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 [" + << std::setw(4) << std::setfill('0') << std::hex + << _message->get_service() << "/" << std::setw(4) << std::setfill('0') + << std::hex << _message->get_method() <<"]"; + other_services_received_response_[std::make_pair(_message->get_service(), + _message->get_method())]++; + + if(std::all_of(other_services_received_response_.cbegin(), + other_services_received_response_.cend(), + [](const std::map, std::uint32_t>::value_type& v) + { return v.second == client_id_test::messages_to_send;})) { + std::lock_guard its_lock(stop_mutex_); + stopped_ = true; + stop_condition_.notify_one(); + } + } + } + + void run() { + VSOMEIP_DEBUG << "Running"; + std::unique_lock its_lock(mutex_); + while (!blocked_) { + condition_.wait(its_lock); + } + blocked_ = false; + + VSOMEIP_DEBUG << "Offering"; + offer(); + + + while (!blocked_) { + condition_.wait(its_lock); + } + blocked_ = false; + + VSOMEIP_DEBUG << "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) { + if ((i.service_id == service_info_.service_id + && i.instance_id == service_info_.instance_id) + || (i.service_id == 0xFFFF && i.instance_id == 0xFFFF)) { + continue; + } + std::shared_ptr msg = vsomeip::runtime::get()->create_request(); + msg->set_service(i.service_id); + 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 <<"]"; + } + } + + while (!blocked_) { + condition_.wait(its_lock); + } + blocked_ = false; + } + + void wait_for_stop() { + std::unique_lock its_lock(stop_mutex_); + while (!stopped_) { + stop_condition_.wait(its_lock); + } + VSOMEIP_INFO << "Received responses from all other services, going down"; + + // let offer thread exit + { + std::lock_guard its_lock(mutex_); + blocked_ = true; + condition_.notify_one(); + } + + std::this_thread::sleep_for(std::chrono::seconds(3)); + app_->stop(); + } + +private: + client_id_test::service_info service_info_; + std::shared_ptr app_; + std::map, bool> other_services_available_; + std::map, std::uint32_t> other_services_received_response_; + + bool blocked_; + std::mutex mutex_; + std::condition_variable condition_; + std::thread offer_thread_; + + bool stopped_; + std::mutex stop_mutex_; + std::condition_variable stop_condition_; + std::thread stop_thread_; +}; + +static int service_number; + +TEST(someip_client_id_test, send_ten_messages_to_service) +{ + client_id_test_service its_sample( + client_id_test::service_infos[service_number]); +} + +#ifndef WIN32 +int main(int argc, char** argv) +{ + ::testing::InitGoogleTest(&argc, argv); + if(argc < 2) { + std::cerr << "Please specify a service number, like: " << argv[0] << " 2" << std::endl; + std::cerr << "Valid service numbers are in the range of [0,4]" << std::endl; + return 1; + } + service_number = std::stoi(std::string(argv[1]), nullptr); + return RUN_ALL_TESTS(); +} +#endif diff --git a/test/client_id_tests/client_id_test_slave_starter.sh b/test/client_id_tests/client_id_test_slave_starter.sh new file mode 100755 index 0000000..94ff78b --- /dev/null +++ b/test/client_id_tests/client_id_test_slave_starter.sh @@ -0,0 +1,50 @@ +#!/bin/bash +# Copyright (C) 2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +# Purpose: This script is needed to start the services with +# one command. This is necessary as ctest - which is used to run the +# tests - isn't able to start multiple binaries for one testcase. Therefore +# the testcase simply executes this script. This script then runs the services +# and checks that all exit successfully. + +FAIL=0 + +if [ $# -lt 1 ] +then + echo "Please pass a json file to this script." + echo "For example: $0 client_id_test_diff_client_ids_diff_ports_slave.json" + exit 1 +fi + +# Start the services +export VSOMEIP_APPLICATION_NAME=client_id_test_service_three +export VSOMEIP_CONFIGURATION=$1 +./client_id_test_service 3 & + +export VSOMEIP_APPLICATION_NAME=client_id_test_service_four +export VSOMEIP_CONFIGURATION=$1 +./client_id_test_service 4 & + +export VSOMEIP_APPLICATION_NAME=client_id_test_service_five +export VSOMEIP_CONFIGURATION=$1 +./client_id_test_service 5 & + + +# Wait until all applications are finished +for job in $(jobs -p) +do + # Fail gets incremented if one of the binaries exits + # with a non-zero exit code + wait $job || ((FAIL+=1)) +done + +# Check if both exited successfully +if [ $FAIL -eq 0 ] +then + exit 0 +else + exit 1 +fi diff --git a/test/client_id_tests/conf/client_id_test_diff_client_ids_diff_ports_master.json.in b/test/client_id_tests/conf/client_id_test_diff_client_ids_diff_ports_master.json.in new file mode 100644 index 0000000..fe2248d --- /dev/null +++ b/test/client_id_tests/conf/client_id_test_diff_client_ids_diff_ports_master.json.in @@ -0,0 +1,56 @@ +{ + "unicast":"@TEST_IP_MASTER@", + "logging": + { + "level":"info", + "console":"true", + "file": + { + "enable":"false", + "path":"/tmp/vsomeip.log" + }, + "dlt":"false" + }, + "applications": + [ + { + "name":"client_id_test_service_one", + "id":"0x1111" + }, + { + "name":"client_id_test_service_two", + "id":"0x2222" + } + ], + "services": + [ + { + "service":"0x1000", + "instance":"0x0001", + "unreliable":"30001", + "reliable": + { + "port":"40001", + "enable-magic-cookies":"false" + } + }, + { + "service":"0x2000", + "instance":"0x0001", + "unreliable":"30002", + "reliable": + { + "port":"40002", + "enable-magic-cookies":"false" + } + } + ], + "routing":"client_id_test_service_one", + "service-discovery": + { + "enable":"true", + "multicast":"224.0.0.1", + "port":"30490", + "protocol":"udp" + } +} \ No newline at end of file diff --git a/test/client_id_tests/conf/client_id_test_diff_client_ids_diff_ports_slave.json.in b/test/client_id_tests/conf/client_id_test_diff_client_ids_diff_ports_slave.json.in new file mode 100644 index 0000000..62aee87 --- /dev/null +++ b/test/client_id_tests/conf/client_id_test_diff_client_ids_diff_ports_slave.json.in @@ -0,0 +1,70 @@ +{ + "unicast":"@TEST_IP_SLAVE@", + "logging": + { + "level":"info", + "console":"true", + "file": + { + "enable":"false", + "path":"/tmp/vsomeip.log" + }, + "dlt":"false" + }, + "applications": + [ + { + "name":"client_id_test_service_three", + "id":"0x3333" + }, + { + "name":"client_id_test_service_four", + "id":"0x4444" + }, + { + "name":"client_id_test_service_five", + "id":"0x5555" + } + ], + "services": + [ + { + "service":"0x3000", + "instance":"0x0001", + "unreliable":"30003", + "reliable": + { + "port":"40003", + "enable-magic-cookies":"false" + } + }, + { + "service":"0x4000", + "instance":"0x0001", + "unreliable":"30004", + "reliable": + { + "port":"40004", + "enable-magic-cookies":"false" + } + }, + { + "service":"0x5000", + "instance":"0x0001", + "unreliable":"30005", + "reliable": + { + "port":"40005", + "enable-magic-cookies":"false" + } + } + ], + "routing":"client_id_test_service_three", + "service-discovery": + { + "enable":"true", + "multicast":"224.0.0.1", + "port":"30490", + "protocol":"udp" + } +} \ No newline at end of file diff --git a/test/client_id_tests/conf/client_id_test_diff_client_ids_same_ports_master.json.in b/test/client_id_tests/conf/client_id_test_diff_client_ids_same_ports_master.json.in new file mode 100644 index 0000000..b0c833b --- /dev/null +++ b/test/client_id_tests/conf/client_id_test_diff_client_ids_same_ports_master.json.in @@ -0,0 +1,56 @@ +{ + "unicast":"@TEST_IP_MASTER@", + "logging": + { + "level":"info", + "console":"true", + "file": + { + "enable":"false", + "path":"/tmp/vsomeip.log" + }, + "dlt":"false" + }, + "applications": + [ + { + "name":"client_id_test_service_one", + "id":"0x1111" + }, + { + "name":"client_id_test_service_two", + "id":"0x2222" + } + ], + "services": + [ + { + "service":"0x1000", + "instance":"0x0001", + "unreliable":"30000", + "reliable": + { + "port":"40000", + "enable-magic-cookies":"false" + } + }, + { + "service":"0x2000", + "instance":"0x0001", + "unreliable":"30000", + "reliable": + { + "port":"40000", + "enable-magic-cookies":"false" + } + } + ], + "routing":"client_id_test_service_one", + "service-discovery": + { + "enable":"true", + "multicast":"224.0.0.1", + "port":"30490", + "protocol":"udp" + } +} \ No newline at end of file diff --git a/test/client_id_tests/conf/client_id_test_diff_client_ids_same_ports_slave.json.in b/test/client_id_tests/conf/client_id_test_diff_client_ids_same_ports_slave.json.in new file mode 100644 index 0000000..a9084fc --- /dev/null +++ b/test/client_id_tests/conf/client_id_test_diff_client_ids_same_ports_slave.json.in @@ -0,0 +1,70 @@ +{ + "unicast":"@TEST_IP_SLAVE@", + "logging": + { + "level":"info", + "console":"true", + "file": + { + "enable":"false", + "path":"/tmp/vsomeip.log" + }, + "dlt":"false" + }, + "applications": + [ + { + "name":"client_id_test_service_three", + "id":"0x3333" + }, + { + "name":"client_id_test_service_four", + "id":"0x4444" + }, + { + "name":"client_id_test_service_five", + "id":"0x5555" + } + ], + "services": + [ + { + "service":"0x3000", + "instance":"0x0001", + "unreliable":"30000", + "reliable": + { + "port":"40000", + "enable-magic-cookies":"false" + } + }, + { + "service":"0x4000", + "instance":"0x0001", + "unreliable":"30000", + "reliable": + { + "port":"40000", + "enable-magic-cookies":"false" + } + }, + { + "service":"0x5000", + "instance":"0x0001", + "unreliable":"30000", + "reliable": + { + "port":"40000", + "enable-magic-cookies":"false" + } + } + ], + "routing":"client_id_test_service_three", + "service-discovery": + { + "enable":"true", + "multicast":"224.0.0.1", + "port":"30490", + "protocol":"udp" + } +} \ No newline at end of file diff --git a/test/client_id_tests/conf/client_id_test_same_client_ids_diff_ports_master.json.in b/test/client_id_tests/conf/client_id_test_same_client_ids_diff_ports_master.json.in new file mode 100644 index 0000000..fe2248d --- /dev/null +++ b/test/client_id_tests/conf/client_id_test_same_client_ids_diff_ports_master.json.in @@ -0,0 +1,56 @@ +{ + "unicast":"@TEST_IP_MASTER@", + "logging": + { + "level":"info", + "console":"true", + "file": + { + "enable":"false", + "path":"/tmp/vsomeip.log" + }, + "dlt":"false" + }, + "applications": + [ + { + "name":"client_id_test_service_one", + "id":"0x1111" + }, + { + "name":"client_id_test_service_two", + "id":"0x2222" + } + ], + "services": + [ + { + "service":"0x1000", + "instance":"0x0001", + "unreliable":"30001", + "reliable": + { + "port":"40001", + "enable-magic-cookies":"false" + } + }, + { + "service":"0x2000", + "instance":"0x0001", + "unreliable":"30002", + "reliable": + { + "port":"40002", + "enable-magic-cookies":"false" + } + } + ], + "routing":"client_id_test_service_one", + "service-discovery": + { + "enable":"true", + "multicast":"224.0.0.1", + "port":"30490", + "protocol":"udp" + } +} \ No newline at end of file diff --git a/test/client_id_tests/conf/client_id_test_same_client_ids_diff_ports_slave.json.in b/test/client_id_tests/conf/client_id_test_same_client_ids_diff_ports_slave.json.in new file mode 100644 index 0000000..dc8f5ae --- /dev/null +++ b/test/client_id_tests/conf/client_id_test_same_client_ids_diff_ports_slave.json.in @@ -0,0 +1,70 @@ +{ + "unicast":"@TEST_IP_SLAVE@", + "logging": + { + "level":"info", + "console":"true", + "file": + { + "enable":"false", + "path":"/tmp/vsomeip.log" + }, + "dlt":"false" + }, + "applications": + [ + { + "name":"client_id_test_service_three", + "id":"0x1111" + }, + { + "name":"client_id_test_service_four", + "id":"0x2222" + }, + { + "name":"client_id_test_service_five", + "id":"0x3333" + } + ], + "services": + [ + { + "service":"0x3000", + "instance":"0x0001", + "unreliable":"30003", + "reliable": + { + "port":"40003", + "enable-magic-cookies":"false" + } + }, + { + "service":"0x4000", + "instance":"0x0001", + "unreliable":"30004", + "reliable": + { + "port":"40004", + "enable-magic-cookies":"false" + } + }, + { + "service":"0x5000", + "instance":"0x0001", + "unreliable":"30005", + "reliable": + { + "port":"40005", + "enable-magic-cookies":"false" + } + } + ], + "routing":"client_id_test_service_three", + "service-discovery": + { + "enable":"true", + "multicast":"224.0.0.1", + "port":"30490", + "protocol":"udp" + } +} \ No newline at end of file diff --git a/test/client_id_tests/conf/client_id_test_same_client_ids_same_ports_master.json.in b/test/client_id_tests/conf/client_id_test_same_client_ids_same_ports_master.json.in new file mode 100644 index 0000000..b0c833b --- /dev/null +++ b/test/client_id_tests/conf/client_id_test_same_client_ids_same_ports_master.json.in @@ -0,0 +1,56 @@ +{ + "unicast":"@TEST_IP_MASTER@", + "logging": + { + "level":"info", + "console":"true", + "file": + { + "enable":"false", + "path":"/tmp/vsomeip.log" + }, + "dlt":"false" + }, + "applications": + [ + { + "name":"client_id_test_service_one", + "id":"0x1111" + }, + { + "name":"client_id_test_service_two", + "id":"0x2222" + } + ], + "services": + [ + { + "service":"0x1000", + "instance":"0x0001", + "unreliable":"30000", + "reliable": + { + "port":"40000", + "enable-magic-cookies":"false" + } + }, + { + "service":"0x2000", + "instance":"0x0001", + "unreliable":"30000", + "reliable": + { + "port":"40000", + "enable-magic-cookies":"false" + } + } + ], + "routing":"client_id_test_service_one", + "service-discovery": + { + "enable":"true", + "multicast":"224.0.0.1", + "port":"30490", + "protocol":"udp" + } +} \ No newline at end of file diff --git a/test/client_id_tests/conf/client_id_test_same_client_ids_same_ports_slave.json.in b/test/client_id_tests/conf/client_id_test_same_client_ids_same_ports_slave.json.in new file mode 100644 index 0000000..0b6e1e2 --- /dev/null +++ b/test/client_id_tests/conf/client_id_test_same_client_ids_same_ports_slave.json.in @@ -0,0 +1,70 @@ +{ + "unicast":"@TEST_IP_SLAVE@", + "logging": + { + "level":"info", + "console":"true", + "file": + { + "enable":"false", + "path":"/tmp/vsomeip.log" + }, + "dlt":"false" + }, + "applications": + [ + { + "name":"client_id_test_service_three", + "id":"0x1111" + }, + { + "name":"client_id_test_service_four", + "id":"0x2222" + }, + { + "name":"client_id_test_service_five", + "id":"0x3333" + } + ], + "services": + [ + { + "service":"0x3000", + "instance":"0x0001", + "unreliable":"30000", + "reliable": + { + "port":"40000", + "enable-magic-cookies":"false" + } + }, + { + "service":"0x4000", + "instance":"0x0001", + "unreliable":"30000", + "reliable": + { + "port":"40000", + "enable-magic-cookies":"false" + } + }, + { + "service":"0x5000", + "instance":"0x0001", + "unreliable":"30000", + "reliable": + { + "port":"40000", + "enable-magic-cookies":"false" + } + } + ], + "routing":"client_id_test_service_three", + "service-discovery": + { + "enable":"true", + "multicast":"224.0.0.1", + "port":"30490", + "protocol":"udp" + } +} \ No newline at end of file diff --git a/test/configuration-test.cpp b/test/configuration-test.cpp deleted file mode 100644 index cc91ab0..0000000 --- a/test/configuration-test.cpp +++ /dev/null @@ -1,214 +0,0 @@ -// Copyright (C) 2015 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 -#include -#include - -#define DESIRED_ADDRESS "10.0.2.15" -#define DESIRED_HAS_CONSOLE true -#define DESIRED_HAS_FILE true -#define DESIRED_HAS_DLT false -#define DESIRED_LOGLEVEL "debug" -#define DESIRED_LOGFILE "/home/someip/another-file.log" -#define DESIRED_HOST "my_application" -#define DESIRED_PROTOCOL "tcp" -#define DESIRED_PORT 30666 - -#define DESIRED_RELIABLE_1234_0022 30506 -#define DESIRED_UNRELIABLE_1234_0022 31000 - -#define DESIRED_RELIABLE_1234_0023 30503 -#define DESIRED_UNRELIABLE_1234_0023 vsomeip::ILLEGAL_PORT - -#define DESIRED_RELIABLE_2277_0022 30505 -#define DESIRED_UNRELIABLE_2277_0022 31001 - -#define DESIRED_RELIABLE_2266_0022 30505 -#define DESIRED_UNRELIABLE_2266_0022 30507 - -#define DESIRED_RELIABLE_4466_0321 30506 -#define DESIRED_UNRELIABLE_4466_0321 30444 - -#define DESIRED_ADDRESS_1234_0022 "local" -#define DESIRED_MIN_INITIAL_DELAY_1234_0022 10 -#define DESIRED_MAX_INITIAL_DELAY_1234_0022 100 -#define DESIRED_REPETITION_BASE_DELAY_1234_0022 200 -#define DESIRED_REPETITION_MAX_1234_0022 7 -#define DESIRED_CYCLIC_OFFER_DELAY_1234_0022 2000 -#define DESIRED_CYCLIC_REQUEST_DELAY_1234_0022 2001 - -#define DESIRED_ADDRESS_2277_0022 "local" -#define DESIRED_MIN_INITIAL_DELAY_2277_0022 100 -#define DESIRED_MAX_INITIAL_DELAY_2277_0022 200 -#define DESIRED_REPETITION_BASE_DELAY_2277_0022 300 -#define DESIRED_REPETITION_MAX_2277_0022 5 -#define DESIRED_CYCLIC_OFFER_DELAY_2277_0022 2500 -#define DESIRED_CYCLIC_REQUEST_DELAY_2277_0022 2221 - -#define DESIRED_ADDRESS_4466_0321 "10.0.2.23" - -template -void check(const T &_is, const T &_desired, const std::string &_test) { - if (_is == _desired) { - VSOMEIP_INFO << "Test \"" << _test << "\" succeeded."; - } else { - VSOMEIP_ERROR << "Test \"" << _test << "\" failed! (" << _is << " != " << _desired << ")"; - } -} - -int main(int argc, char **argv) { - std::string its_path; - - int i = 0; - while (i < argc-1) { - if (std::string("--someip") == argv[i]) { - its_path = argv[i+1]; - break; - } - - i++; - } - - if (its_path == "") { - std::cerr << "Usage: " << argv[0] << " --someip " << std::endl; - return -1; - } - - vsomeip::configuration *its_configuration = vsomeip::configuration::get(its_path); - - // 1. Did we get a configuration object? - if (0 == its_configuration) { - VSOMEIP_ERROR << "No configuration object. Either memory overflow or loading error detected!"; - return -1; - } - - // 2. Check host address - boost::asio::ip::address its_address = its_configuration->get_unicast(); - check(its_address.to_string(), DESIRED_ADDRESS, "HOST 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(has_console, DESIRED_HAS_CONSOLE, "HAS CONSOLE"); - check(has_file, DESIRED_HAS_FILE, "HAS FILE"); - check(has_dlt, DESIRED_HAS_DLT, "HAS DLT"); - check(logfile, DESIRED_LOGFILE, "LOGFILE"); - check(boost::log::trivial::to_string(loglevel), DESIRED_LOGLEVEL, "LOGLEVEL"); - - // 4. Services - uint16_t its_reliable = its_configuration->get_reliable_port(0x1234, 0x0022); - uint16_t its_unreliable = its_configuration->get_unreliable_port(0x1234, 0x0022); - - check(its_reliable, DESIRED_RELIABLE_1234_0022, "RELIABLE_TEST_1234_0022"); - check(its_unreliable, DESIRED_UNRELIABLE_1234_0022, "UNRELIABLE_TEST_1234_0022"); - - its_reliable = its_configuration->get_reliable_port(0x1234, 0x0023); - its_unreliable = its_configuration->get_unreliable_port(0x1234, 0x0023); - - check(its_reliable, DESIRED_RELIABLE_1234_0023, "RELIABLE_TEST_1234_0023"); - check(its_unreliable, DESIRED_UNRELIABLE_1234_0023, "UNRELIABLE_TEST_1234_0023"); - - its_reliable = its_configuration->get_reliable_port(0x2277, 0x0022); - its_unreliable = its_configuration->get_unreliable_port(0x2277, 0x0022); - - check(its_reliable, DESIRED_RELIABLE_2277_0022, "RELIABLE_TEST_2277_0022"); - check(its_unreliable, DESIRED_UNRELIABLE_2277_0022, "UNRELIABLE_TEST_2277_0022"); - - its_reliable = its_configuration->get_reliable_port(0x4466, 0x0321); - its_unreliable = its_configuration->get_unreliable_port(0x4466, 0x0321); - - check(its_reliable, DESIRED_RELIABLE_4466_0321, "RELIABLE_TEST_4466_0321"); - check(its_unreliable, DESIRED_UNRELIABLE_4466_0321, "UNRELIABLE_TEST_4466_0321"); - - its_reliable = its_configuration->get_reliable_port(0x2277, 0x0022); - its_unreliable = its_configuration->get_unreliable_port(0x2277, 0x0022); - - check(its_reliable, DESIRED_RELIABLE_2277_0022, "RELIABLE_TEST_2277_0022"); - check(its_unreliable, DESIRED_UNRELIABLE_2277_0022, "UNRELIABLE_TEST_2277_0022"); - - std::string its_address_s = its_configuration->get_unicast(0x1234, 0x0022); - std::string its_group_name = its_configuration->get_group(0x1234, 0x0022); - uint32_t its_min_initial_delay = its_configuration->get_min_initial_delay(its_group_name); - uint32_t its_max_initial_delay = its_configuration->get_max_initial_delay(its_group_name); - uint32_t its_repetition_base_delay = its_configuration->get_repetition_base_delay(its_group_name); - uint8_t its_repetition_max = its_configuration->get_repetition_max(its_group_name); - uint32_t its_cyclic_offer_delay = its_configuration->get_cyclic_offer_delay(its_group_name); - uint32_t its_cyclic_request_delay = its_configuration->get_cyclic_request_delay(its_group_name); - - check(its_address_s, DESIRED_ADDRESS_1234_0022, "ADDRESS_TEST_1234_0022"); - check(its_min_initial_delay, DESIRED_MIN_INITIAL_DELAY_1234_0022, "MIN_INITIAL_DELAY_TEST_1234_0022"); - check(its_max_initial_delay, DESIRED_MAX_INITIAL_DELAY_1234_0022, "MAX_INITIAL_DELAY_TEST_1234_0022"); - check(its_repetition_base_delay, DESIRED_REPETITION_BASE_DELAY_1234_0022, "REPETITION_BASE_DELAY_TEST_1234_0022"); - check(its_repetition_max, DESIRED_REPETITION_MAX_1234_0022, "REPETITION_MAX_TEST_1234_0022"); - check(its_cyclic_offer_delay, DESIRED_CYCLIC_OFFER_DELAY_1234_0022, "CYCLIC_OFFER_DELAY_TEST_1234_0022"); - check(its_cyclic_request_delay, DESIRED_CYCLIC_REQUEST_DELAY_1234_0022, "CYCLIC_REQUEST_DELAY_TEST_1234_0022"); - - its_group_name = its_configuration->get_group(0x1234, 0x0023); - its_min_initial_delay = its_configuration->get_min_initial_delay(its_group_name); - its_max_initial_delay = its_configuration->get_max_initial_delay(its_group_name); - its_repetition_base_delay = its_configuration->get_repetition_base_delay(its_group_name); - its_repetition_max = its_configuration->get_repetition_max(its_group_name); - its_cyclic_offer_delay = its_configuration->get_cyclic_offer_delay(its_group_name); - its_cyclic_request_delay = its_configuration->get_cyclic_request_delay(its_group_name); - - check(its_min_initial_delay, DESIRED_MIN_INITIAL_DELAY_1234_0022, "MIN_INITIAL_DELAY_TEST_1234_0023"); - check(its_max_initial_delay, DESIRED_MAX_INITIAL_DELAY_1234_0022, "MAX_INITIAL_DELAY_TEST_1234_0023"); - check(its_repetition_base_delay, DESIRED_REPETITION_BASE_DELAY_1234_0022, "REPETITION_BASE_DELAY_TEST_1234_0023"); - check(its_repetition_max, DESIRED_REPETITION_MAX_1234_0022, "REPETITION_MAX_TEST_1234_0023"); - check(its_cyclic_offer_delay, DESIRED_CYCLIC_OFFER_DELAY_1234_0022, "CYCLIC_OFFER_DELAY_TEST_1234_0023"); - check(its_cyclic_request_delay, DESIRED_CYCLIC_REQUEST_DELAY_1234_0022, "CYCLIC_REQUEST_DELAY_TEST_1234_0023"); - - its_group_name = its_configuration->get_group(0x2277, 0x0022); - its_min_initial_delay = its_configuration->get_min_initial_delay(its_group_name); - its_max_initial_delay = its_configuration->get_max_initial_delay(its_group_name); - its_repetition_base_delay = its_configuration->get_repetition_base_delay(its_group_name); - its_repetition_max = its_configuration->get_repetition_max(its_group_name); - its_cyclic_offer_delay = its_configuration->get_cyclic_offer_delay(its_group_name); - its_cyclic_request_delay = its_configuration->get_cyclic_request_delay(its_group_name); - - check(its_min_initial_delay, DESIRED_MIN_INITIAL_DELAY_2277_0022, "MIN_INITIAL_DELAY_TEST_2277_0022"); - check(its_max_initial_delay, DESIRED_MAX_INITIAL_DELAY_2277_0022, "MAX_INITIAL_DELAY_TEST_2277_0022"); - check(its_repetition_base_delay, DESIRED_REPETITION_BASE_DELAY_2277_0022, "REPETITION_BASE_DELAY_TEST_2277_0022"); - check(its_repetition_max, DESIRED_REPETITION_MAX_2277_0022, "REPETITION_MAX_TEST_2277_0022"); - check(its_cyclic_offer_delay, DESIRED_CYCLIC_OFFER_DELAY_2277_0022, "CYCLIC_OFFER_DELAY_TEST_2277_0022"); - check(its_cyclic_request_delay, DESIRED_CYCLIC_REQUEST_DELAY_2277_0022, "CYCLIC_REQUEST_DELAY_TEST_2277_0022"); - - its_group_name = its_configuration->get_group(0x2266, 0x0022); - its_min_initial_delay = its_configuration->get_min_initial_delay(its_group_name); - its_max_initial_delay = its_configuration->get_max_initial_delay(its_group_name); - its_repetition_base_delay = its_configuration->get_repetition_base_delay(its_group_name); - its_repetition_max = its_configuration->get_repetition_max(its_group_name); - its_cyclic_offer_delay = its_configuration->get_cyclic_offer_delay(its_group_name); - its_cyclic_request_delay = its_configuration->get_cyclic_request_delay(its_group_name); - - check(its_min_initial_delay, DESIRED_MIN_INITIAL_DELAY_2277_0022, "MIN_INITIAL_DELAY_TEST_2266_0022"); - check(its_max_initial_delay, DESIRED_MAX_INITIAL_DELAY_2277_0022, "MAX_INITIAL_DELAY_TEST_2266_0022"); - check(its_repetition_base_delay, DESIRED_REPETITION_BASE_DELAY_2277_0022, "REPETITION_BASE_DELAY_TEST_2266_0022"); - check(its_repetition_max, DESIRED_REPETITION_MAX_2277_0022, "REPETITION_MAX_TEST_2266_0022"); - check(its_cyclic_offer_delay, DESIRED_CYCLIC_OFFER_DELAY_2277_0022, "CYCLIC_OFFER_DELAY_TEST_2266_0022"); - check(its_cyclic_request_delay, DESIRED_CYCLIC_REQUEST_DELAY_2277_0022, "CYCLIC_REQUEST_DELAY_TEST_2266_0022"); - - its_address_s = its_configuration->get_unicast(0x4466, 0x0321); - check(its_address_s, DESIRED_ADDRESS_4466_0321, "ADDRESS_TEST_4466_0321"); - - // 5. Service discovery - std::string protocol = its_configuration->get_service_discovery_protocol(); - uint16_t port = its_configuration->get_service_discovery_port(); - - check(protocol, DESIRED_PROTOCOL, "SERVICE DISCOVERY PROTOCOL"); - check(port, DESIRED_PORT, "SERVICE DISCOVERY PORT"); - - return 0; -} - - - diff --git a/test/configuration_tests/configuration-test-deprecated.json b/test/configuration_tests/configuration-test-deprecated.json new file mode 100644 index 0000000..8d6a8d2 --- /dev/null +++ b/test/configuration_tests/configuration-test-deprecated.json @@ -0,0 +1,131 @@ +{ + "unicast" : "10.0.2.15", + "logging" : + { + "level" : "debug", + "console" : "true", + "file" : { "enable" : "true", "path" : "/home/someip/another-file.log" }, + "dlt" : "false" + }, + "applications" : + [ + { + "name" : "my_application", + "id" : "0x7788" + }, + { + "name" : "other_application", + "id" : "0x9933" + } + ], + "servicegroups" : + [ + { + "name" : "default", + "unicast" : "local", + "delays" : + { + "initial" : { "minimum" : "10", "maximum" : "100" }, + "repetition-base" : "200", + "repetition-max" : "7", + "cyclic-offer" : "2132", + "cyclic-request" : "2001" + }, + "services" : + [ + { + "service" : "0x1234", + "instance" : "0x0022", + "reliable" : { "port" : "30506", "magic_cookies" : "false" }, + "unreliable" : "31000", + "events" : + [ + { + "event" : "0x0778", + "is_field" : "false" + }, + { + "event" : "0x779", + "is_field" : "true" + }, + { + "event" : "0x77A", + "is_field" : "false" + } + ], + "eventgroups" : + [ + { + "eventgroup" : "0x4567", + "multicast" : "225.226.227.228", + "events" : [ "0x778", "0x779" ] + }, + { + "eventgroup" : "0x4569", + "multicast" : "225.227.227.228", + "events" : [ "0x779", "0x77A" ] + }, + { + "eventgroup" : "0x4569", + "multicast" : "225.222.227.228", + "events" : [ "0x778", "0x77A" ] + } + ] + }, + { + "service" : "0x1234", + "instance" : "0x0023", + "reliable" : "30503" + } + ] + }, + { + "name" : "extra", + "unicast" : "local", + "delays" : + { + "initial" : { "minimum" : "100", "maximum" : "200" }, + "repetition-base" : "300", + "repetition-max" : "5", + "cyclic-offer" : "2500", + "cyclic-request" : "2221" + }, + "services" : + [ + { + "service" : "0x2277", + "instance" : "0x0022", + "reliable" : { "port" : "30505" }, + "unreliable" : "31001" + }, + { + "service" : "0x2266", + "instance" : "0x0022", + "reliable" : "30505", + "unreliable" : "30507" + } + ] + }, + { + "name" : "remote", + "unicast" : "10.0.2.23", + "services" : + [ + { + "service" : "0x4466", + "instance" : "0x0321", + "reliable" : "30506", + "unreliable" : "30444" + } + ] + } + ], + "routing" : "my_application", + "service-discovery" : + { + "enable" : "true", + "protocol" : "udp", + "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 new file mode 100644 index 0000000..b4538d0 --- /dev/null +++ b/test/configuration_tests/configuration-test.cpp @@ -0,0 +1,346 @@ +// Copyright (C) 2015 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 + +#include "../implementation/configuration/include/configuration.hpp" +#include "../implementation/logging/include/logger.hpp" + +#define CONFIGURATION_FILE "configuration-test.json" +#define DEPRECATED_CONFIGURATION_FILE "configuration-test-deprecated.json" + +#define EXPECTED_UNICAST_ADDRESS "10.0.2.15" + +#define EXPECTED_HAS_CONSOLE true +#define EXPECTED_HAS_FILE true +#define EXPECTED_HAS_DLT false +#define EXPECTED_LOGLEVEL "debug" +#define EXPECTED_LOGFILE "/home/someip/another-file.log" + +#define EXPECTED_ROUTING_MANAGER_HOST "my_application" + +// Services +#define EXPECTED_UNICAST_ADDRESS_1234_0022 EXPECTED_UNICAST_ADDRESS +#define EXPECTED_RELIABLE_PORT_1234_0022 30506 +#define EXPECTED_UNRELIABLE_PORT_1234_0022 31000 + +#define EXPECTED_UNICAST_ADDRESS_1234_0023 EXPECTED_UNICAST_ADDRESS +#define EXPECTED_RELIABLE_PORT_1234_0023 30503 +#define EXPECTED_UNRELIABLE_PORT_1234_0023 vsomeip::ILLEGAL_PORT + +#define EXPECTED_UNICAST_ADDRESS_2277_0022 EXPECTED_UNICAST_ADDRESS +#define EXPECTED_RELIABLE_PORT_2277_0022 30505 +#define EXPECTED_UNRELIABLE_PORT_2277_0022 31001 + +#define EXPECTED_UNICAST_ADDRESS_2266_0022 EXPECTED_UNICAST_ADDRESS +#define EXPECTED_RELIABLE_PORT_2266_0022 30505 +#define EXPECTED_UNRELIABLE_PORT_2266_0022 30507 + +#define EXPECTED_UNICAST_ADDRESS_4466_0321 "10.0.2.23" +#define EXPECTED_RELIABLE_PORT_4466_0321 30506 +#define EXPECTED_UNRELIABLE_PORT_4466_0321 30444 + +// Service Discovery +#define EXPECTED_SD_ENABLED true +#define EXPECTED_SD_PROTOCOL "udp" +#define EXPECTED_SD_MULTICAST "224.212.244.223" +#define EXPECTED_SD_PORT 30666 + +#define EXPECTED_INITIAL_DELAY_MIN 1234 +#define EXPECTED_INITIAL_DELAY_MAX 2345 +#define EXPECTED_REPETITIONS_BASE_DELAY 4242 +#define EXPECTED_REPETITIONS_MAX 4 +#define EXPECTED_TTL 13 +#define EXPECTED_CYCLIC_OFFER_DELAY 2132 +#define EXPECTED_REQUEST_RESPONSE_DELAY 1111 + +#define EXPECTED_DEPRECATED_INITIAL_DELAY_MIN 10 +#define EXPECTED_DEPRECATED_INITIAL_DELAY_MAX 100 +#define EXPECTED_DEPRECATED_REPETITIONS_BASE_DELAY 200 +#define EXPECTED_DEPRECATED_REPETITIONS_MAX 7 +#define EXPECTED_DEPRECATED_TTL 5 +#define EXPECTED_DEPRECATED_REQUEST_RESPONSE_DELAY 2001 + +template +void check(const T &_is, const T &_expected, const std::string &_test) { + if (_is == _expected) { + VSOMEIP_INFO << "Test \"" << _test << "\" succeeded."; + } else { + VSOMEIP_ERROR << "Test \"" << _test << "\" failed! (" + << _is << " != " << _expected << ")"; + } +} + +void check_file(const std::string &_config_file, + const std::string &_expected_unicast_address, + bool _expected_has_console, + bool _expected_has_file, + bool _expected_has_dlt, + const std::string &_expected_logfile, + const std::string &_expected_loglevel, + const std::string &_expected_unicast_address_1234_0022, + uint16_t _expected_reliable_port_1234_0022, + uint16_t _expected_unreliable_port_1234_0022, + const std::string &_expected_unicast_address_1234_0023, + uint16_t _expected_reliable_port_1234_0023, + uint16_t _expected_unreliable_port_1234_0023, + const std::string &_expected_unicast_address_2277_0022, + uint16_t _expected_reliable_port_2277_0022, + uint16_t _expected_unreliable_port_2277_0022, + const std::string &_expected_unicast_address_2266_0022, + uint16_t _expected_reliable_port_2266_0022, + uint16_t _expected_unreliable_port_2266_0022, + const std::string &_expected_unicast_address_4466_0321, + uint16_t _expected_reliable_port_4466_0321, + uint16_t _expected_unreliable_port_4466_0321, + bool _expected_enabled, + const std::string &_expected_protocol, + const std::string &_expected_multicast, + uint16_t _expected_port, + int32_t _expected_initial_delay_min, + int32_t _expected_initial_delay_max, + int32_t _expected_repetitions_base_delay, + uint8_t _expected_repetitions_max, + vsomeip::ttl_t _expected_ttl, + vsomeip::ttl_t _expected_cyclic_offer_delay, + vsomeip::ttl_t _expected_request_response_delay) { + + // Reset configuration + vsomeip::configuration::reset(); + + // Load test configuration + std::set its_configuration_files; + its_configuration_files.insert(_config_file); + std::shared_ptr 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(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(has_console, _expected_has_console, "HAS CONSOLE"); + check(has_file, _expected_has_file, "HAS FILE"); + check(has_dlt, _expected_has_dlt, "HAS DLT"); + check(logfile, _expected_logfile, "LOGFILE"); + check(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(its_unicast_address, + _expected_unicast_address_1234_0022, + "UNICAST_ADDRESS_1234_0022"); + check(its_reliable_port, + _expected_reliable_port_1234_0022, + "RELIABLE_PORT_1234_0022"); + check(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(its_unicast_address, + _expected_unicast_address_1234_0023, + "UNICAST_ADDRESS_1234_0023"); + check(its_reliable_port, + _expected_reliable_port_1234_0023, + "RELIABLE_PORT_1234_0023"); + check(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(its_unicast_address, + _expected_unicast_address_2277_0022, + "UNICAST_ADDRESS_2277_0022"); + check(its_reliable_port, + _expected_reliable_port_2277_0022, + "RELIABLE_PORT_2277_0022"); + check(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(its_unicast_address, + _expected_unicast_address_2266_0022, + "UNICAST_ADDRESS_2266_0022"); + check(its_reliable_port, + _expected_reliable_port_2266_0022, + "RELIABLE_PORT_2266_0022"); + check(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(its_unicast_address, + _expected_unicast_address_4466_0321, + "UNICAST_ADDRESS_4466_0321"); + check(its_reliable_port, + _expected_reliable_port_4466_0321, + "RELIABLE_PORT_4466_0321"); + check(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(enabled, _expected_enabled, "SD ENABLED"); + check(protocol, _expected_protocol, "SD PROTOCOL"); + check(multicast, _expected_multicast, "SD MULTICAST"); + check(port, _expected_port, "SD PORT"); + + check(initial_delay_min, _expected_initial_delay_min, "SD INITIAL DELAY MIN"); + check(initial_delay_max, _expected_initial_delay_max, "SD INITIAL DELAY MAX"); + check(repetitions_base_delay, _expected_repetitions_base_delay, "SD REPETITION BASE DELAY"); + check(repetitions_max,_expected_repetitions_max, "SD REPETITION MAX"); + check(ttl, _expected_ttl, "SD TTL"); + check(cyclic_offer_delay, _expected_cyclic_offer_delay, "SD CYCLIC OFFER DELAY"); + check(request_response_delay, _expected_request_response_delay, "SD RESPONSE REQUEST DELAY"); +} + + + +int main() { + // Check current configuration file format + std::cout << "/////////////////////////////////" << std::endl + << "// CHECKING CONFIGURATION FILE //" << std::endl + << "/////////////////////////////////" << std::endl; + check_file(CONFIGURATION_FILE, + EXPECTED_UNICAST_ADDRESS, + EXPECTED_HAS_CONSOLE, + EXPECTED_HAS_FILE, + EXPECTED_HAS_DLT, + EXPECTED_LOGFILE, + EXPECTED_LOGLEVEL, + EXPECTED_UNICAST_ADDRESS_1234_0022, + EXPECTED_RELIABLE_PORT_1234_0022, + EXPECTED_UNRELIABLE_PORT_1234_0022, + EXPECTED_UNICAST_ADDRESS_1234_0023, + EXPECTED_RELIABLE_PORT_1234_0023, + EXPECTED_UNRELIABLE_PORT_1234_0023, + EXPECTED_UNICAST_ADDRESS_2277_0022, + EXPECTED_RELIABLE_PORT_2277_0022, + EXPECTED_UNRELIABLE_PORT_2277_0022, + EXPECTED_UNICAST_ADDRESS_2266_0022, + EXPECTED_RELIABLE_PORT_2266_0022, + EXPECTED_UNRELIABLE_PORT_2266_0022, + EXPECTED_UNICAST_ADDRESS_4466_0321, + EXPECTED_RELIABLE_PORT_4466_0321, + EXPECTED_UNRELIABLE_PORT_4466_0321, + EXPECTED_SD_ENABLED, + EXPECTED_SD_PROTOCOL, + EXPECTED_SD_MULTICAST, + EXPECTED_SD_PORT, + EXPECTED_INITIAL_DELAY_MIN, + EXPECTED_INITIAL_DELAY_MAX, + EXPECTED_REPETITIONS_BASE_DELAY, + EXPECTED_REPETITIONS_MAX, + EXPECTED_TTL, + EXPECTED_CYCLIC_OFFER_DELAY, + EXPECTED_REQUEST_RESPONSE_DELAY); + + // Check deprecated configuration file format + std::cout << "////////////////////////////////////////////" << std::endl + << "// CHECKING DEPRECATED CONFIGURATION FILE //" << std::endl + << "////////////////////////////////////////////" << std::endl; + check_file(DEPRECATED_CONFIGURATION_FILE, + EXPECTED_UNICAST_ADDRESS, + EXPECTED_HAS_CONSOLE, + EXPECTED_HAS_FILE, + EXPECTED_HAS_DLT, + EXPECTED_LOGFILE, + EXPECTED_LOGLEVEL, + EXPECTED_UNICAST_ADDRESS_1234_0022, + EXPECTED_RELIABLE_PORT_1234_0022, + EXPECTED_UNRELIABLE_PORT_1234_0022, + EXPECTED_UNICAST_ADDRESS_1234_0023, + EXPECTED_RELIABLE_PORT_1234_0023, + EXPECTED_UNRELIABLE_PORT_1234_0023, + EXPECTED_UNICAST_ADDRESS_2277_0022, + EXPECTED_RELIABLE_PORT_2277_0022, + EXPECTED_UNRELIABLE_PORT_2277_0022, + EXPECTED_UNICAST_ADDRESS_2266_0022, + EXPECTED_RELIABLE_PORT_2266_0022, + EXPECTED_UNRELIABLE_PORT_2266_0022, + EXPECTED_UNICAST_ADDRESS_4466_0321, + EXPECTED_RELIABLE_PORT_4466_0321, + EXPECTED_UNRELIABLE_PORT_4466_0321, + EXPECTED_SD_ENABLED, + EXPECTED_SD_PROTOCOL, + EXPECTED_SD_MULTICAST, + EXPECTED_SD_PORT, + EXPECTED_DEPRECATED_INITIAL_DELAY_MIN, + EXPECTED_DEPRECATED_INITIAL_DELAY_MAX, + EXPECTED_DEPRECATED_REPETITIONS_BASE_DELAY, + EXPECTED_DEPRECATED_REPETITIONS_MAX, + EXPECTED_DEPRECATED_TTL, + EXPECTED_CYCLIC_OFFER_DELAY, + EXPECTED_DEPRECATED_REQUEST_RESPONSE_DELAY); + + return 0; +} + + + diff --git a/test/configuration_tests/configuration-test.json b/test/configuration_tests/configuration-test.json new file mode 100644 index 0000000..499dbc9 --- /dev/null +++ b/test/configuration_tests/configuration-test.json @@ -0,0 +1,103 @@ +{ + "unicast" : "10.0.2.15", + "logging" : + { + "level" : "debug", + "console" : "true", + "file" : { "enable" : "true", "path" : "/home/someip/another-file.log" }, + "dlt" : "false" + }, + "applications" : + [ + { + "name" : "my_application", + "id" : "0x7788" + }, + { + "name" : "other_application", + "id" : "0x9933" + } + ], + "services" : + [ + { + "service" : "0x1234", + "instance" : "0x0022", + "unicast" : "local", + "reliable" : { "port" : "30506", "magic_cookies" : "false" }, + "unreliable" : "31000", + "events" : + [ + { + "event" : "0x0778", + "is_field" : "false" + }, + { + "event" : "0x779", + "is_field" : "true" + }, + { + "event" : "0x77A", + "is_field" : "false" + } + ], + "eventgroups" : + [ + { + "eventgroup" : "0x4567", + "multicast" : "225.226.227.228", + "events" : [ "0x778", "0x779" ] + }, + { + "eventgroup" : "0x4569", + "multicast" : "225.227.227.228", + "events" : [ "0x779", "0x77A" ] + }, + { + "eventgroup" : "0x4569", + "multicast" : "225.222.227.228", + "events" : [ "0x778", "0x77A" ] + } + ] + }, + { + "service" : "0x1234", + "instance" : "0x0023", + "reliable" : "30503" + }, + { + "service" : "0x2277", + "instance" : "0x0022", + "reliable" : { "port" : "30505" }, + "unreliable" : "31001" + }, + { + "service" : "0x2266", + "instance" : "0x0022", + "reliable" : "30505", + "unreliable" : "30507" + }, + { + "service" : "0x4466", + "instance" : "0x0321", + "unicast" : "10.0.2.23", + "reliable" : "30506", + "unreliable" : "30444" + } + ], + "routing" : "my_application", + "service-discovery" : + { + "enable" : "true", + "protocol" : "udp", + "multicast" : "224.212.244.223", + "port" : "30666", + "initial_delay_min" : "1234", + "initial_delay_max" : "2345", + "repetitions_base_delay" : "4242", + "repetitions_max" : "4", + "ttl" : "13", + "cyclic_offer_delay" : "2132", + "request_response_delay" : "1111" + } +} \ No newline at end of file diff --git a/test/header_factory_tests/header_factory_test_client.cpp b/test/header_factory_tests/header_factory_test_client.cpp index 4cce67e..3f9eb4f 100644 --- a/test/header_factory_tests/header_factory_test_client.cpp +++ b/test/header_factory_tests/header_factory_test_client.cpp @@ -22,24 +22,20 @@ void header_factory_test_client::init() { app_->init(); - app_->register_event_handler( - std::bind(&header_factory_test_client::on_event, this, + app_->register_state_handler( + std::bind(&header_factory_test_client::on_state, this, std::placeholders::_1)); - app_->register_availability_handler(vsomeip_test::TEST_SERVICE_SERVICE_ID, - vsomeip_test::TEST_SERVICE_INSTANCE_ID, - std::bind(&header_factory_test_client::on_availability, this, - std::placeholders::_1, std::placeholders::_2, - std::placeholders::_3)); - app_->register_message_handler(vsomeip::ANY_SERVICE, vsomeip_test::TEST_SERVICE_INSTANCE_ID, vsomeip::ANY_METHOD, std::bind(&header_factory_test_client::on_message, this, std::placeholders::_1)); - request_->set_service(vsomeip_test::TEST_SERVICE_SERVICE_ID); - request_->set_instance(vsomeip_test::TEST_SERVICE_INSTANCE_ID); - request_->set_method(vsomeip_test::TEST_SERVICE_METHOD_ID); + app_->register_availability_handler(vsomeip_test::TEST_SERVICE_SERVICE_ID, + vsomeip_test::TEST_SERVICE_INSTANCE_ID, + std::bind(&header_factory_test_client::on_availability, this, + std::placeholders::_1, std::placeholders::_2, + std::placeholders::_3)); } void header_factory_test_client::start() @@ -53,7 +49,7 @@ 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_event_handler(); + app_->unregister_state_handler(); app_->unregister_message_handler(vsomeip::ANY_SERVICE, vsomeip_test::TEST_SERVICE_INSTANCE_ID, vsomeip::ANY_METHOD); @@ -66,9 +62,9 @@ void header_factory_test_client::join_sender_thread(){ ASSERT_EQ(number_of_sent_messages_, number_of_acknowledged_messages_); } -void header_factory_test_client::on_event(vsomeip::event_type_e _event) +void header_factory_test_client::on_state(vsomeip::state_type_e _state) { - if(_event == vsomeip::event_type_e::ET_REGISTERED) + if(_state == vsomeip::state_type_e::ST_REGISTERED) { app_->request_service(vsomeip_test::TEST_SERVICE_SERVICE_ID, vsomeip_test::TEST_SERVICE_INSTANCE_ID, false); @@ -112,6 +108,11 @@ void header_factory_test_client::on_message(const std::shared_ptrget_client(), vsomeip_test::TEST_CLIENT_CLIENT_ID); ASSERT_EQ(_response->get_session(), static_cast(number_of_acknowledged_messages_)); + if(number_of_acknowledged_messages_ == number_of_messages_to_send_) { + std::lock_guard its_lock(mutex_); + blocked_ = true; + condition_.notify_one(); + } } void header_factory_test_client::send() @@ -128,8 +129,12 @@ void header_factory_test_client::run() { condition_.wait(its_lock); } + blocked_ = false; + request_->set_service(vsomeip_test::TEST_SERVICE_SERVICE_ID); + request_->set_instance(vsomeip_test::TEST_SERVICE_INSTANCE_ID); + request_->set_method(vsomeip_test::TEST_SERVICE_METHOD_ID); - for (int i = 0; i < number_of_messages_to_send_; i++) + for (uint32_t i = 0; i < number_of_messages_to_send_; i++) { app_->send(request_, true); VSOMEIP_INFO << "Client/Session [" << std::setw(4) << std::setfill('0') @@ -141,14 +146,10 @@ void header_factory_test_client::run() << request_->get_instance() << "]"; number_of_sent_messages_++; } - blocked_ = false; - // wait until all send messages has been acknowledged, but a maximum of 5 sec. - int cnt = 0; - while (number_of_acknowledged_messages_ != number_of_messages_to_send_ - && cnt < 5) + // wait until all messages have been acknowledged + while (!blocked_) { - std::this_thread::sleep_for(std::chrono::seconds(1)); - cnt++; + condition_.wait(its_lock); } stop(); } diff --git a/test/header_factory_tests/header_factory_test_client.hpp b/test/header_factory_tests/header_factory_test_client.hpp index 51803a1..a68627e 100644 --- a/test/header_factory_tests/header_factory_test_client.hpp +++ b/test/header_factory_tests/header_factory_test_client.hpp @@ -25,7 +25,7 @@ public: void start(); void stop(); void join_sender_thread(); - void on_event(vsomeip::event_type_e _event); + void on_state(vsomeip::state_type_e _state); void on_availability(vsomeip::service_t _service, vsomeip::instance_t _instance, bool _is_available); void on_message(const std::shared_ptr &_response); diff --git a/test/header_factory_tests/header_factory_test_client.json b/test/header_factory_tests/header_factory_test_client.json index d0523b3..71bc75b 100644 --- a/test/header_factory_tests/header_factory_test_client.json +++ b/test/header_factory_tests/header_factory_test_client.json @@ -21,78 +21,77 @@ "id" : "0x1343" } ], + "services" : + [ + { + "service" : "0x1234", + "instance" : "0x5678", + "unreliable" : "30509", + "events" : + [ + { + "event" : "0x0777", + "is_field" : "true" + }, - "servicegroups" : - [ - { - "name" : "remote", - "unicast" : "127.0.0.1", - "services" : - [ - { - "service" : "0x1234", - "instance" : "0x5678", - "unreliable" : "30509", - "events" : - [ - { - "event" : "0x0777", - "is_field" : "true" - }, - - { - "event" : "0x0778", - "is_field" : "false" - }, + { + "event" : "0x0778", + "is_field" : "false" + }, - { - "event" : "0x0779", - "is_field" : "true" - } - ], + { + "event" : "0x0779", + "is_field" : "true" + } + ], - "eventgroups" : - [ - { - "eventgroup" : "0x4455", - "events" : - [ - "0x777", - "0x778" - ] - }, + "eventgroups" : + [ + { + "eventgroup" : "0x4455", + "events" : + [ + "0x777", + "0x778" + ] + }, - { - "eventgroup" : "0x4465", - "events" : - [ - "0x778", - "0x779" - ], + { + "eventgroup" : "0x4465", + "events" : + [ + "0x778", + "0x779" + ], - "is_multicast" : "true" - }, + "is_multicast" : "true" + }, - { - "eventgroup" : "0x4555", - "events" : - [ - "0x777", - "0x779" - ] - } - ] - } - ] + { + "eventgroup" : "0x4555", + "events" : + [ + "0x777", + "0x779" + ] + } + ] } ], "routing" : "header_factory_test_service", "service-discovery" : { - "enable" : "false", - "multicast" : "224.0.0.1", - "port" : "30491", - "protocol" : "udp" + "enable" : "false", + "multicast" : "224.0.0.1", + "port" : "30491", + "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" } } \ No newline at end of file diff --git a/test/header_factory_tests/header_factory_test_client_start.sh b/test/header_factory_tests/header_factory_test_client_start.sh index d8696cb..b500060 100755 --- a/test/header_factory_tests/header_factory_test_client_start.sh +++ b/test/header_factory_tests/header_factory_test_client_start.sh @@ -4,5 +4,5 @@ # 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/. export VSOMEIP_APPLICATION_NAME=header_factory_test_client -export VSOMEIP_CONFIGURATION_FILE=header_factory_test_client.json +export VSOMEIP_CONFIGURATION=header_factory_test_client.json ./header_factory_test_client diff --git a/test/header_factory_tests/header_factory_test_send_receive_starter.sh b/test/header_factory_tests/header_factory_test_send_receive_starter.sh index 094dfd4..74f8504 100755 --- a/test/header_factory_tests/header_factory_test_send_receive_starter.sh +++ b/test/header_factory_tests/header_factory_test_send_receive_starter.sh @@ -12,13 +12,13 @@ # Start the service export VSOMEIP_APPLICATION_NAME=header_factory_test_service -export VSOMEIP_CONFIGURATION_FILE=header_factory_test_service.json +export VSOMEIP_CONFIGURATION=header_factory_test_service.json ./header_factory_test_service & sleep 1; # Start the client export VSOMEIP_APPLICATION_NAME=header_factory_test_client -export VSOMEIP_CONFIGURATION_FILE=header_factory_test_client.json +export VSOMEIP_CONFIGURATION=header_factory_test_client.json ./header_factory_test_client & # Wait until client and service are finished diff --git a/test/header_factory_tests/header_factory_test_service.cpp b/test/header_factory_tests/header_factory_test_service.cpp index cbdc5a6..9879b48 100644 --- a/test/header_factory_tests/header_factory_test_service.cpp +++ b/test/header_factory_tests/header_factory_test_service.cpp @@ -10,9 +10,9 @@ header_factory_test_service::header_factory_test_service(bool _use_static_routing) : app_(vsomeip::runtime::get()->create_application()), is_registered_(false), - blocked_(false), use_static_routing_(_use_static_routing), offer_thread_(std::bind(&header_factory_test_service::run, this)), + blocked_(false), number_of_received_messages_(0) { } @@ -27,8 +27,8 @@ void header_factory_test_service::init() std::bind(&header_factory_test_service::on_message, this, std::placeholders::_1)); - app_->register_event_handler( - std::bind(&header_factory_test_service::on_event, this, + app_->register_state_handler( + std::bind(&header_factory_test_service::on_state, this, std::placeholders::_1)); VSOMEIP_INFO << "Static routing " << (use_static_routing_ ? "ON" : "OFF"); @@ -45,8 +45,10 @@ 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_event_handler(); + app_->unregister_state_handler(); app_->stop(); + std::thread t([](){ usleep(1000000 * 5);}); + t.join(); } void header_factory_test_service::join_offer_thread() @@ -66,13 +68,13 @@ void header_factory_test_service::stop_offer() vsomeip_test::TEST_SERVICE_INSTANCE_ID); } -void header_factory_test_service::on_event(vsomeip::event_type_e _event) +void header_factory_test_service::on_state(vsomeip::state_type_e _state) { VSOMEIP_INFO << "Application " << app_->get_name() << " is " - << (_event == vsomeip::event_type_e::ET_REGISTERED ? "registered." : + << (_state == vsomeip::state_type_e::ST_REGISTERED ? "registered." : "deregistered."); - if(_event == vsomeip::event_type_e::ET_REGISTERED) + if(_state == vsomeip::state_type_e::ST_REGISTERED) { if(!is_registered_) { @@ -122,7 +124,9 @@ void header_factory_test_service::on_message(const std::shared_ptr= vsomeip_test::NUMBER_OF_MESSAGES_TO_SEND) { - app_->stop(); + std::lock_guard its_lock(mutex_); + blocked_ =true; + condition_.notify_one(); } ASSERT_LT(number_of_received_messages_, vsomeip_test::NUMBER_OF_MESSAGES_TO_SEND + 1); @@ -134,10 +138,17 @@ void header_factory_test_service::run() while (!blocked_) condition_.wait(its_lock); + blocked_ = false; if(use_static_routing_) { offer(); } + while (!blocked_) + condition_.wait(its_lock); + + std::thread t([](){ usleep(1000000 * 5);}); + t.join(); + app_->stop(); } TEST(someip_header_factory_test, reveice_message_ten_times_test) diff --git a/test/header_factory_tests/header_factory_test_service.hpp b/test/header_factory_tests/header_factory_test_service.hpp index 0c2df1c..99f5b09 100644 --- a/test/header_factory_tests/header_factory_test_service.hpp +++ b/test/header_factory_tests/header_factory_test_service.hpp @@ -26,7 +26,7 @@ public: void offer(); void stop_offer(); void join_offer_thread(); - void on_event(vsomeip::event_type_e _event); + void on_state(vsomeip::state_type_e _state); void on_message(const std::shared_ptr &_request); void run(); diff --git a/test/header_factory_tests/header_factory_test_service.json b/test/header_factory_tests/header_factory_test_service.json index cb403cb..a99d0a2 100644 --- a/test/header_factory_tests/header_factory_test_service.json +++ b/test/header_factory_tests/header_factory_test_service.json @@ -1,118 +1,105 @@ { - "unicast" : "127.0.0.1", - "logging" : - { - "level" : "debug", - "console" : "true", - "file" : - { - "enable" : "false", - "path" : "/tmp/vsomeip.log" - }, + "unicast" : "127.0.0.1", + "logging" : + { + "level" : "debug", + "console" : "true", + "file" : + { + "enable" : "false", + "path" : "/tmp/vsomeip.log" + }, + "dlt" : "false" + }, - "dlt" : "false" - }, + "applications" : + [ + { + "name" : "header_factory_test_service", + "id" : "0x1277" + } + ], - "applications" : - [ - { - "name" : "header_factory_test_service", - "id" : "0x1277" - } - ], - - "servicegroups" : - [ - { - "name" : "default", - "delays" : - { - "initial" : + "services" : + [ + { + "service" : "0x1234", + "instance" : "0x5678", + "unreliable" : "30509", + "multicast" : { - "minimum" : "10", - "maximum" : "100" + "address" : "224.225.226.233", + "port" : "32344" }, - "repetition-base" : "200", - "repetition-max" : "3", - "cyclic-offer" : "2000", - "cyclic-request" : "2001" - }, - - "services" : - [ - { - "service" : "0x1234", - "instance" : "0x5678", - "unreliable" : "30509", - "multicast" : - { - "address" : "224.225.226.233", - "port" : "32344" - }, + "events" : + [ + { + "event" : "0x0777", + "is_field" : "true", + "update-cycle" : 2000 + }, - "events" : - [ - { - "event" : "0x0777", - "is_field" : "true", - "update-cycle" : 2000 - }, + { + "event" : "0x0778", + "is_field" : "true", + "update-cycle" : 0 + }, - { - "event" : "0x0778", - "is_field" : "true", - "update-cycle" : 0 - }, + { + "event" : "0x0779", + "is_field" : "true" + } + ], - { - "event" : "0x0779", - "is_field" : "true" - } - ], - - "eventgroups" : - [ - { - "eventgroup" : "0x4455", - "events" : - [ + "eventgroups" : + [ + { + "eventgroup" : "0x4455", + "events" : + [ "0x777", "0x778" - ] - }, + ] + }, - { - "eventgroup" : "0x4465", - "events" : - [ - "0x778", - "0x779" - ], + { + "eventgroup" : "0x4465", + "events" : + [ + "0x778", + "0x779" + ], - "is_multicast" : "true" - }, + "is_multicast" : "true" + }, - { - "eventgroup" : "0x4555", - "events" : - [ + { + "eventgroup" : "0x4555", + "events" : + [ "0x777", - "0x779" - ] - } - ] - } - ] - } - ], + "0x779" + ] + } + ] + } + ], + + "routing" : "header_factory_test_service", - "routing" : "header_factory_test_service", - "service-discovery" : - { - "enable" : "false", - "multicast" : "224.0.0.1", - "port" : "30490", - "protocol" : "udp" - } + "service-discovery" : + { + "enable" : "false", + "multicast" : "224.0.0.1", + "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" + } } \ No newline at end of file diff --git a/test/header_factory_tests/header_factory_test_service_start.sh b/test/header_factory_tests/header_factory_test_service_start.sh index e0e4c2d..437ecdd 100755 --- a/test/header_factory_tests/header_factory_test_service_start.sh +++ b/test/header_factory_tests/header_factory_test_service_start.sh @@ -5,5 +5,5 @@ # file, You can obtain one at http://mozilla.org/MPL/2.0/. export VSOMEIP_APPLICATION_NAME=header_factory_test_service -export VSOMEIP_CONFIGURATION_FILE=header_factory_test_service.json +export VSOMEIP_CONFIGURATION=header_factory_test_service.json ./header_factory_test_service diff --git a/test/magic-cookies-test-client.cpp b/test/magic-cookies-test-client.cpp deleted file mode 100644 index a2f7681..0000000 --- a/test/magic-cookies-test-client.cpp +++ /dev/null @@ -1,179 +0,0 @@ -// Copyright (C) 2015 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 -#include -#include -#include - -#include - -#include "../examples/sample-ids.hpp" -#include "../implementation/runtime/include/application_impl.hpp" -#include "../implementation/routing/include/routing_manager.hpp" - -class client_sample { -public: - client_sample() - : app_(new vsomeip::application_impl("")), - runner_(std::bind(&client_sample::run, this)), - is_available_(false), - is_blocked_(false) { - } - - void init() { - VSOMEIP_INFO << "Initializing..."; - app_->init(); - - app_->register_event_handler( - std::bind( - &client_sample::on_event, - this, - std::placeholders::_1)); - - app_->register_availability_handler(SAMPLE_SERVICE_ID, SAMPLE_INSTANCE_ID, - std::bind(&client_sample::on_availability, - this, - std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); - - app_->register_message_handler( - vsomeip::ANY_SERVICE, SAMPLE_INSTANCE_ID, vsomeip::ANY_METHOD, - std::bind(&client_sample::on_message, - this, - std::placeholders::_1)); - } - - void start() { - VSOMEIP_INFO << "Starting..."; - app_->start(); - } - - void stop() { - VSOMEIP_INFO << "Stopping..."; - app_->stop(); - } - - void on_event(vsomeip::event_type_e _event) { - if (_event == vsomeip::event_type_e::ET_REGISTERED) { - VSOMEIP_INFO << "Client registration done."; - app_->request_service(SAMPLE_SERVICE_ID, SAMPLE_INSTANCE_ID, false, - vsomeip::ANY_MAJOR, vsomeip::ANY_MINOR, - vsomeip::ANY_TTL); - } - } - - 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."); - - if (SAMPLE_SERVICE_ID == _service && SAMPLE_INSTANCE_ID == _instance) { - static bool is_available = false; - if (is_available && !_is_available) is_available = false; - else if (_is_available && !is_available) { - is_available = true; - std::lock_guard< std::mutex > its_lock(mutex_); - is_blocked_ = true; - condition_.notify_one(); - } - } - } - - void on_message(const std::shared_ptr< vsomeip::message > &_response) { - VSOMEIP_INFO << "Received a response from Service [" - << std::setw(4) << std::setfill('0') << std::hex << _response->get_service() - << "." - << std::setw(4) << std::setfill('0') << std::hex << _response->get_instance() - << "] to Client/Session [" - << std::setw(4) << std::setfill('0') << std::hex << _response->get_client() - << "/" - << std::setw(4) << std::setfill('0') << std::hex << _response->get_session() - << "]"; - } - - void join() { - runner_.join(); - } - - void run() { - std::unique_lock< std::mutex > its_lock(mutex_); - while (!is_blocked_) condition_.wait(its_lock); - VSOMEIP_INFO << "Running..."; - - vsomeip::routing_manager *its_routing = app_->get_routing_manager(); - - vsomeip::byte_t its_good_payload_data[] = { - 0x12, 0x34, 0x84, 0x21, - 0x00, 0x00, 0x00, 0x11, - 0x13, 0x43, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, - 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01 - }; - - vsomeip::byte_t its_bad_payload_data[] = { - 0x12, 0x34, 0x84, 0x21, - 0x00, 0x00, 0x01, 0x23, - 0x13, 0x43, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, - 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01 - }; - - // Test sequence - its_good_payload_data[11] = 0x01; - its_routing->send(0x1343, its_good_payload_data, sizeof(its_good_payload_data), SAMPLE_INSTANCE_ID, true, true); - its_bad_payload_data[11] = 0x02; - its_routing->send(0x1343, its_bad_payload_data, sizeof(its_bad_payload_data), SAMPLE_INSTANCE_ID, true, true); - its_good_payload_data[11] = 0x03; - its_routing->send(0x1343, its_good_payload_data, sizeof(its_good_payload_data), SAMPLE_INSTANCE_ID, true, true); - its_bad_payload_data[11] = 0x04; - its_routing->send(0x1343, its_bad_payload_data, sizeof(its_bad_payload_data), SAMPLE_INSTANCE_ID, true, true); - its_bad_payload_data[11] = 0x05; - its_routing->send(0x1343, its_bad_payload_data, sizeof(its_bad_payload_data), SAMPLE_INSTANCE_ID, true, true); - its_good_payload_data[11] = 0x06; - its_routing->send(0x1343, its_good_payload_data, sizeof(its_good_payload_data), SAMPLE_INSTANCE_ID, true, true); - its_good_payload_data[11] = 0x07; - its_routing->send(0x1343, its_good_payload_data, sizeof(its_good_payload_data), SAMPLE_INSTANCE_ID, true, true); - its_bad_payload_data[11] = 0x08; - its_routing->send(0x1343, its_bad_payload_data, sizeof(its_bad_payload_data), SAMPLE_INSTANCE_ID, true, true); - its_bad_payload_data[11] = 0x09; - its_routing->send(0x1343, its_bad_payload_data, sizeof(its_bad_payload_data), SAMPLE_INSTANCE_ID, true, true); - its_bad_payload_data[11] = 0x0A; - its_routing->send(0x1343, its_bad_payload_data, sizeof(its_bad_payload_data), SAMPLE_INSTANCE_ID, true, true); - its_good_payload_data[11] = 0x0B; - its_routing->send(0x1343, its_good_payload_data, sizeof(its_good_payload_data), SAMPLE_INSTANCE_ID, true, true); - its_good_payload_data[11] = 0x0C; - its_routing->send(0x1343, its_good_payload_data, sizeof(its_good_payload_data), SAMPLE_INSTANCE_ID, true, true); - its_good_payload_data[11] = 0x0D; - its_routing->send(0x1343, its_good_payload_data, sizeof(its_good_payload_data), SAMPLE_INSTANCE_ID, true, true); - its_bad_payload_data[11] = 0x0E; - its_routing->send(0x1343, its_bad_payload_data, sizeof(its_bad_payload_data), SAMPLE_INSTANCE_ID, true, true); - its_good_payload_data[11] = 0x0F; - its_routing->send(0x1343, its_good_payload_data, sizeof(its_good_payload_data), SAMPLE_INSTANCE_ID, true, true); - - std::this_thread::sleep_for(std::chrono::milliseconds(2000)); - stop(); - } - -private: - std::shared_ptr< vsomeip::application_impl > app_; - std::thread runner_; - std::mutex mutex_; - std::condition_variable condition_; - bool is_available_; - bool is_blocked_; -}; - - -int main(int argc, char **argv) { - client_sample its_client; - its_client.init(); - its_client.start(); - its_client.join(); - return 0; -} - - diff --git a/test/magic_cookies_test_client_start.sh b/test/magic_cookies_test_client_start.sh deleted file mode 100755 index 45ee754..0000000 --- a/test/magic_cookies_test_client_start.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/bash -# Copyright (C) 2015 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/. - -export VSOMEIP_APPLICATION_NAME=client-sample -export VSOMEIP_CONFIGURATION_FILE=vsomeip-magic-cookies-client.json -./magic-cookies-test-client diff --git a/test/magic_cookies_test_service_start.sh b/test/magic_cookies_test_service_start.sh deleted file mode 100755 index 0d946ab..0000000 --- a/test/magic_cookies_test_service_start.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/bash -# Copyright (C) 2015 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/. - -export VSOMEIP_APPLICATION_NAME=service-sample -export VSOMEIP_CONFIGURATION_FILE=vsomeip-magic-cookies-service.json -.././response-sample --tcp --static-routing diff --git a/test/magic_cookies_test_starter.sh b/test/magic_cookies_test_starter.sh deleted file mode 100755 index c7ec3f7..0000000 --- a/test/magic_cookies_test_starter.sh +++ /dev/null @@ -1,90 +0,0 @@ -#!/bin/bash -# Copyright (C) 2015 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 -# Parameter 2: number of TCP/UDP sockets the process should have open -check_tcp_udp_sockets_are_open () -{ - # Check that the passed pid/process does listen on at least one 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 -lt $2 ] - then - ((FAIL+=1)) - fi -} - -# Parameter 1: the pid to check -check_tcp_udp_sockets_are_closed () -{ - # Check that the passed pid/process 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 -} - -# Display a message to show the user that he must now call the external service -# to finish the test successfully -cat < +#include +#include +#include +#include + +#include + +#include "../someip_test_globals.hpp" +#include "../implementation/runtime/include/application_impl.hpp" +#include "../implementation/routing/include/routing_manager.hpp" + +class magic_cookies_test_client { +public: + magic_cookies_test_client() + : app_(new vsomeip::application_impl("")), + is_available_(false), + is_blocked_(false), + runner_(std::bind(&magic_cookies_test_client::run, this)) { + } + + void init() { + VSOMEIP_INFO << "Initializing..."; + app_->init(); + + app_->register_state_handler( + std::bind( + &magic_cookies_test_client::on_state, + this, + std::placeholders::_1)); + + app_->register_message_handler( + vsomeip::ANY_SERVICE, vsomeip_test::TEST_SERVICE_INSTANCE_ID, vsomeip::ANY_METHOD, + std::bind(&magic_cookies_test_client::on_message, + this, + std::placeholders::_1)); + + app_->register_availability_handler(vsomeip_test::TEST_SERVICE_SERVICE_ID, vsomeip_test::TEST_SERVICE_INSTANCE_ID, + std::bind(&magic_cookies_test_client::on_availability, + this, + std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); + } + + void start() { + VSOMEIP_INFO << "Starting..."; + app_->start(); + } + + void stop() { + VSOMEIP_INFO << "Stopping..."; + app_->stop(); + } + + void on_state(vsomeip::state_type_e _state) { + if (_state == vsomeip::state_type_e::ST_REGISTERED) { + VSOMEIP_INFO << "Client registration done."; + app_->request_service(vsomeip_test::TEST_SERVICE_SERVICE_ID, + vsomeip_test::TEST_SERVICE_INSTANCE_ID, + vsomeip::ANY_MAJOR, vsomeip::ANY_MINOR, + false); + } + } + + 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."); + + if (vsomeip_test::TEST_SERVICE_SERVICE_ID == _service && vsomeip_test::TEST_SERVICE_INSTANCE_ID == _instance) { + static bool is_available = false; + if (is_available && !_is_available) is_available = false; + else if (_is_available && !is_available) { + is_available = true; + std::lock_guard< std::mutex > its_lock(mutex_); + is_blocked_ = true; + condition_.notify_one(); + } + } + } + + void on_message(const std::shared_ptr< vsomeip::message > &_response) { + if (_response->get_return_code() == vsomeip::return_code_e::E_OK) { + VSOMEIP_INFO << "Received a response from Service [" + << std::setw(4) << std::setfill('0') << std::hex << _response->get_service() + << "." + << std::setw(4) << std::setfill('0') << std::hex << _response->get_instance() + << "] to Client/Session [" + << std::setw(4) << std::setfill('0') << std::hex << _response->get_client() + << "/" + << std::setw(4) << std::setfill('0') << std::hex << _response->get_session() + << "]"; + } else if (_response->get_return_code() == vsomeip::return_code_e::E_MALFORMED_MESSAGE) { + VSOMEIP_INFO << "Received an error message from Service [" + << std::setw(4) << std::setfill('0') << std::hex << _response->get_service() + << "." + << std::setw(4) << std::setfill('0') << std::hex << _response->get_instance() + << "] to Client/Session [" + << std::setw(4) << std::setfill('0') << std::hex << _response->get_client() + << "/" + << std::setw(4) << std::setfill('0') << std::hex << _response->get_session() + << "]"; + } + } + + void join() { + runner_.join(); + } + + void run() { + std::unique_lock< std::mutex > its_lock(mutex_); + while (!is_blocked_) condition_.wait(its_lock); + VSOMEIP_INFO << "Running..."; + + vsomeip::routing_manager *its_routing = app_->get_routing_manager(); + + vsomeip::byte_t its_good_payload_data[] = { + 0x12, 0x34, 0x84, 0x21, + 0x00, 0x00, 0x00, 0x11, + 0x13, 0x43, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, + 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01 + }; + + vsomeip::byte_t its_bad_payload_data[] = { + 0x12, 0x34, 0x84, 0x21, + 0x00, 0x00, 0x01, 0x23, + 0x13, 0x43, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, + 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01 + }; + + // Test sequence + its_good_payload_data[11] = 0x01; + its_routing->send(0x1343, its_good_payload_data, sizeof(its_good_payload_data), vsomeip_test::TEST_SERVICE_INSTANCE_ID, true, true); + its_bad_payload_data[11] = 0x02; + its_routing->send(0x1343, its_bad_payload_data, sizeof(its_bad_payload_data), vsomeip_test::TEST_SERVICE_INSTANCE_ID, true, true); + its_good_payload_data[11] = 0x03; + its_routing->send(0x1343, its_good_payload_data, sizeof(its_good_payload_data), vsomeip_test::TEST_SERVICE_INSTANCE_ID, true, true); + its_bad_payload_data[11] = 0x04; + its_routing->send(0x1343, its_bad_payload_data, sizeof(its_bad_payload_data), vsomeip_test::TEST_SERVICE_INSTANCE_ID, true, true); + its_bad_payload_data[11] = 0x05; + its_routing->send(0x1343, its_bad_payload_data, sizeof(its_bad_payload_data), vsomeip_test::TEST_SERVICE_INSTANCE_ID, true, true); + its_good_payload_data[11] = 0x06; + its_routing->send(0x1343, its_good_payload_data, sizeof(its_good_payload_data), vsomeip_test::TEST_SERVICE_INSTANCE_ID, true, true); + its_good_payload_data[11] = 0x07; + its_routing->send(0x1343, its_good_payload_data, sizeof(its_good_payload_data), vsomeip_test::TEST_SERVICE_INSTANCE_ID, true, true); + its_bad_payload_data[11] = 0x08; + its_routing->send(0x1343, its_bad_payload_data, sizeof(its_bad_payload_data), vsomeip_test::TEST_SERVICE_INSTANCE_ID, true, true); + its_bad_payload_data[11] = 0x09; + its_routing->send(0x1343, its_bad_payload_data, sizeof(its_bad_payload_data), vsomeip_test::TEST_SERVICE_INSTANCE_ID, true, true); + its_bad_payload_data[11] = 0x0A; + its_routing->send(0x1343, its_bad_payload_data, sizeof(its_bad_payload_data), vsomeip_test::TEST_SERVICE_INSTANCE_ID, true, true); + its_good_payload_data[11] = 0x0B; + its_routing->send(0x1343, its_good_payload_data, sizeof(its_good_payload_data), vsomeip_test::TEST_SERVICE_INSTANCE_ID, true, true); + its_good_payload_data[11] = 0x0C; + its_routing->send(0x1343, its_good_payload_data, sizeof(its_good_payload_data), vsomeip_test::TEST_SERVICE_INSTANCE_ID, true, true); + its_good_payload_data[11] = 0x0D; + its_routing->send(0x1343, its_good_payload_data, sizeof(its_good_payload_data), vsomeip_test::TEST_SERVICE_INSTANCE_ID, true, true); + its_bad_payload_data[11] = 0x0E; + its_routing->send(0x1343, its_bad_payload_data, sizeof(its_bad_payload_data), vsomeip_test::TEST_SERVICE_INSTANCE_ID, true, true); + its_good_payload_data[11] = 0x0F; + its_routing->send(0x1343, its_good_payload_data, sizeof(its_good_payload_data), vsomeip_test::TEST_SERVICE_INSTANCE_ID, true, true); + + std::this_thread::sleep_for(std::chrono::milliseconds(2000)); + stop(); + } + +private: + std::shared_ptr< vsomeip::application_impl > app_; + std::mutex mutex_; + std::condition_variable condition_; + bool is_available_; + bool is_blocked_; + std::thread runner_; +}; + + +int main() { + magic_cookies_test_client its_client; + its_client.init(); + its_client.start(); + its_client.join(); + return 0; +} + + diff --git a/test/magic_cookies_tests/magic_cookies_test_client_start.sh b/test/magic_cookies_tests/magic_cookies_test_client_start.sh new file mode 100755 index 0000000..ba4f662 --- /dev/null +++ b/test/magic_cookies_tests/magic_cookies_test_client_start.sh @@ -0,0 +1,9 @@ +#!/bin/bash +# Copyright (C) 2015 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/. + +export VSOMEIP_APPLICATION_NAME=magic_cookies_test_client +export VSOMEIP_CONFIGURATION=magic_cookies_test_client.json +./magic_cookies_test_client diff --git a/test/magic_cookies_tests/magic_cookies_test_service.cpp b/test/magic_cookies_tests/magic_cookies_test_service.cpp new file mode 100644 index 0000000..35e1d77 --- /dev/null +++ b/test/magic_cookies_tests/magic_cookies_test_service.cpp @@ -0,0 +1,155 @@ +// Copyright (C) 2014-2015 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 +#include +#include +#include +#include + +#include + +#include "../someip_test_globals.hpp" + +class magic_cookies_test_service { +public: + magic_cookies_test_service(bool _use_static_routing) : + app_(vsomeip::runtime::get()->create_application()), + is_registered_(false), + use_static_routing_(_use_static_routing), + blocked_(false), + offer_thread_(std::bind(&magic_cookies_test_service::run, this)) { + } + + ~magic_cookies_test_service() { + offer_thread_.join(); + } + void init() { + std::lock_guard its_lock(mutex_); + + app_->init(); + app_->register_message_handler( + vsomeip_test::TEST_SERVICE_SERVICE_ID, + vsomeip_test::TEST_SERVICE_INSTANCE_ID, + vsomeip_test::TEST_SERVICE_METHOD_ID, + std::bind(&magic_cookies_test_service::on_message, this, + std::placeholders::_1)); + + app_->register_state_handler( + std::bind(&magic_cookies_test_service::on_state, this, + std::placeholders::_1)); + + VSOMEIP_INFO<< "Static routing " << (use_static_routing_ ? "ON" : "OFF"); + } + + void start() { + app_->start(); + } + + void offer() { + app_->offer_service(vsomeip_test::TEST_SERVICE_SERVICE_ID, vsomeip_test::TEST_SERVICE_INSTANCE_ID); + } + + void stop_offer() { + app_->stop_offer_service(vsomeip_test::TEST_SERVICE_SERVICE_ID, vsomeip_test::TEST_SERVICE_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) { + if (!is_registered_) { + is_registered_ = true; + blocked_ = true; + condition_.notify_one(); + } + } else { + is_registered_ = false; + } + } + + void on_message(const std::shared_ptr &_request) { + VSOMEIP_INFO << "Received a message with Client/Session [" << std::setw(4) + << std::setfill('0') << std::hex << _request->get_client() << "/" + << std::setw(4) << std::setfill('0') << std::hex + << _request->get_session() << "]"; + + std::shared_ptr its_response = vsomeip::runtime::get() + ->create_response(_request); + + std::shared_ptr its_payload = vsomeip::runtime::get() + ->create_payload(); + std::vector its_payload_data; + for (std::size_t i = 0; i < 120; ++i) + its_payload_data.push_back(i % 256); + its_payload->set_data(its_payload_data); + its_response->set_payload(its_payload); + + app_->send(its_response, true); + if(_request->get_session() == 0x0F) { + std::lock_guard its_lock(mutex_); + blocked_ = true; + condition_.notify_one(); + } + } + + void run() { + std::unique_lock its_lock(mutex_); + while (!blocked_) + condition_.wait(its_lock); + + bool is_offer(true); + blocked_ = false; + + if (use_static_routing_) { + offer(); + while (!blocked_) { + condition_.wait(its_lock); + } + std::this_thread::sleep_for(std::chrono::milliseconds(5)); + app_->stop(); + } else { + while (true) { + if (is_offer) + offer(); + else + stop_offer(); + std::this_thread::sleep_for(std::chrono::milliseconds(10000)); + is_offer = !is_offer; + } + } + } + +private: + std::shared_ptr app_; + bool is_registered_; + bool use_static_routing_; + + std::mutex mutex_; + std::condition_variable condition_; + bool blocked_; + std::thread offer_thread_; +}; + +int main(int argc, char **argv) { + bool use_static_routing(false); + + std::string static_routing_enable("--static-routing"); + + for (int i = 1; i < argc; i++) { + if (static_routing_enable == argv[i]) { + use_static_routing = true; + } + } + + magic_cookies_test_service its_sample(use_static_routing); + its_sample.init(); + its_sample.start(); + + return 0; +} diff --git a/test/magic_cookies_tests/magic_cookies_test_service_start.sh b/test/magic_cookies_tests/magic_cookies_test_service_start.sh new file mode 100755 index 0000000..4261ed5 --- /dev/null +++ b/test/magic_cookies_tests/magic_cookies_test_service_start.sh @@ -0,0 +1,9 @@ +#!/bin/bash +# Copyright (C) 2015 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/. + +export VSOMEIP_APPLICATION_NAME=magic_cookies_test_service +export VSOMEIP_CONFIGURATION=magic_cookies_test_service.json +./magic_cookies_test_service --tcp --static-routing diff --git a/test/magic_cookies_tests/magic_cookies_test_starter.sh b/test/magic_cookies_tests/magic_cookies_test_starter.sh new file mode 100755 index 0000000..ac97d61 --- /dev/null +++ b/test/magic_cookies_tests/magic_cookies_test_starter.sh @@ -0,0 +1,90 @@ +#!/bin/bash +# Copyright (C) 2015 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 successfully. + +FAIL=0 + +# Parameter 1: the pid to check +# Parameter 2: number of TCP/UDP sockets the process should have open +check_tcp_udp_sockets_are_open () +{ + # Check that the passed pid/process does listen on at least one 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 -lt $2 ] + then + ((FAIL+=1)) + fi +} + +# Parameter 1: the pid to check +check_tcp_udp_sockets_are_closed () +{ + # Check that the passed pid/process 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 +} + +# Display a message to show the user that he must now call the external service +# to finish the test successfully +cat < to continue the test +******************************************************************************* +******************************************************************************* +End-of-message +read + +# Start the client for magic-cookies test +export VSOMEIP_APPLICATION_NAME=magic_cookies_test_client +export VSOMEIP_CONFIGURATION=magic_cookies_test_client.json +./magic_cookies_test_client & +CLIENT_PID=$! + +# Wait until client is finished +for job in $(jobs -p) +do + # Fail gets incremented if either client or service exit + # with a non-zero exit code + wait $job || ((FAIL+=1)) +done + +# Check if server exited successfully +if [ $FAIL -eq 0 ] +then + exit 0 +else + exit 1 +fi diff --git a/test/payload_tests/conf/external_local_payload_test_client_external.json.in b/test/payload_tests/conf/external_local_payload_test_client_external.json.in new file mode 100644 index 0000000..d027a6f --- /dev/null +++ b/test/payload_tests/conf/external_local_payload_test_client_external.json.in @@ -0,0 +1,48 @@ +{ + "unicast" : "@TEST_IP_SLAVE@", + "netmask" : "255.255.255.0", + "logging" : + { + "level" : "debug", + "console" : "true", + "file" : + { + "enable" : "true", + "path" : "/var/log/vsomeip.log" + }, + + "dlt" : "true" + }, + + "applications" : + [ + { + "name" : "external_local_payload_test_client_external", + "id" : "0x1343" + } + ], + + "services" : + [ + { + "service" : "0x1234", + "instance" : "0x5678", + "unicast" : "@TEST_IP_MASTER@", + "unreliable" : "30509", + "reliable" : + { + "port" : "30510", + "enable-magic-cookies" : "false" + } + } + ], + + "routing" : "external_local_payload_test_client_external", + "service-discovery" : + { + "enable" : "false", + "multicast" : "224.0.0.1", + "port" : "30491", + "protocol" : "udp" + } +} diff --git a/test/payload_tests/conf/external_local_payload_test_client_local.json.in b/test/payload_tests/conf/external_local_payload_test_client_local.json.in new file mode 100644 index 0000000..40f40ca --- /dev/null +++ b/test/payload_tests/conf/external_local_payload_test_client_local.json.in @@ -0,0 +1,49 @@ +{ + "unicast" : "@TEST_IP_MASTER@", + "netmask" : "255.255.255.0", + "logging" : + { + "level" : "debug", + "console" : "true", + "file" : + { + "enable" : "true", + "path" : "/var/log/vsomeip.log" + }, + + "dlt" : "true" + }, + + "applications" : + [ + { + "name" : "external_local_payload_test_client_local", + "id" : "0x1343" + } + ], + + + "services" : + [ + { + "service" : "0x1234", + "instance" : "0x5678", + "unicast" : "@TEST_IP_MASTER@", + "unreliable" : "30509", + "reliable" : + { + "port" : "30510", + "enable-magic-cookies" : "false" + } + } + ], + + "routing" : "external_local_payload_test_service", + "service-discovery" : + { + "enable" : "false", + "multicast" : "224.0.0.1", + "port" : "30491", + "protocol" : "udp" + } +} diff --git a/test/payload_tests/conf/external_local_payload_test_service.json.in b/test/payload_tests/conf/external_local_payload_test_service.json.in new file mode 100644 index 0000000..dc7680c --- /dev/null +++ b/test/payload_tests/conf/external_local_payload_test_service.json.in @@ -0,0 +1,46 @@ +{ + "unicast" : "@TEST_IP_MASTER@", + "logging" : + { + "level" : "debug", + "console" : "true", + "file" : + { + "enable" : "false", + "path" : "/tmp/vsomeip.log" + }, + + "dlt" : "false" + }, + + "applications" : + [ + { + "name" : "external_local_payload_test_service", + "id" : "0x1277" + } + ], + + "services" : + [ + { + "service" : "0x1234", + "instance" : "0x5678", + "unreliable" : "30509", + "reliable" : + { + "port" : "30510", + "enable-magic-cookies" : "false" + } + } + ], + + "routing" : "external_local_payload_test_service", + "service-discovery" : + { + "enable" : "false", + "multicast" : "224.0.0.1", + "port" : "30490", + "protocol" : "udp" + } +} diff --git a/test/payload_tests/external_local_payload_test_client_external.json b/test/payload_tests/external_local_payload_test_client_external.json deleted file mode 100644 index 0f76ec0..0000000 --- a/test/payload_tests/external_local_payload_test_client_external.json +++ /dev/null @@ -1,54 +0,0 @@ -{ - "unicast" : "172.16.100.131", - "netmask" : "255.255.255.0", - "logging" : - { - "level" : "debug", - "console" : "true", - "file" : - { - "enable" : "true", - "path" : "/var/log/vsomeip.log" - }, - - "dlt" : "true" - }, - - "applications" : - [ - { - "name" : "external_local_payload_test_client_external", - "id" : "0x1343" - } - ], - - "servicegroups" : - [ - { - "name" : "remote", - "unicast" : "134.86.56.183", - "services" : - [ - { - "service" : "0x1234", - "instance" : "0x5678", - "unreliable" : "30509", - "reliable" : - { - "port" : "30510", - "enable-magic-cookies" : "false" - } - } - ] - } - ], - - "routing" : "external_local_payload_test_client_external", - "service-discovery" : - { - "enable" : "false", - "multicast" : "224.0.0.1", - "port" : "30491", - "protocol" : "udp" - } -} \ No newline at end of file diff --git a/test/payload_tests/external_local_payload_test_client_external_start.sh b/test/payload_tests/external_local_payload_test_client_external_start.sh index 87d403a..2ca6816 100755 --- a/test/payload_tests/external_local_payload_test_client_external_start.sh +++ b/test/payload_tests/external_local_payload_test_client_external_start.sh @@ -5,7 +5,7 @@ # file, You can obtain one at http://mozilla.org/MPL/2.0/. export VSOMEIP_APPLICATION_NAME=external_local_payload_test_client_external -export VSOMEIP_CONFIGURATION_FILE=external_local_payload_test_client_external.json +export VSOMEIP_CONFIGURATION=external_local_payload_test_client_external.json ./payload_test_client --udp --max-payload-size UDP # We sleep to let the service restart with --tcp option so we can test # communication via TCP. diff --git a/test/payload_tests/external_local_payload_test_client_external_starter.sh b/test/payload_tests/external_local_payload_test_client_external_starter.sh index f5c6ca5..225adba 100755 --- a/test/payload_tests/external_local_payload_test_client_external_starter.sh +++ b/test/payload_tests/external_local_payload_test_client_external_starter.sh @@ -50,7 +50,7 @@ check_tcp_udp_sockets_are_closed () # Start the service for payload test with UDP export VSOMEIP_APPLICATION_NAME=external_local_payload_test_service -export VSOMEIP_CONFIGURATION_FILE=external_local_payload_test_service.json +export VSOMEIP_CONFIGURATION=external_local_payload_test_service.json ./payload_test_service --udp & SERIVCE_PID=$! @@ -87,7 +87,7 @@ done # Start the service for payload test with tcp export VSOMEIP_APPLICATION_NAME=external_local_payload_test_service -export VSOMEIP_CONFIGURATION_FILE=external_local_payload_test_service.json +export VSOMEIP_CONFIGURATION=external_local_payload_test_service.json ./payload_test_service --tcp & SERIVCE_PID=$! diff --git a/test/payload_tests/external_local_payload_test_client_local.json b/test/payload_tests/external_local_payload_test_client_local.json deleted file mode 100644 index 78ae45a..0000000 --- a/test/payload_tests/external_local_payload_test_client_local.json +++ /dev/null @@ -1,54 +0,0 @@ -{ - "unicast" : "134.86.56.183", - "netmask" : "255.255.255.0", - "logging" : - { - "level" : "debug", - "console" : "true", - "file" : - { - "enable" : "true", - "path" : "/var/log/vsomeip.log" - }, - - "dlt" : "true" - }, - - "applications" : - [ - { - "name" : "external_local_payload_test_client_local", - "id" : "0x1343" - } - ], - - "servicegroups" : - [ - { - "name" : "remote", - "unicast" : "134.86.56.183", - "services" : - [ - { - "service" : "0x1234", - "instance" : "0x5678", - "unreliable" : "30509", - "reliable" : - { - "port" : "30510", - "enable-magic-cookies" : "false" - } - } - ] - } - ], - - "routing" : "external_local_payload_test_service", - "service-discovery" : - { - "enable" : "false", - "multicast" : "224.0.0.1", - "port" : "30491", - "protocol" : "udp" - } -} \ No newline at end of file diff --git a/test/payload_tests/external_local_payload_test_client_local_and_external_starter.sh b/test/payload_tests/external_local_payload_test_client_local_and_external_starter.sh index 038ada5..ba0bf15 100755 --- a/test/payload_tests/external_local_payload_test_client_local_and_external_starter.sh +++ b/test/payload_tests/external_local_payload_test_client_local_and_external_starter.sh @@ -50,7 +50,7 @@ check_tcp_udp_sockets_are_closed () # Start the service export VSOMEIP_APPLICATION_NAME=external_local_payload_test_service -export VSOMEIP_CONFIGURATION_FILE=external_local_payload_test_service.json +export VSOMEIP_CONFIGURATION=external_local_payload_test_service.json ./payload_test_service & SERIVCE_PID=$! sleep 1; @@ -60,7 +60,7 @@ check_tcp_udp_sockets_are_open $SERIVCE_PID 2 # Start the client which sends messages over local UDS export VSOMEIP_APPLICATION_NAME=external_local_payload_test_client_local -export VSOMEIP_CONFIGURATION_FILE=external_local_payload_test_client_local.json +export VSOMEIP_CONFIGURATION=external_local_payload_test_client_local.json ./payload_test_client --dont-shutdown-service & CLIENT_PID=$! sleep 1 @@ -104,7 +104,7 @@ done # Start the service for payload test with tcp export VSOMEIP_APPLICATION_NAME=external_local_payload_test_service -export VSOMEIP_CONFIGURATION_FILE=external_local_payload_test_service.json +export VSOMEIP_CONFIGURATION=external_local_payload_test_service.json ./payload_test_service --tcp & SERIVCE_PID=$! diff --git a/test/payload_tests/external_local_payload_test_client_local_start.sh b/test/payload_tests/external_local_payload_test_client_local_start.sh index fbf2633..87b9296 100755 --- a/test/payload_tests/external_local_payload_test_client_local_start.sh +++ b/test/payload_tests/external_local_payload_test_client_local_start.sh @@ -5,5 +5,5 @@ # file, You can obtain one at http://mozilla.org/MPL/2.0/. export VSOMEIP_APPLICATION_NAME=external_local_payload_test_client_local -export VSOMEIP_CONFIGURATION_FILE=external_local_payload_test_client_local.json +export VSOMEIP_CONFIGURATION=external_local_payload_test_client_local.json ./payload_test_client diff --git a/test/payload_tests/external_local_payload_test_client_local_starter.sh b/test/payload_tests/external_local_payload_test_client_local_starter.sh index 1c0ecbe..6fda55a 100755 --- a/test/payload_tests/external_local_payload_test_client_local_starter.sh +++ b/test/payload_tests/external_local_payload_test_client_local_starter.sh @@ -50,7 +50,7 @@ check_tcp_udp_sockets_are_closed () # Start the service export VSOMEIP_APPLICATION_NAME=external_local_payload_test_service -export VSOMEIP_CONFIGURATION_FILE=external_local_payload_test_service.json +export VSOMEIP_CONFIGURATION=external_local_payload_test_service.json ./payload_test_service & SERIVCE_PID=$! sleep 1; @@ -60,7 +60,7 @@ check_tcp_udp_sockets_are_open $SERIVCE_PID 2 # Start the client export VSOMEIP_APPLICATION_NAME=external_local_payload_test_client_local -export VSOMEIP_CONFIGURATION_FILE=external_local_payload_test_client_local.json +export VSOMEIP_CONFIGURATION=external_local_payload_test_client_local.json ./payload_test_client & CLIENT_PID=$! diff --git a/test/payload_tests/external_local_payload_test_service.json b/test/payload_tests/external_local_payload_test_service.json deleted file mode 100644 index 517b897..0000000 --- a/test/payload_tests/external_local_payload_test_service.json +++ /dev/null @@ -1,67 +0,0 @@ -{ - "unicast" : "134.86.56.183", - "logging" : - { - "level" : "debug", - "console" : "true", - "file" : - { - "enable" : "false", - "path" : "/tmp/vsomeip.log" - }, - - "dlt" : "false" - }, - - "applications" : - [ - { - "name" : "external_local_payload_test_service", - "id" : "0x1277" - } - ], - - "servicegroups" : - [ - { - "name" : "default", - "unicast" : "local", - "delays" : - { - "initial" : - { - "minimum" : "10", - "maximum" : "100" - }, - - "repetition-base" : "200", - "repetition-max" : "3", - "cyclic-offer" : "2000", - "cyclic-request" : "2001" - }, - - "services" : - [ - { - "service" : "0x1234", - "instance" : "0x5678", - "unreliable" : "30509", - "reliable" : - { - "port" : "30510", - "enable-magic-cookies" : "false" - } - } - ] - } - ], - - "routing" : "external_local_payload_test_service", - "service-discovery" : - { - "enable" : "false", - "multicast" : "224.0.0.1", - "port" : "30490", - "protocol" : "udp" - } -} \ No newline at end of file diff --git a/test/payload_tests/external_local_payload_test_service_client_external_start.sh b/test/payload_tests/external_local_payload_test_service_client_external_start.sh index 4230216..a41fd9d 100755 --- a/test/payload_tests/external_local_payload_test_service_client_external_start.sh +++ b/test/payload_tests/external_local_payload_test_service_client_external_start.sh @@ -5,7 +5,7 @@ # file, You can obtain one at http://mozilla.org/MPL/2.0/. export VSOMEIP_APPLICATION_NAME=external_local_payload_test_service -export VSOMEIP_CONFIGURATION_FILE=external_local_payload_test_service.json +export VSOMEIP_CONFIGURATION=external_local_payload_test_service.json ./payload_test_service --udp # After payload was measured with UDP the client will restart and measure # throughput with TCP diff --git a/test/payload_tests/external_local_payload_test_service_start.sh b/test/payload_tests/external_local_payload_test_service_start.sh index e1dc27d..45fbcc2 100755 --- a/test/payload_tests/external_local_payload_test_service_start.sh +++ b/test/payload_tests/external_local_payload_test_service_start.sh @@ -5,5 +5,5 @@ # file, You can obtain one at http://mozilla.org/MPL/2.0/. export VSOMEIP_APPLICATION_NAME=external_local_payload_test_service -export VSOMEIP_CONFIGURATION_FILE=external_local_payload_test_service.json +export VSOMEIP_CONFIGURATION=external_local_payload_test_service.json ./payload_test_service diff --git a/test/payload_tests/local_payload_test_client.json b/test/payload_tests/local_payload_test_client.json index 8ac8e79..24fa1fa 100644 --- a/test/payload_tests/local_payload_test_client.json +++ b/test/payload_tests/local_payload_test_client.json @@ -21,17 +21,8 @@ "id" : "0x1343" } ], - - "servicegroups" : - [ - { - "name" : "remote", - "unicast" : "127.0.0.1", - "services" : - [ - - ] - } + "services" : + [ ], "routing" : "local_payload_test_service", @@ -42,4 +33,4 @@ "port" : "30491", "protocol" : "udp" } -} \ No newline at end of file +} diff --git a/test/payload_tests/local_payload_test_client_start.sh b/test/payload_tests/local_payload_test_client_start.sh index 38c6e2a..ac157bc 100755 --- a/test/payload_tests/local_payload_test_client_start.sh +++ b/test/payload_tests/local_payload_test_client_start.sh @@ -5,5 +5,5 @@ # file, You can obtain one at http://mozilla.org/MPL/2.0/. export VSOMEIP_APPLICATION_NAME=local_payload_test_client -export VSOMEIP_CONFIGURATION_FILE=local_payload_test_client.json +export VSOMEIP_CONFIGURATION=local_payload_test_client.json ./payload_test_client diff --git a/test/payload_tests/local_payload_test_service.json b/test/payload_tests/local_payload_test_service.json index 776881c..b5c83a6 100644 --- a/test/payload_tests/local_payload_test_service.json +++ b/test/payload_tests/local_payload_test_service.json @@ -1,5 +1,5 @@ { - "unicast" : "134.86.56.183", + "unicast" : "127.0.0.1", "logging" : { "level" : "debug", @@ -21,32 +21,11 @@ } ], - "servicegroups" : + "services" : [ { - "name" : "default", - "unicast" : "local", - "delays" : - { - "initial" : - { - "minimum" : "10", - "maximum" : "100" - }, - - "repetition-base" : "200", - "repetition-max" : "3", - "cyclic-offer" : "2000", - "cyclic-request" : "2001" - }, - - "services" : - [ - { - "service" : "0x1234", - "instance" : "0x5678" - } - ] + "service" : "0x1234", + "instance" : "0x5678" } ], @@ -58,4 +37,4 @@ "port" : "30490", "protocol" : "udp" } -} \ No newline at end of file +} diff --git a/test/payload_tests/local_payload_test_service_start.sh b/test/payload_tests/local_payload_test_service_start.sh index a514e3a..8173a94 100755 --- a/test/payload_tests/local_payload_test_service_start.sh +++ b/test/payload_tests/local_payload_test_service_start.sh @@ -5,5 +5,5 @@ # file, You can obtain one at http://mozilla.org/MPL/2.0/. export VSOMEIP_APPLICATION_NAME=local_payload_test_service -export VSOMEIP_CONFIGURATION_FILE=local_payload_test_service.json +export VSOMEIP_CONFIGURATION=local_payload_test_service.json ./payload_test_service diff --git a/test/payload_tests/local_payload_test_starter.sh b/test/payload_tests/local_payload_test_starter.sh index 930da96..a2bc3d4 100755 --- a/test/payload_tests/local_payload_test_starter.sh +++ b/test/payload_tests/local_payload_test_starter.sh @@ -35,7 +35,7 @@ check_tcp_udp_sockets_are_closed () # Start the service export VSOMEIP_APPLICATION_NAME=local_payload_test_service -export VSOMEIP_CONFIGURATION_FILE=local_payload_test_service.json +export VSOMEIP_CONFIGURATION=local_payload_test_service.json ./payload_test_service & SERIVCE_PID=$! sleep 1; @@ -44,7 +44,7 @@ check_tcp_udp_sockets_are_closed $SERIVCE_PID # Start the client export VSOMEIP_APPLICATION_NAME=local_payload_test_client -export VSOMEIP_CONFIGURATION_FILE=local_payload_test_client.json +export VSOMEIP_CONFIGURATION=local_payload_test_client.json ./payload_test_client & CLIENT_PID=$! diff --git a/test/payload_tests/payload_test_client.cpp b/test/payload_tests/payload_test_client.cpp index 6151452..41bd577 100644 --- a/test/payload_tests/payload_test_client.cpp +++ b/test/payload_tests/payload_test_client.cpp @@ -8,7 +8,7 @@ enum class payloadsize : std::uint8_t { - UDS, TCP, UDP + UDS, TCP, UDP, USER_SPECIFIED }; // this variables are changed via cmdline parameters @@ -17,7 +17,8 @@ static bool call_service_sync = true; static std::uint32_t sliding_window_size = vsomeip_test::NUMBER_OF_MESSAGES_TO_SEND_PAYLOAD_TESTS; static payloadsize max_payload_size = payloadsize::UDS; static bool shutdown_service_at_end = true; - +static std::uint32_t user_defined_max_payload; +static std::uint32_t number_of_messages_to_send = 0; payload_test_client::payload_test_client( bool _use_tcp, @@ -30,7 +31,7 @@ payload_test_client::payload_test_client( sender_(std::bind(&payload_test_client::run, this)), blocked_(false), is_available_(false), - number_of_messages_to_send_(vsomeip_test::NUMBER_OF_MESSAGES_TO_SEND_PAYLOAD_TESTS), + number_of_messages_to_send_(number_of_messages_to_send ? number_of_messages_to_send : vsomeip_test::NUMBER_OF_MESSAGES_TO_SEND_PAYLOAD_TESTS), number_of_sent_messages_(0), number_of_sent_messages_total_(0), number_of_acknowledged_messages_(0), @@ -43,24 +44,20 @@ void payload_test_client::init() { app_->init(); - app_->register_event_handler( - std::bind(&payload_test_client::on_event, this, + app_->register_state_handler( + std::bind(&payload_test_client::on_state, this, std::placeholders::_1)); - app_->register_availability_handler(vsomeip_test::TEST_SERVICE_SERVICE_ID, - vsomeip_test::TEST_SERVICE_INSTANCE_ID, - std::bind(&payload_test_client::on_availability, this, - std::placeholders::_1, std::placeholders::_2, - std::placeholders::_3)); - app_->register_message_handler(vsomeip::ANY_SERVICE, vsomeip_test::TEST_SERVICE_INSTANCE_ID, vsomeip::ANY_METHOD, std::bind(&payload_test_client::on_message, this, std::placeholders::_1)); - request_->set_service(vsomeip_test::TEST_SERVICE_SERVICE_ID); - request_->set_instance(vsomeip_test::TEST_SERVICE_INSTANCE_ID); - request_->set_method(vsomeip_test::TEST_SERVICE_METHOD_ID); + app_->register_availability_handler(vsomeip_test::TEST_SERVICE_SERVICE_ID, + vsomeip_test::TEST_SERVICE_INSTANCE_ID, + std::bind(&payload_test_client::on_availability, this, + std::placeholders::_1, std::placeholders::_2, + std::placeholders::_3)); } void payload_test_client::start() @@ -79,11 +76,9 @@ void payload_test_client::stop() } app_->unregister_availability_handler(vsomeip_test::TEST_SERVICE_SERVICE_ID, vsomeip_test::TEST_SERVICE_INSTANCE_ID); - app_->unregister_event_handler(); + app_->unregister_state_handler(); app_->unregister_message_handler(vsomeip::ANY_SERVICE, vsomeip_test::TEST_SERVICE_INSTANCE_ID, vsomeip::ANY_METHOD); - - app_->stop(); } void payload_test_client::shutdown_service() @@ -99,9 +94,9 @@ void payload_test_client::join_sender_thread() sender_.join(); } -void payload_test_client::on_event(vsomeip::event_type_e _event) +void payload_test_client::on_state(vsomeip::state_type_e _state) { - if(_event == vsomeip::event_type_e::ET_REGISTERED) + if(_state == vsomeip::state_type_e::ST_REGISTERED) { app_->request_service(vsomeip_test::TEST_SERVICE_SERVICE_ID, vsomeip_test::TEST_SERVICE_INSTANCE_ID, false); @@ -150,16 +145,16 @@ void payload_test_client::on_message(const std::shared_ptr& _r else { // We notify the sender thread only if all sent messages have been acknowledged - if(number_of_acknowledged_messages_ % sliding_window_size == 0) + if(number_of_acknowledged_messages_ == number_of_messages_to_send_) { std::lock_guard lk(all_msg_acknowledged_mutex_); + number_of_acknowledged_messages_ = 0; all_msg_acknowledged_ = true; all_msg_acknowledged_cv_.notify_one(); } - if(number_of_acknowledged_messages_ == number_of_messages_to_send_) + else if(number_of_acknowledged_messages_ % sliding_window_size == 0) { std::lock_guard lk(all_msg_acknowledged_mutex_); - number_of_acknowledged_messages_ = 0; all_msg_acknowledged_ = true; all_msg_acknowledged_cv_.notify_one(); } @@ -181,6 +176,10 @@ void payload_test_client::run() condition_.wait(its_lock); } + request_->set_service(vsomeip_test::TEST_SERVICE_SERVICE_ID); + request_->set_instance(vsomeip_test::TEST_SERVICE_INSTANCE_ID); + request_->set_method(vsomeip_test::TEST_SERVICE_METHOD_ID); + // lock the mutex std::unique_lock lk(all_msg_acknowledged_mutex_); @@ -218,6 +217,11 @@ void payload_test_client::run() blocked_ = false; stop(); + std::thread t1([](){ usleep(1000000 * 5);}); + t1.join(); + app_->stop(); + std::thread t([](){ usleep(1000000 * 5);}); + t.join(); } @@ -235,6 +239,9 @@ std::uint32_t payload_test_client::get_max_allowed_payload() case payloadsize::UDP: payload = VSOMEIP_MAX_UDP_MESSAGE_SIZE; break; + case payloadsize::USER_SPECIFIED: + payload = user_defined_max_payload; + break; default: payload = VSOMEIP_MAX_LOCAL_MESSAGE_SIZE; break; @@ -317,6 +324,7 @@ int main(int argc, char** argv) std::string sliding_window_size_param("--sliding-window-size"); std::string max_payload_size_param("--max-payload-size"); std::string shutdown_service_disable_param("--dont-shutdown-service"); + std::string numbers_of_messages("--number-of-messages"); std::string help("--help"); int i = 1; @@ -359,6 +367,16 @@ int main(int argc, char** argv) { max_payload_size = payloadsize::UDP; } + else { + max_payload_size = payloadsize::USER_SPECIFIED; + std::stringstream converter(argv[i]); + converter >> user_defined_max_payload; + } + } + else if (numbers_of_messages == argv[i]) { + i++; + std::stringstream converter(argv[i]); + converter >> number_of_messages_to_send; } else if(shutdown_service_disable_param == argv[i]) { @@ -380,6 +398,7 @@ int main(int argc, char** argv) "TCP (=" << VSOMEIP_MAX_TCP_MESSAGE_SIZE << "byte)}, default: UDS\n" << "--dont-shutdown-service: Don't shutdown the service upon " "finishing of the payload test\n" + << "--number-of-messages: Number of messages to send per payload size iteration\n" << "--help: print this help"; } i++; diff --git a/test/payload_tests/payload_test_client.hpp b/test/payload_tests/payload_test_client.hpp index 9511560..ca1b58c 100644 --- a/test/payload_tests/payload_test_client.hpp +++ b/test/payload_tests/payload_test_client.hpp @@ -27,7 +27,7 @@ public: void start(); void stop(); void join_sender_thread(); - void on_event(vsomeip::event_type_e _event); + void on_state(vsomeip::state_type_e _state); void on_availability(vsomeip::service_t _service, vsomeip::instance_t _instance, bool _is_available); void on_message(const std::shared_ptr &_response); diff --git a/test/payload_tests/payload_test_service.cpp b/test/payload_tests/payload_test_service.cpp index b8ae72f..2a92064 100644 --- a/test/payload_tests/payload_test_service.cpp +++ b/test/payload_tests/payload_test_service.cpp @@ -7,6 +7,7 @@ // this variables are changed via cmdline parameters static bool use_tcp = false; +static bool check_payload = true; payload_test_service::payload_test_service(bool _use_tcp) : app_(vsomeip::runtime::get()->create_application()), @@ -34,8 +35,8 @@ void payload_test_service::init() std::bind(&payload_test_service::on_message_shutdown, this, std::placeholders::_1)); - app_->register_event_handler( - std::bind(&payload_test_service::on_event, this, + app_->register_state_handler( + std::bind(&payload_test_service::on_state, this, std::placeholders::_1)); } @@ -52,7 +53,7 @@ void payload_test_service::stop() 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_event_handler(); + app_->unregister_state_handler(); app_->stop(); } @@ -71,13 +72,13 @@ void payload_test_service::stop_offer() app_->stop_offer_service(vsomeip_test::TEST_SERVICE_SERVICE_ID, vsomeip_test::TEST_SERVICE_INSTANCE_ID); } -void payload_test_service::on_event(vsomeip::event_type_e _event) +void payload_test_service::on_state(vsomeip::state_type_e _state) { VSOMEIP_INFO << "Application " << app_->get_name() << " is " - << (_event == vsomeip::event_type_e::ET_REGISTERED ? "registered." : + << (_state == vsomeip::state_type_e::ST_REGISTERED ? "registered." : "deregistered."); - if(_event == vsomeip::event_type_e::ET_REGISTERED) + if(_state == vsomeip::state_type_e::ST_REGISTERED) { if(!is_registered_) { @@ -117,11 +118,13 @@ void payload_test_service::on_message(const std::shared_ptr& _ // make sure the message was sent from the service ASSERT_EQ(_request->get_client(), vsomeip_test::TEST_CLIENT_CLIENT_ID); - std::shared_ptr pl = _request->get_payload(); - vsomeip::byte_t* pl_ptr = pl->get_data(); - for (int i = 0; i < pl->get_length(); i++) - { - ASSERT_EQ(*(pl_ptr+i), vsomeip_test::PAYLOAD_TEST_DATA); + if (check_payload) { + std::shared_ptr pl = _request->get_payload(); + vsomeip::byte_t* pl_ptr = pl->get_data(); + for (vsomeip::length_t i = 0; i < pl->get_length(); i++) + { + ASSERT_EQ(*(pl_ptr+i), vsomeip_test::PAYLOAD_TEST_DATA); + } } // send response @@ -134,6 +137,7 @@ void payload_test_service::on_message(const std::shared_ptr& _ void payload_test_service::on_message_shutdown( const std::shared_ptr& _request) { + (void)_request; VSOMEIP_INFO << "Shutdown method was called, going down now."; stop(); } @@ -159,6 +163,7 @@ TEST(someip_payload_test, send_response_for_every_request) int main(int argc, char** argv) { std::string help("--help"); + std::string check("--do-not-check-payload"); int i = 1; while (i < argc) @@ -166,7 +171,11 @@ int main(int argc, char** argv) if(help == argv[i]) { VSOMEIP_INFO << "Parameters:\n" - << "--help: print this help"; + << "--help: print this help\n" + << "--do-not-check-payload: Don't verify payload data " + << "-> Use this flag for performance measurements!"; + } else if (check == argv[i]) { + check_payload = false; } i++; } diff --git a/test/payload_tests/payload_test_service.hpp b/test/payload_tests/payload_test_service.hpp index 4255fc3..b272e66 100644 --- a/test/payload_tests/payload_test_service.hpp +++ b/test/payload_tests/payload_test_service.hpp @@ -26,7 +26,7 @@ public: void offer(); void stop_offer(); void join_offer_thread(); - void on_event(vsomeip::event_type_e _event); + void on_state(vsomeip::state_type_e _state); void on_message(const std::shared_ptr &_request); void on_message_shutdown(const std::shared_ptr &_request); void run(); diff --git a/test/payload_tests/stopwatch.cpp b/test/payload_tests/stopwatch.cpp index 13701a3..4911f1c 100644 --- a/test/payload_tests/stopwatch.cpp +++ b/test/payload_tests/stopwatch.cpp @@ -14,23 +14,25 @@ stop_watch::usec_t stop_watch::get_total_elapsed_microseconds() const { - usec_t elapsed = total_elapsed_; + usec_t elapsed = total_elapsed_; - if (started_) - elapsed += get_elapsed(); + if (started_) + elapsed += get_elapsed(); - return elapsed; + return elapsed; } stop_watch::usec_t stop_watch::get_total_elapsed_seconds() const { - return get_total_elapsed_microseconds() / USEC_PER_SEC; + return get_total_elapsed_microseconds() / USEC_PER_SEC; } stop_watch::usec_t stop_watch::now() { - struct timespec ts; + struct timespec ts; - assert(!clock_gettime(CLOCK_MONOTONIC_RAW, &ts)); + const int ret = clock_gettime(CLOCK_MONOTONIC_RAW, &ts); + assert(!ret); + static_cast(ret); // prevent warning in release build - return (usec_t) ts.tv_sec * USEC_PER_SEC + (usec_t) ts.tv_nsec / NSEC_PER_USEC; + return (usec_t) ts.tv_sec * USEC_PER_SEC + (usec_t) ts.tv_nsec / NSEC_PER_USEC; } diff --git a/test/payload_tests/stopwatch.hpp b/test/payload_tests/stopwatch.hpp index fa6bbe8..0cdc078 100644 --- a/test/payload_tests/stopwatch.hpp +++ b/test/payload_tests/stopwatch.hpp @@ -16,8 +16,8 @@ public: stop_watch() : started_(false), - total_elapsed_(0), - start_time_point_(0) + start_time_point_(0), + total_elapsed_(0) { } diff --git a/test/readme.txt b/test/readme.txt index 3aa1da0..ab643e5 100644 --- a/test/readme.txt +++ b/test/readme.txt @@ -52,6 +52,20 @@ The expected output is: 2015-02-10 08:47:31.517106 [info] Test "SERVICE DISCOVERY PORT" succeeded. +Application test +---------------- + +This test tests starting and stopping a vsomeip application in various ways. + +Automatic start from build directory: + +ctest -V -R application_test + +Manual start from sub folder test of build directory: + +./application_test_starter.sh + + Magic Cookies Test ------------------ To run the magic cookies test you need two devices on the same network. The network addresses within @@ -59,13 +73,18 @@ the configuration files need to be adapted to match the devices addresses. To start the magic-cookies-test from the build-directory do: -HOST1: -env VSOMEIP_CONFIGURATION_FILE=../config/vsomeip-magic-cookies-client.json \ -VSOMEIP_APPLICATION_NAME=client-sample ./magic-cookies-test-client +Automatic start from build directory: + +ctest -V -R magic_cookies_test + +Manual start from sub folder test of build directory: + +# On external host run +./magic_cookies_test_service_start.sh + +# On local host run +./magic_cookies_test_client_start.sh -HOST2: -env VSOMEIP_CONFIGURATION_FILE=../config/vsomeip-magic-cookies-service.json \ -VSOMEIP_APPLICATION_NAME=service-sample ./response-sample --tcp --static-routing The expected result is an output like this on service side: @@ -247,10 +266,76 @@ cd test ./external_local_payload_test_service_client_external_start.sh & # Start the local client VSOMEIP_APPLICATION_NAME=external_local_payload_test_client_local \ -VSOMEIP_CONFIGURATION_FILE=external_local_payload_test_client_local.json \ +VSOMEIP_CONFIGURATION=external_local_payload_test_client_local.json \ ./payload_test_client --dont-shutdown-service # Start the external client after the local client is finished from an # external host ./external_local_payload_test_client_external_start.sh All tests should be marked as "passed". + + +Big payload tests +----------------- + +This test tests the possibility to increase the maximum allowed payload size for +local and TCP messages via configuration file. + +The test will send a messages with 600k payload from a client to a service. +The service will reply with a response containing 600k payload as well. +This is repeated 10 times. +There is a version for local and for TCP communication available. + +Automatic start from the build directory: + +ctest -V -R big_payload_test_local + +Manual start from sub folder test of build directory: + +./big_payload_test_service_local_start.sh & +./big_payload_test_client_local_start.sh + + +Automatic start of the TCP version from the build directory: + +ctest -V -R big_payload_test_external + +Manual start from sub folder test of build directory: + +./big_payload_test_client_start.sh + +# On external host run +./big_payload_test_service_external_start.sh + + +Client ID tests +--------------- + +This tests tests communication over two nodes with multiple services on both +nodes. + +The test setup is as followed: +* There are five services with one method each. +* Two of the services run on node 1. +* Three of the services run on node 2. +* Each of the services sends ten requests to the other services and waits + until it received a response for every request. +* If all responses have been received, the service shutdown. + +Automatic start from the build directory: + +ctest -V -R client_id_test_diff_client_ids_diff_ports + +Manual start from sub folder test of build directory: + +./client_id_test_master_starter.sh client_id_test_diff_client_ids_diff_ports_master.json + +Second version where all services on one node use the same port: + +Automatic start from the build directory: + +ctest -V -R client_id_test_diff_client_ids_same_ports + +Manual start from sub folder test of build directory: + +./client_id_test_master_starter.sh client_id_test_diff_client_ids_same_ports_master.json 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 new file mode 100644 index 0000000..3633538 --- /dev/null +++ b/test/routing_tests/conf/external_local_routing_test_client_external.json.in @@ -0,0 +1,43 @@ +{ + "unicast" : "@TEST_IP_SLAVE@", + "netmask" : "255.255.255.0", + "logging" : + { + "level" : "debug", + "console" : "true", + "file" : + { + "enable" : "true", + "path" : "/var/log/vsomeip.log" + }, + + "dlt" : "true" + }, + + "applications" : + [ + { + "name" : "external_local_routing_test_client_external", + "id" : "0x1344" + } + ], + + "services" : + [ + { + "service" : "0x1234", + "instance" : "0x5678", + "unicast" : "@TEST_IP_MASTER@", + "unreliable" : "30509" + } + ], + + "routing" : "external_local_routing_test_client_external", + "service-discovery" : + { + "enable" : "false", + "multicast" : "224.0.0.1", + "port" : "30491", + "protocol" : "udp" + } +} 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 new file mode 100644 index 0000000..0ef1f77 --- /dev/null +++ b/test/routing_tests/conf/external_local_routing_test_service.json.in @@ -0,0 +1,41 @@ +{ + "unicast" : "@TEST_IP_MASTER@", + "logging" : + { + "level" : "debug", + "console" : "true", + "file" : + { + "enable" : "false", + "path" : "/tmp/vsomeip.log" + }, + + "dlt" : "false" + }, + + "applications" : + [ + { + "name" : "external_local_routing_test_service", + "id" : "0x1277" + } + ], + + "services" : + [ + { + "service" : "0x1234", + "instance" : "0x5678", + "unreliable" : "30509" + } + ], + + "routing" : "external_local_routing_test_service", + "service-discovery" : + { + "enable" : "false", + "multicast" : "224.0.0.1", + "port" : "30490", + "protocol" : "udp" + } +} diff --git a/test/routing_tests/external_local_routing_test_client_external.json b/test/routing_tests/external_local_routing_test_client_external.json deleted file mode 100644 index fb33ae8..0000000 --- a/test/routing_tests/external_local_routing_test_client_external.json +++ /dev/null @@ -1,49 +0,0 @@ -{ - "unicast" : "172.16.100.131", - "netmask" : "255.255.255.0", - "logging" : - { - "level" : "debug", - "console" : "true", - "file" : - { - "enable" : "true", - "path" : "/var/log/vsomeip.log" - }, - - "dlt" : "true" - }, - - "applications" : - [ - { - "name" : "external_local_routing_test_client_external", - "id" : "0x1344" - } - ], - - "servicegroups" : - [ - { - "name" : "remote", - "unicast" : "134.86.56.183", - "services" : - [ - { - "service" : "0x1234", - "instance" : "0x5678", - "unreliable" : "30509" - } - ] - } - ], - - "routing" : "external_local_routing_test_client_external", - "service-discovery" : - { - "enable" : "false", - "multicast" : "224.0.0.1", - "port" : "30491", - "protocol" : "udp" - } -} diff --git a/test/routing_tests/external_local_routing_test_client_external_start.sh b/test/routing_tests/external_local_routing_test_client_external_start.sh index 44b5187..a40dece 100755 --- a/test/routing_tests/external_local_routing_test_client_external_start.sh +++ b/test/routing_tests/external_local_routing_test_client_external_start.sh @@ -5,5 +5,5 @@ # file, You can obtain one at http://mozilla.org/MPL/2.0/. export VSOMEIP_APPLICATION_NAME=external_local_routing_test_client_external -export VSOMEIP_CONFIGURATION_FILE=external_local_routing_test_client_external.json +export VSOMEIP_CONFIGURATION=external_local_routing_test_client_external.json ./local_routing_test_client diff --git a/test/routing_tests/external_local_routing_test_service.cpp b/test/routing_tests/external_local_routing_test_service.cpp index 2553898..72899fd 100644 --- a/test/routing_tests/external_local_routing_test_service.cpp +++ b/test/routing_tests/external_local_routing_test_service.cpp @@ -9,11 +9,11 @@ external_local_routing_test_service::external_local_routing_test_service(bool _use_static_routing) : app_(vsomeip::runtime::get()->create_application()), is_registered_(false), - blocked_(false), use_static_routing_(_use_static_routing), - offer_thread_(std::bind(&external_local_routing_test_service::run, this)), + blocked_(false), number_received_messages_local_(0), - number_received_messages_external_(0) + number_received_messages_external_(0), + offer_thread_(std::bind(&external_local_routing_test_service::run, this)) { } @@ -32,8 +32,8 @@ void external_local_routing_test_service::init() std::bind(&external_local_routing_test_service::on_message, this, std::placeholders::_1)); - app_->register_event_handler( - std::bind(&external_local_routing_test_service::on_event, this, + app_->register_state_handler( + std::bind(&external_local_routing_test_service::on_state, this, std::placeholders::_1)); VSOMEIP_INFO << "Static routing " << (use_static_routing_ ? "ON" : "OFF"); @@ -50,7 +50,7 @@ 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_event_handler(); + app_->unregister_state_handler(); app_->stop(); } @@ -69,16 +69,17 @@ void external_local_routing_test_service::stop_offer() app_->stop_offer_service(vsomeip_test::TEST_SERVICE_SERVICE_ID, vsomeip_test::TEST_SERVICE_INSTANCE_ID); } -void external_local_routing_test_service::on_event(vsomeip::event_type_e _event) +void external_local_routing_test_service::on_state(vsomeip::state_type_e _state) { VSOMEIP_INFO << "Application " << app_->get_name() << " is " - << (_event == vsomeip::event_type_e::ET_REGISTERED ? "registered." : + << (_state == vsomeip::state_type_e::ST_REGISTERED ? "registered." : "deregistered."); - if(_event == vsomeip::event_type_e::ET_REGISTERED) + if(_state == vsomeip::state_type_e::ST_REGISTERED) { if(!is_registered_) { + std::lock_guard its_lock(mutex_); is_registered_ = true; blocked_ = true; // "start" the run method thread diff --git a/test/routing_tests/external_local_routing_test_service.hpp b/test/routing_tests/external_local_routing_test_service.hpp index d5b767e..82f6220 100644 --- a/test/routing_tests/external_local_routing_test_service.hpp +++ b/test/routing_tests/external_local_routing_test_service.hpp @@ -27,7 +27,7 @@ public: void offer(); void stop_offer(); void join_offer_thread(); - void on_event(vsomeip::event_type_e _event); + void on_state(vsomeip::state_type_e _state); void on_message(const std::shared_ptr &_request); void run(); @@ -36,12 +36,12 @@ private: bool is_registered_; bool use_static_routing_; - std::thread offer_thread_; std::mutex mutex_; std::condition_variable condition_; bool blocked_; std::uint32_t number_received_messages_local_; std::uint32_t number_received_messages_external_; + std::thread offer_thread_; }; #endif /* EXTERNALLOCALROUTINGTESTSERVICE_HPP_ */ diff --git a/test/routing_tests/external_local_routing_test_service.json b/test/routing_tests/external_local_routing_test_service.json deleted file mode 100644 index d48a33a..0000000 --- a/test/routing_tests/external_local_routing_test_service.json +++ /dev/null @@ -1,62 +0,0 @@ -{ - "unicast" : "134.86.56.183", - "logging" : - { - "level" : "debug", - "console" : "true", - "file" : - { - "enable" : "false", - "path" : "/tmp/vsomeip.log" - }, - - "dlt" : "false" - }, - - "applications" : - [ - { - "name" : "external_local_routing_test_service", - "id" : "0x1277" - } - ], - - "servicegroups" : - [ - { - "name" : "default", - "unicast" : "local", - "delays" : - { - "initial" : - { - "minimum" : "10", - "maximum" : "100" - }, - - "repetition-base" : "200", - "repetition-max" : "3", - "cyclic-offer" : "2000", - "cyclic-request" : "2001" - }, - - "services" : - [ - { - "service" : "0x1234", - "instance" : "0x5678", - "unreliable" : "30509" - } - ] - } - ], - - "routing" : "external_local_routing_test_service", - "service-discovery" : - { - "enable" : "false", - "multicast" : "224.0.0.1", - "port" : "30490", - "protocol" : "udp" - } -} \ No newline at end of file diff --git a/test/routing_tests/external_local_routing_test_service_start.sh b/test/routing_tests/external_local_routing_test_service_start.sh index b28b6cf..e6ac677 100755 --- a/test/routing_tests/external_local_routing_test_service_start.sh +++ b/test/routing_tests/external_local_routing_test_service_start.sh @@ -5,5 +5,5 @@ # file, You can obtain one at http://mozilla.org/MPL/2.0/. export VSOMEIP_APPLICATION_NAME=external_local_routing_test_service -export VSOMEIP_CONFIGURATION_FILE=external_local_routing_test_service.json +export VSOMEIP_CONFIGURATION=external_local_routing_test_service.json ./external_local_routing_test_service diff --git a/test/routing_tests/external_local_routing_test_starter.sh b/test/routing_tests/external_local_routing_test_starter.sh index dc0a2c3..abee34d 100755 --- a/test/routing_tests/external_local_routing_test_starter.sh +++ b/test/routing_tests/external_local_routing_test_starter.sh @@ -49,7 +49,7 @@ check_tcp_udp_sockets_are_closed () # Start the service export VSOMEIP_APPLICATION_NAME=external_local_routing_test_service -export VSOMEIP_CONFIGURATION_FILE=external_local_routing_test_service.json +export VSOMEIP_CONFIGURATION=external_local_routing_test_service.json ./external_local_routing_test_service & SERIVCE_PID=$! sleep 1; @@ -59,7 +59,7 @@ check_tcp_udp_sockets_are_open $SERIVCE_PID # Start the client (we reuse the one from the local_routing_test to check # the local routing functionality). export VSOMEIP_APPLICATION_NAME=local_routing_test_client -export VSOMEIP_CONFIGURATION_FILE=local_routing_test_client.json +export VSOMEIP_CONFIGURATION=local_routing_test_client.json ./local_routing_test_client & CLIENT_PID=$! diff --git a/test/routing_tests/local_routing_test_client.cpp b/test/routing_tests/local_routing_test_client.cpp index a9a11f5..0659e48 100644 --- a/test/routing_tests/local_routing_test_client.cpp +++ b/test/routing_tests/local_routing_test_client.cpp @@ -8,13 +8,13 @@ local_routing_test_client::local_routing_test_client(bool _use_tcp) : app_(vsomeip::runtime::get()->create_application()), request_(vsomeip::runtime::get()->create_request(_use_tcp)), - sender_(std::bind(&local_routing_test_client::run, this)), running_(true), blocked_(false), is_available_(false), number_of_messages_to_send_(vsomeip_test::NUMBER_OF_MESSAGES_TO_SEND), number_of_sent_messages_(0), - number_of_acknowledged_messages_(0) + number_of_acknowledged_messages_(0), + sender_(std::bind(&local_routing_test_client::run, this)) { } @@ -22,24 +22,20 @@ void local_routing_test_client::init() { app_->init(); - app_->register_event_handler( - std::bind(&local_routing_test_client::on_event, this, + app_->register_state_handler( + std::bind(&local_routing_test_client::on_state, this, std::placeholders::_1)); - app_->register_availability_handler(vsomeip_test::TEST_SERVICE_SERVICE_ID, - vsomeip_test::TEST_SERVICE_INSTANCE_ID, - std::bind(&local_routing_test_client::on_availability, this, - std::placeholders::_1, std::placeholders::_2, - std::placeholders::_3)); - app_->register_message_handler(vsomeip::ANY_SERVICE, vsomeip_test::TEST_SERVICE_INSTANCE_ID, vsomeip::ANY_METHOD, std::bind(&local_routing_test_client::on_message, this, std::placeholders::_1)); - request_->set_service(vsomeip_test::TEST_SERVICE_SERVICE_ID); - request_->set_instance(vsomeip_test::TEST_SERVICE_INSTANCE_ID); - request_->set_method(vsomeip_test::TEST_SERVICE_METHOD_ID); + app_->register_availability_handler(vsomeip_test::TEST_SERVICE_SERVICE_ID, + vsomeip_test::TEST_SERVICE_INSTANCE_ID, + std::bind(&local_routing_test_client::on_availability, this, + std::placeholders::_1, std::placeholders::_2, + std::placeholders::_3)); } void local_routing_test_client::start() @@ -53,7 +49,7 @@ 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_event_handler(); + app_->unregister_state_handler(); app_->unregister_message_handler(vsomeip::ANY_SERVICE, vsomeip_test::TEST_SERVICE_INSTANCE_ID, vsomeip::ANY_METHOD); @@ -66,9 +62,9 @@ void local_routing_test_client::join_sender_thread(){ ASSERT_EQ(number_of_sent_messages_, number_of_acknowledged_messages_); } -void local_routing_test_client::on_event(vsomeip::event_type_e _event) +void local_routing_test_client::on_state(vsomeip::state_type_e _state) { - if(_event == vsomeip::event_type_e::ET_REGISTERED) + if(_state == vsomeip::state_type_e::ST_REGISTERED) { app_->request_service(vsomeip_test::TEST_SERVICE_SERVICE_ID, vsomeip_test::TEST_SERVICE_INSTANCE_ID, false); @@ -107,6 +103,11 @@ void local_routing_test_client::on_message(const std::shared_ptrget_client() << "/" << std::setw(4) << std::setfill('0') << std::hex << _response->get_session() << "]"; number_of_acknowledged_messages_++; + if(number_of_acknowledged_messages_ == number_of_messages_to_send_) { + std::lock_guard its_lock(mutex_); + blocked_ = true; + condition_.notify_one(); + } } void local_routing_test_client::send() @@ -123,8 +124,12 @@ void local_routing_test_client::run() { condition_.wait(its_lock); } + blocked_ = false; + request_->set_service(vsomeip_test::TEST_SERVICE_SERVICE_ID); + request_->set_instance(vsomeip_test::TEST_SERVICE_INSTANCE_ID); + request_->set_method(vsomeip_test::TEST_SERVICE_METHOD_ID); - for (int i = 0; i < number_of_messages_to_send_; i++) + for (uint32_t i = 0; i < number_of_messages_to_send_; i++) { app_->send(request_, true); VSOMEIP_INFO << "Client/Session [" << std::setw(4) << std::setfill('0') @@ -137,18 +142,15 @@ void local_routing_test_client::run() number_of_sent_messages_++; } blocked_ = false; - // wait until all send messages have been acknowledged, but a maximum of 5 sec. - int cnt = 0; - while (number_of_acknowledged_messages_ != number_of_messages_to_send_ - && cnt < 5) + // wait until all messages have been acknowledged + while (!blocked_) { - std::this_thread::sleep_for(std::chrono::seconds(1)); - cnt++; + condition_.wait(its_lock); } stop(); } -TEST(someip_header_factory_test, send_ten_messages_over_local_uds_socket) +TEST(someip_local_routing_test, send_ten_messages_to_service_and_receive_reply) { bool use_tcp = false; local_routing_test_client test_client_(use_tcp); diff --git a/test/routing_tests/local_routing_test_client.hpp b/test/routing_tests/local_routing_test_client.hpp index 1eedc8a..311b6eb 100644 --- a/test/routing_tests/local_routing_test_client.hpp +++ b/test/routing_tests/local_routing_test_client.hpp @@ -25,7 +25,7 @@ public: void start(); void stop(); void join_sender_thread(); - void on_event(vsomeip::event_type_e _event); + void on_state(vsomeip::state_type_e _state); void on_availability(vsomeip::service_t _service, vsomeip::instance_t _instance, bool _is_available); void on_message(const std::shared_ptr &_response); @@ -37,13 +37,13 @@ private: std::shared_ptr request_; std::mutex mutex_; std::condition_variable condition_; - std::thread sender_; bool running_; bool blocked_; bool is_available_; std::uint32_t number_of_messages_to_send_; std::uint32_t number_of_sent_messages_; std::uint32_t number_of_acknowledged_messages_; + std::thread sender_; }; #endif /* LOCALROUTINGTESTCLIENT_HPP_ */ diff --git a/test/routing_tests/local_routing_test_client.json b/test/routing_tests/local_routing_test_client.json index fa8d46a..a5991c2 100644 --- a/test/routing_tests/local_routing_test_client.json +++ b/test/routing_tests/local_routing_test_client.json @@ -22,16 +22,8 @@ } ], - "servicegroups" : + "services" : [ - { - "name" : "remote", - "unicast" : "127.0.0.1", - "services" : - [ - - ] - } ], "routing" : "local_routing_test_service", diff --git a/test/routing_tests/local_routing_test_client_start.sh b/test/routing_tests/local_routing_test_client_start.sh index ebe1bf9..1c9cad9 100755 --- a/test/routing_tests/local_routing_test_client_start.sh +++ b/test/routing_tests/local_routing_test_client_start.sh @@ -5,5 +5,5 @@ # file, You can obtain one at http://mozilla.org/MPL/2.0/. export VSOMEIP_APPLICATION_NAME=local_routing_test_client -export VSOMEIP_CONFIGURATION_FILE=local_routing_test_client.json +export VSOMEIP_CONFIGURATION=local_routing_test_client.json ./local_routing_test_client diff --git a/test/routing_tests/local_routing_test_service.cpp b/test/routing_tests/local_routing_test_service.cpp index 36dbe72..7e04f01 100644 --- a/test/routing_tests/local_routing_test_service.cpp +++ b/test/routing_tests/local_routing_test_service.cpp @@ -8,10 +8,10 @@ local_routing_test_service::local_routing_test_service(bool _use_static_routing) : app_(vsomeip::runtime::get()->create_application()), is_registered_(false), - blocked_(false), use_static_routing_(_use_static_routing), - offer_thread_(std::bind(&local_routing_test_service::run, this)), - number_of_received_messages_(0) + blocked_(false), + number_of_received_messages_(0), + offer_thread_(std::bind(&local_routing_test_service::run, this)) { } @@ -25,8 +25,8 @@ void local_routing_test_service::init() std::bind(&local_routing_test_service::on_message, this, std::placeholders::_1)); - app_->register_event_handler( - std::bind(&local_routing_test_service::on_event, this, + app_->register_state_handler( + std::bind(&local_routing_test_service::on_state, this, std::placeholders::_1)); VSOMEIP_INFO << "Static routing " << (use_static_routing_ ? "ON" : "OFF"); @@ -43,7 +43,7 @@ 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_event_handler(); + app_->unregister_state_handler(); app_->stop(); } @@ -62,17 +62,18 @@ void local_routing_test_service::stop_offer() app_->stop_offer_service(vsomeip_test::TEST_SERVICE_SERVICE_ID, vsomeip_test::TEST_SERVICE_INSTANCE_ID); } -void local_routing_test_service::on_event(vsomeip::event_type_e _event) +void local_routing_test_service::on_state(vsomeip::state_type_e _state) { VSOMEIP_INFO << "Application " << app_->get_name() << " is " - << (_event == vsomeip::event_type_e::ET_REGISTERED ? "registered." : + << (_state == vsomeip::state_type_e::ST_REGISTERED ? "registered." : "deregistered."); - if(_event == vsomeip::event_type_e::ET_REGISTERED) + if(_state == vsomeip::state_type_e::ST_REGISTERED) { if(!is_registered_) { is_registered_ = true; + std::lock_guard its_lock(mutex_); blocked_ = true; // "start" the run method thread condition_.notify_one(); @@ -118,7 +119,9 @@ void local_routing_test_service::on_message(const std::shared_ptr= vsomeip_test::NUMBER_OF_MESSAGES_TO_SEND) { - app_->stop(); + std::lock_guard its_lock(mutex_); + blocked_ =true; + condition_.notify_one(); } ASSERT_LT(number_of_received_messages_, vsomeip_test::NUMBER_OF_MESSAGES_TO_SEND + 1); @@ -130,10 +133,17 @@ void local_routing_test_service::run() while (!blocked_) condition_.wait(its_lock); + blocked_ = false; if(use_static_routing_) { offer(); } + while (!blocked_) + condition_.wait(its_lock); + + std::thread t2([](){ usleep(1000000 * 5);}); + t2.join(); + app_->stop(); } TEST(someip_local_routing_test, receive_ten_messages_over_local_uds_socket) diff --git a/test/routing_tests/local_routing_test_service.hpp b/test/routing_tests/local_routing_test_service.hpp index 8ee00b4..8cd4fb9 100644 --- a/test/routing_tests/local_routing_test_service.hpp +++ b/test/routing_tests/local_routing_test_service.hpp @@ -26,7 +26,7 @@ public: void offer(); void stop_offer(); void join_offer_thread(); - void on_event(vsomeip::event_type_e _event); + void on_state(vsomeip::state_type_e _state); void on_message(const std::shared_ptr &_request); void run(); @@ -35,11 +35,11 @@ private: bool is_registered_; bool use_static_routing_; - std::thread offer_thread_; - std::mutex mutex_; - std::condition_variable condition_; bool blocked_; std::uint32_t number_of_received_messages_; + std::mutex mutex_; + std::condition_variable condition_; + std::thread offer_thread_; }; #endif /* LOCALROUTINGTESTSERVICE_HPP_ */ diff --git a/test/routing_tests/local_routing_test_service.json b/test/routing_tests/local_routing_test_service.json index 6726f0e..528074f 100644 --- a/test/routing_tests/local_routing_test_service.json +++ b/test/routing_tests/local_routing_test_service.json @@ -1,5 +1,5 @@ { - "unicast" : "134.86.56.183", + "unicast" : "127.0.0.1", "logging" : { "level" : "debug", @@ -21,32 +21,11 @@ } ], - "servicegroups" : + "services" : [ { - "name" : "default", - "unicast" : "local", - "delays" : - { - "initial" : - { - "minimum" : "10", - "maximum" : "100" - }, - - "repetition-base" : "200", - "repetition-max" : "3", - "cyclic-offer" : "2000", - "cyclic-request" : "2001" - }, - - "services" : - [ - { - "service" : "0x1234", - "instance" : "0x5678" - } - ] + "service" : "0x1234", + "instance" : "0x5678" } ], @@ -58,4 +37,4 @@ "port" : "30490", "protocol" : "udp" } -} \ No newline at end of file +} diff --git a/test/routing_tests/local_routing_test_service_start.sh b/test/routing_tests/local_routing_test_service_start.sh index fef108e..acafd51 100755 --- a/test/routing_tests/local_routing_test_service_start.sh +++ b/test/routing_tests/local_routing_test_service_start.sh @@ -5,5 +5,5 @@ # file, You can obtain one at http://mozilla.org/MPL/2.0/. export VSOMEIP_APPLICATION_NAME=local_routing_test_service -export VSOMEIP_CONFIGURATION_FILE=local_routing_test_service.json +export VSOMEIP_CONFIGURATION=local_routing_test_service.json ./local_routing_test_service diff --git a/test/routing_tests/local_routing_test_starter.sh b/test/routing_tests/local_routing_test_starter.sh index 6c803b9..97bd67d 100755 --- a/test/routing_tests/local_routing_test_starter.sh +++ b/test/routing_tests/local_routing_test_starter.sh @@ -35,7 +35,7 @@ check_tcp_udp_sockets_are_closed () # Start the service export VSOMEIP_APPLICATION_NAME=local_routing_test_service -export VSOMEIP_CONFIGURATION_FILE=local_routing_test_service.json +export VSOMEIP_CONFIGURATION=local_routing_test_service.json ./local_routing_test_service & SERIVCE_PID=$! sleep 1; @@ -44,7 +44,7 @@ check_tcp_udp_sockets_are_closed $SERIVCE_PID # Start the client export VSOMEIP_APPLICATION_NAME=local_routing_test_client -export VSOMEIP_CONFIGURATION_FILE=local_routing_test_client.json +export VSOMEIP_CONFIGURATION=local_routing_test_client.json ./local_routing_test_client & CLIENT_PID=$! diff --git a/test/someip_test_globals.hpp b/test/someip_test_globals.hpp index 99cbe3f..d95e7de 100644 --- a/test/someip_test_globals.hpp +++ b/test/someip_test_globals.hpp @@ -8,6 +8,8 @@ #include +#include "../implementation/logging/include/logger.hpp" + namespace vsomeip_test { diff --git a/vsomeip.pc.in b/vsomeip.pc.in new file mode 100644 index 0000000..dc450b7 --- /dev/null +++ b/vsomeip.pc.in @@ -0,0 +1,11 @@ +prefix=@CMAKE_INSTALL_PREFIX@ +exec_prefix=@CMAKE_INSTALL_PREFIX@ +libdir=@CMAKE_INSTALL_PREFIX@/@INSTALL_LIB_DIR@ +includedir=@CMAKE_INSTALL_PREFIX@/include + +Name: @PROJECT@ +Description: New SOME/IP stack, feature complete +Version: @VSOMEIP_VERSION@ +Libs: -L${libdir} -lvsomeip -lvsomeip-sd -lboost_system -lboost_log -lboost_filesystem +Cflags: -I${includedir} + -- cgit v1.2.1