summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDiogo Pedrosa <48529452+DiogoPedrozza@users.noreply.github.com>2023-03-03 11:17:22 +0000
committerGitHub <noreply@github.com>2023-03-03 11:17:22 +0000
commit11447b294a5ad4d8be08a466f769670aa7ed924a (patch)
tree75a04fb3c8cca73a377e707d577c74bcb329597a
parent44be74e9d2b432494a0634f997887684c71f187f (diff)
downloadvSomeIP-11447b294a5ad4d8be08a466f769670aa7ed924a.tar.gz
vsomeip 3.1.37.1 (#414)
Co-authored-by: Diogo Pedrosa <diogo.pedrosa@ctw.bmwgroup.com>
-rw-r--r--CHANGES112
-rw-r--r--CMakeLists.txt14
-rw-r--r--documentation/vsomeipUserGuide8
-rw-r--r--examples/request-sample.cpp4
-rw-r--r--examples/response-sample.cpp2
-rw-r--r--examples/routingmanagerd/routingmanagerd.cpp29
-rw-r--r--implementation/configuration/include/client.hpp6
-rw-r--r--implementation/configuration/include/configuration.hpp7
-rw-r--r--implementation/configuration/include/configuration_impl.hpp27
-rw-r--r--implementation/configuration/include/internal.hpp.in9
-rw-r--r--implementation/configuration/include/internal_android.hpp9
-rw-r--r--implementation/configuration/src/configuration_impl.cpp309
-rw-r--r--implementation/endpoints/include/client_endpoint_impl.hpp4
-rw-r--r--implementation/endpoints/include/endpoint.hpp1
-rw-r--r--implementation/endpoints/include/endpoint_host.hpp1
-rw-r--r--implementation/endpoints/include/endpoint_impl.hpp1
-rw-r--r--implementation/endpoints/include/endpoint_manager_base.hpp1
-rw-r--r--implementation/endpoints/include/endpoint_manager_impl.hpp13
-rw-r--r--implementation/endpoints/include/local_client_endpoint_impl.hpp2
-rw-r--r--implementation/endpoints/include/local_server_endpoint_impl.hpp1
-rw-r--r--implementation/endpoints/include/server_endpoint_impl.hpp7
-rw-r--r--implementation/endpoints/include/tcp_client_endpoint_impl.hpp2
-rw-r--r--implementation/endpoints/include/tcp_server_endpoint_impl.hpp1
-rw-r--r--implementation/endpoints/include/udp_client_endpoint_impl.hpp7
-rw-r--r--implementation/endpoints/include/udp_server_endpoint_impl.hpp1
-rw-r--r--implementation/endpoints/include/virtual_server_endpoint_impl.hpp1
-rw-r--r--implementation/endpoints/src/client_endpoint_impl.cpp54
-rw-r--r--implementation/endpoints/src/endpoint_manager_base.cpp9
-rw-r--r--implementation/endpoints/src/endpoint_manager_impl.cpp190
-rw-r--r--implementation/endpoints/src/local_client_endpoint_impl.cpp13
-rw-r--r--implementation/endpoints/src/local_server_endpoint_impl.cpp4
-rw-r--r--implementation/endpoints/src/server_endpoint_impl.cpp39
-rw-r--r--implementation/endpoints/src/tcp_client_endpoint_impl.cpp247
-rw-r--r--implementation/endpoints/src/tcp_server_endpoint_impl.cpp51
-rw-r--r--implementation/endpoints/src/udp_client_endpoint_impl.cpp263
-rw-r--r--implementation/endpoints/src/udp_server_endpoint_impl.cpp121
-rw-r--r--implementation/endpoints/src/virtual_server_endpoint_impl.cpp4
-rw-r--r--implementation/logger/src/message.cpp3
-rw-r--r--implementation/message/src/deserializer.cpp12
-rw-r--r--implementation/routing/include/eventgroupinfo.hpp12
-rw-r--r--implementation/routing/include/remote_subscription.hpp3
-rw-r--r--implementation/routing/include/routing_manager_base.hpp8
-rw-r--r--implementation/routing/include/routing_manager_impl.hpp14
-rw-r--r--implementation/routing/include/routing_manager_proxy.hpp2
-rw-r--r--implementation/routing/include/routing_manager_stub.hpp10
-rw-r--r--implementation/routing/include/routing_manager_stub_host.hpp2
-rw-r--r--implementation/routing/src/event.cpp46
-rw-r--r--implementation/routing/src/eventgroupinfo.cpp167
-rw-r--r--implementation/routing/src/remote_subscription.cpp30
-rw-r--r--implementation/routing/src/routing_manager_base.cpp60
-rw-r--r--implementation/routing/src/routing_manager_impl.cpp361
-rw-r--r--implementation/routing/src/routing_manager_proxy.cpp109
-rw-r--r--implementation/routing/src/routing_manager_stub.cpp93
-rw-r--r--implementation/runtime/src/application_impl.cpp2
-rw-r--r--implementation/security/src/policy.cpp4
-rw-r--r--implementation/security/src/security_impl.cpp16
-rw-r--r--implementation/service_discovery/include/service_discovery.hpp1
-rw-r--r--implementation/service_discovery/include/service_discovery_host.hpp2
-rw-r--r--implementation/service_discovery/include/service_discovery_impl.hpp5
-rw-r--r--implementation/service_discovery/src/service_discovery_impl.cpp258
-rw-r--r--test/CMakeLists.txt103
-rwxr-xr-xtest/big_payload_tests/big_payload_test_external_starter.sh6
-rw-r--r--test/big_payload_tests/big_payload_test_service.cpp7
-rw-r--r--test/big_payload_tests/big_payload_test_service.hpp1
-rw-r--r--test/client_id_tests/client_id_test_globals.hpp15
-rwxr-xr-xtest/client_id_tests/client_id_test_master_starter.sh3
-rw-r--r--test/client_id_tests/client_id_test_service.cpp42
-rw-r--r--test/cpu_load_tests/cpu_load_test_client.cpp2
-rwxr-xr-xtest/cpu_load_tests/cpu_load_test_master_starter.sh3
-rw-r--r--test/cpu_load_tests/cpu_load_test_service.cpp2
-rw-r--r--test/debounce_tests/debounce_test_client.json52
-rw-r--r--test/debounce_tests/debounce_test_service.json19
-rwxr-xr-xtest/e2e_tests/e2e_profile_04_test_external_master_start.sh10
-rwxr-xr-xtest/e2e_tests/e2e_profile_04_test_external_slave_start.sh5
-rwxr-xr-xtest/e2e_tests/e2e_test_external_master_start.sh10
-rwxr-xr-xtest/e2e_tests/e2e_test_external_slave_start.sh5
-rwxr-xr-xtest/event_tests/event_test_master_starter.sh10
-rw-r--r--test/initial_event_tests/initial_event_test_client.cpp161
-rwxr-xr-xtest/initial_event_tests/initial_event_test_master_starter.sh11
-rw-r--r--test/initial_event_tests/initial_event_test_service.cpp5
-rwxr-xr-xtest/initial_event_tests/initial_event_test_slave_starter.sh4
-rw-r--r--test/initial_event_tests/initial_event_test_stop_service.cpp10
-rwxr-xr-xtest/magic_cookies_tests/magic_cookies_test_starter.sh3
-rwxr-xr-xtest/malicious_data_tests/conf/malicious_data_test_master_starter.sh.in4
-rwxr-xr-xtest/npdu_tests/npdu_test_starter.sh4
-rwxr-xr-xtest/offer_tests/conf/offer_test_big_sd_msg_master_starter.sh.in4
-rwxr-xr-xtest/offer_tests/conf/offer_test_external_master_starter.sh.in34
-rw-r--r--test/offer_tests/offer_test_external_sd_msg_sender.cpp24
-rwxr-xr-xtest/offer_tests/offer_test_external_slave_sd_starter.sh38
-rw-r--r--test/offer_tests/offer_test_service_availability_checker.cpp118
-rwxr-xr-xtest/payload_tests/external_local_payload_test_client_external_starter.sh3
-rwxr-xr-xtest/payload_tests/external_local_payload_test_client_local_and_external_starter.sh3
-rwxr-xr-xtest/pending_subscription_tests/conf/pending_subscription_test_master_starter.sh.in3
-rwxr-xr-xtest/routing_tests/external_local_routing_test_starter.sh3
-rwxr-xr-xtest/second_address_tests/second_address_test_master_starter.sh3
-rwxr-xr-xtest/security_tests/security_test_external_master_start.sh10
-rwxr-xr-xtest/security_tests/security_test_external_slave_start.sh5
-rwxr-xr-xtest/someip_tp_tests/conf/someip_tp_test_master_starter.sh.in4
-rwxr-xr-xtest/subscribe_notify_one_tests/subscribe_notify_one_test_master_starter.sh5
-rwxr-xr-xtest/subscribe_notify_one_tests/subscribe_notify_one_test_slave_starter.sh4
-rw-r--r--test/subscribe_notify_tests/conf/subscribe_notify_test_one_event_two_eventgroups_master.json.in2
-rw-r--r--test/subscribe_notify_tests/conf/subscribe_notify_test_one_event_two_eventgroups_tcp_slave.json.in2
-rw-r--r--test/subscribe_notify_tests/conf/subscribe_notify_test_one_event_two_eventgroups_udp_slave.json.in2
-rwxr-xr-xtest/subscribe_notify_tests/subscribe_notify_test_master_starter.sh5
-rwxr-xr-xtest/subscribe_notify_tests/subscribe_notify_test_one_event_two_eventgroups_master_starter.sh4
-rwxr-xr-xtest/subscribe_notify_tests/subscribe_notify_test_one_event_two_eventgroups_slave_starter.sh2
-rwxr-xr-xtest/subscribe_notify_tests/subscribe_notify_test_slave_starter.sh4
-rw-r--r--test/suspend_resume_tests/conf/suspend_resume_test_client.json.in32
-rw-r--r--test/suspend_resume_tests/conf/suspend_resume_test_service.json.in40
-rw-r--r--test/suspend_resume_tests/suspend_resume_test.hpp22
-rw-r--r--test/suspend_resume_tests/suspend_resume_test_client.cpp239
-rwxr-xr-xtest/suspend_resume_tests/suspend_resume_test_master_starter.sh72
-rw-r--r--test/suspend_resume_tests/suspend_resume_test_service.cpp213
-rwxr-xr-xtest/suspend_resume_tests/suspend_resume_test_slave_starter.sh29
-rw-r--r--tools/vsomeip_ctrl.cpp17
115 files changed, 3485 insertions, 752 deletions
diff --git a/CHANGES b/CHANGES
index 954f70c..f5868f9 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,5 +1,117 @@
Changes
=======
+v3.1.37.1
+- Support REQUEST_ACK message type (PR #237)
+- Fix typo in error message (PR #238)
+- Fix for bug #239, as one process use two stubs for different vlans (PR #247, Issues #223 #239 #241)
+- Fix multicast timeout crash on Windows caused by bad use of reinterpret_cast (PR #272)
+- Update configuration paths to reside on vendor partition (PR #274)
+- Retry failed netlink operations (PR #283)
+- Fixed android build error (PR #288)
+- Fix for configuration option deserialize bug (PR #300, Issue #263)
+- Accept return codes within range 0x20-0x5E as valid (PR #312)
+- Add support for broadcast (PR #314)
+- Fix for TC8 test case SOMEIPSRV_RPC_07 and SOMEIPSRV_SD_BEHAVIOR_03 (PR #316, Issue #315)
+- Support boost 1.76 (PR #318)
+- Fix big endian support in byteorder.hpp (PR #320)
+- Use Reference to Prevent Copying (PR #356)
+- Add CI using github actions (PR #140)
+
+v3.1.37
+- Added dependency from network tests to e2e library (plugin).
+- Avoid services becoming available when the daemon is suspended
+- Handling with some udp errors in send_cbk process,
+ restarting the connection.
+
+v3.1.36
+- Fix for ELVIS-339712: Fix handling of subscription objects
+ during unsubscribe.
+
+v3.1.35
+- Reworked fix for ELVIS-3310053
+- Improve checking for matching responses.
+ - When sending a response, vSomeIP only checked for a request with
+ the corresponding combination of client and session identifiers.
+ - This led to the possibility, that a response was sent for the
+ wrong service and/or method because of matching client and session
+ identifiers.
+ - This commit implements a full check of service, method, client and
+ session identifiers to ensure a response fits to the received
+ request.
+- Rework to get rid of clang-tidy (llvm14) warnings.
+- Facilitate manual execution of (some) subscription tests.
+ - Switch log level from "debug" to "warning" to facilitate the selection
+ of the script name that must be executed on client side.
+- Do not send initial events for rejected subscriptions.
+
+v3.1.34
+- Use default ports if an acceptance configuration does not specify any.
+- Prevent StopSubscribe/Subscribe on first offer reception.
+- Ignore routing state settings to the current state.
+- Explicitely clean subscriptions if a service removal is reported.
+- Use SOL_RECBUFFORCE instead of SOL_RECVBUF.
+
+v3.1.33
+- Corrected flag initialization to avoid wait time when re-establishing
+ connections.
+
+v3.1.32
+- Fix bug which could lead to deleting requested services of routing
+ manager.
+- Add Jenkins pipeline.
+- Fix race condition which could lead to false positive security
+ warnings.
+- Fix handling of remote subscriptions for unoffered services: Fix bug
+ which could lead to erroneously not accepting remote subscriptions
+ after a service was stop being offered and offered again.
+
+v3.1.31
+- Fix race condition which could lead to not establishing a TCP
+ connection to a remote service
+
+v3.1.30
+- Fixed lock order inversion
+- Fixed UDP socket bind error handling
+
+v3.1.29
+- Do not send re-subscriptions on suspend
+
+v3.1.28
+- Fixed race condition in client endpoint send queue
+- Improved robustness when receiving malformed remote subscriptions
+- Cleanup remote subscribers on suspend
+
+v3.1.27
+- Performance improvement: Added service partitioning:
+ Each configured partition will lead to a separate client port being used
+ to connect to a remote server port
+- Improve handling of expired subscriptions
+- Fixed race condition when starting "last message received" - timer.
+
+v3.1.26
+- Improve handling of expired subscriptions
+
+v3.1.25
+- Fix event payload caching at proxy
+
+v3.1.24
+- Fix for initial events
+
+v3.1.23
+- Fixed crash in TCP client endpoint
+- Fixed TCP socket bind error handling
+
+v3.1.22
+- Fixed joining multicast group for udp server endpoints
+
+v3.1.21
+- Fixed missing DLT logs if DLT was enabled in config in parallel with file or console logging.
+- Avoid heap-buffer-overflow in look_ahead() when deserializing SD entry / option type.
+- Restart UDP client endpoint on connection refused error.
+- Select a free client port that was not used recently.
+- Limit the number of possible remote subscribers from same remote IP address
+ to an eventgroup provided by a service/instance if the remote
+ subscriber uses different ports for its subscriptions.
v3.1.20.3
- Correct detection payload changes (Issue #164)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index aa83b7f..36cf6ac 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -11,8 +11,8 @@ set (VSOMEIP_COMPAT_NAME vsomeip)
set (VSOMEIP_MAJOR_VERSION 3)
set (VSOMEIP_MINOR_VERSION 1)
-set (VSOMEIP_PATCH_VERSION 20)
-set (VSOMEIP_HOTFIX_VERSION 3)
+set (VSOMEIP_PATCH_VERSION 37)
+set (VSOMEIP_HOTFIX_VERSION 1)
set (VSOMEIP_VERSION ${VSOMEIP_MAJOR_VERSION}.${VSOMEIP_MINOR_VERSION}.${VSOMEIP_PATCH_VERSION})
set (PACKAGE_VERSION ${VSOMEIP_VERSION}) # Used in documentation/doxygen.in
@@ -141,7 +141,7 @@ find_package(Threads REQUIRED)
# Boost
find_package( Boost 1.55 COMPONENTS system thread filesystem REQUIRED )
-include_directories( ${Boost_INCLUDE_DIR} )
+include_directories(SYSTEM ${Boost_INCLUDE_DIR} )
if(Boost_FOUND)
if(Boost_LIBRARY_DIR)
@@ -183,7 +183,7 @@ find_package(PkgConfig)
# DLT
if(VSOMEIP_ENABLE_DLT EQUAL 1)
pkg_check_modules(DLT "automotive-dlt >= 2.11")
-if(DLT_FOUND)
+if(DLT_FOUND)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DUSE_DLT")
endif(DLT_FOUND)
endif()
@@ -352,7 +352,7 @@ endif ()
target_include_directories(
${VSOMEIP_COMPAT_NAME}
PUBLIC
- $<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}> # for headers when building
+ $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/interface/compat>
$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}> # for generated files in build mode
$<INSTALL_INTERFACE:include/compat> # for clients in install mode
)
@@ -416,7 +416,7 @@ foreach ( file ${vsomeip_INCLUDE} )
endforeach()
install (
- TARGETS ${VSOMEIP_NAME}
+ TARGETS ${VSOMEIP_NAME}
# IMPORTANT: Add the vsomeip library to the "export-set"
EXPORT vsomeip3Targets
RUNTIME DESTINATION "${INSTALL_BIN_DIR}" COMPONENT
@@ -704,11 +704,11 @@ endif()
add_custom_target(build_tests)
add_dependencies(build_tests vsomeip3)
+add_dependencies(build_tests vsomeip3-e2e)
add_dependencies(build_tests vsomeip3-sd)
set(CMAKE_CTEST_COMMAND ctest -V)
add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND})
-
add_dependencies(check build_tests)
##############################################################################
diff --git a/documentation/vsomeipUserGuide b/documentation/vsomeipUserGuide
index f3ac6be..dd4f13d 100644
--- a/documentation/vsomeipUserGuide
+++ b/documentation/vsomeipUserGuide
@@ -1113,6 +1113,14 @@ Time which the stack collects new service offers before they enter the
repetition phase. This can be used to reduce the number of
sent messages during startup. The default setting is _500ms_.
+
+
+** `max_remote_subscribers`
++
+Limit the number of possible remote subscribers from same remote IP address
+to an eventgroup provided by a service/instance if the remote subscriber uses
+different ports for its subscriptions. The default setting is _3_.
++
+
//Watchdog
* anchor:config-watchdog[]`watchdog` (optional)
+
diff --git a/examples/request-sample.cpp b/examples/request-sample.cpp
index b6105c4..96eadfd 100644
--- a/examples/request-sample.cpp
+++ b/examples/request-sample.cpp
@@ -63,7 +63,8 @@ public:
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);
+ for (std::size_t i = 0; i < 10; ++i)
+ its_payload_data.push_back(static_cast<vsomeip::byte_t>(i % 256));
its_payload->set_data(its_payload_data);
request_->set_payload(its_payload);
@@ -175,7 +176,6 @@ private:
bool use_tcp_;
bool be_quiet_;
uint32_t cycle_;
- vsomeip::session_t session_;
std::mutex mutex_;
std::condition_variable condition_;
bool running_;
diff --git a/examples/response-sample.cpp b/examples/response-sample.cpp
index 68112d2..8b30302 100644
--- a/examples/response-sample.cpp
+++ b/examples/response-sample.cpp
@@ -107,7 +107,7 @@ public:
= vsomeip::runtime::get()->create_payload();
std::vector<vsomeip::byte_t> its_payload_data;
for (std::size_t i = 0; i < 120; ++i)
- its_payload_data.push_back(i % 256);
+ its_payload_data.push_back(static_cast<vsomeip::byte_t>(i % 256));
its_payload->set_data(its_payload_data);
its_response->set_payload(its_payload);
diff --git a/examples/routingmanagerd/routingmanagerd.cpp b/examples/routingmanagerd/routingmanagerd.cpp
index ff0a280..b2118f6 100644
--- a/examples/routingmanagerd/routingmanagerd.cpp
+++ b/examples/routingmanagerd/routingmanagerd.cpp
@@ -23,6 +23,7 @@
static std::shared_ptr<vsomeip::application> its_application;
#ifndef VSOMEIP_ENABLE_SIGNAL_HANDLING
+static vsomeip::routing_state_e routing_state = vsomeip::routing_state_e::RS_RUNNING;
static bool stop_application = false;
static bool stop_sighandler = false;
static std::condition_variable_any sighandler_condition;
@@ -35,9 +36,24 @@ static std::recursive_mutex sighandler_mutex;
*/
void routingmanagerd_stop(int _signal) {
// Do not log messages in signal handler as this can cause deadlock in boost logger
- if (_signal == SIGINT || _signal == SIGTERM) {
+ switch (_signal) {
+ case SIGINT:
+ case SIGTERM:
stop_application = true;
- }
+ break;
+
+ case SIGUSR1:
+ routing_state = vsomeip::routing_state_e::RS_SUSPENDED;
+ break;
+
+ case SIGUSR2:
+ routing_state = vsomeip::routing_state_e::RS_RESUMED;
+ break;
+
+ default:
+ ;
+ };
+
std::unique_lock<std::recursive_mutex> its_lock(sighandler_mutex);
sighandler_condition.notify_one();
}
@@ -68,6 +84,8 @@ int routingmanagerd_process(bool _is_quiet) {
// Unblock signals for this thread only
sigset_t handler_mask;
sigemptyset(&handler_mask);
+ sigaddset(&handler_mask, SIGUSR1);
+ sigaddset(&handler_mask, SIGUSR2);
sigaddset(&handler_mask, SIGTERM);
sigaddset(&handler_mask, SIGINT);
sigaddset(&handler_mask, SIGSEGV);
@@ -77,6 +95,8 @@ int routingmanagerd_process(bool _is_quiet) {
// Handle the following signals
signal(SIGINT, routingmanagerd_stop);
signal(SIGTERM, routingmanagerd_stop);
+ signal(SIGUSR1, routingmanagerd_stop);
+ signal(SIGUSR2, routingmanagerd_stop);
while (!stop_sighandler) {
std::unique_lock<std::recursive_mutex> its_lock(sighandler_mutex);
@@ -84,6 +104,11 @@ int routingmanagerd_process(bool _is_quiet) {
if (stop_application) {
its_application->stop();
return;
+ } else if (routing_state == vsomeip::routing_state_e::RS_RESUMED ||
+ routing_state == vsomeip::routing_state_e::RS_SUSPENDED){
+ VSOMEIP_INFO << "Received signal for setting routing_state to: 0x"
+ << std::hex << static_cast<int>(routing_state );
+ its_application->set_routing_state(routing_state);
}
}
});
diff --git a/implementation/configuration/include/client.hpp b/implementation/configuration/include/client.hpp
index 7758eca..872974f 100644
--- a/implementation/configuration/include/client.hpp
+++ b/implementation/configuration/include/client.hpp
@@ -16,16 +16,20 @@ namespace vsomeip_v3 {
namespace cfg {
struct client {
- client() : service_(ANY_SERVICE), instance_(ANY_INSTANCE) {}
+ client() : service_(ANY_SERVICE),
+ instance_(ANY_INSTANCE) {
+ }
// ports for specific service / instance
service_t service_;
instance_t instance_;
std::map<bool, std::set<uint16_t> > ports_;
+ std::map<bool, uint16_t> last_used_specific_client_port_;
// client port ranges mapped to remote port ranges
std::map<bool, std::pair<uint16_t, uint16_t> > remote_ports_;
std::map<bool, std::pair<uint16_t, uint16_t> > client_ports_;
+ std::map<bool, uint16_t> last_used_client_port_;
};
} // namespace cfg
diff --git a/implementation/configuration/include/configuration.hpp b/implementation/configuration/include/configuration.hpp
index a962298..e107e17 100644
--- a/implementation/configuration/include/configuration.hpp
+++ b/implementation/configuration/include/configuration.hpp
@@ -254,7 +254,7 @@ public:
virtual bool is_secure_service(service_t _service, instance_t _instance) const = 0;
- virtual std::uint32_t get_udp_receive_buffer_size() const = 0;
+ virtual int get_udp_receive_buffer_size() const = 0;
virtual bool check_routing_credentials(client_t _client, uint32_t _uid, uint32_t _gid) const = 0;
@@ -273,6 +273,11 @@ public:
virtual uint32_t get_statistics_interval() const = 0;
virtual uint32_t get_statistics_min_freq() const = 0;
virtual uint32_t get_statistics_max_messages() const = 0;
+
+ virtual uint8_t get_max_remote_subscribers() const = 0;
+
+ virtual partition_id_t get_partition_id(
+ service_t _service, instance_t _instance) const = 0;
};
} // namespace vsomeip_v3
diff --git a/implementation/configuration/include/configuration_impl.hpp b/implementation/configuration/include/configuration_impl.hpp
index 66cfc84..cb6c284 100644
--- a/implementation/configuration/include/configuration_impl.hpp
+++ b/implementation/configuration/include/configuration_impl.hpp
@@ -220,7 +220,7 @@ public:
VSOMEIP_EXPORT bool is_secure_service(service_t _service, instance_t _instance) const;
- VSOMEIP_EXPORT std::uint32_t get_udp_receive_buffer_size() const;
+ VSOMEIP_EXPORT int get_udp_receive_buffer_size() const;
VSOMEIP_EXPORT bool has_overlay(const std::string &_name) const;
VSOMEIP_EXPORT void load_overlay(const std::string &_name);
@@ -239,6 +239,11 @@ public:
VSOMEIP_EXPORT uint32_t get_statistics_min_freq() const;
VSOMEIP_EXPORT uint32_t get_statistics_max_messages() const;
+ VSOMEIP_EXPORT uint8_t get_max_remote_subscribers() const;
+
+ VSOMEIP_EXPORT partition_id_t get_partition_id(
+ service_t _service, instance_t _instance) const;
+
private:
void read_data(const std::set<std::string> &_input,
std::vector<configuration_element> &_elements,
@@ -355,6 +360,9 @@ private:
instance_t _instance, eventgroup_t _eventgroup) const;
bool find_port(uint16_t &_port, uint16_t _remote, bool _reliable,
std::map<bool, std::set<uint16_t> > &_used_client_ports) const;
+ bool find_specific_port(uint16_t &_port, service_t _service,
+ instance_t _instance, bool _reliable,
+ std::map<bool, std::set<uint16_t> > &_used_client_ports) const;
void set_magic_cookies_unicast_address();
@@ -379,6 +387,9 @@ private:
void load_secure_services(const configuration_element &_element);
void load_secure_service(const boost::property_tree::ptree &_tree);
+ void load_partitions(const configuration_element &_element);
+ void load_partition(const boost::property_tree::ptree &_tree);
+
private:
std::mutex mutex_;
@@ -514,7 +525,9 @@ protected:
ET_PLUGIN_TYPE,
ET_ROUTING_CREDENTIALS,
ET_SHUTDOWN_TIMEOUT,
- ET_MAX = 42
+ ET_MAX_REMOTE_SUBSCRIBERS,
+ ET_PARTITIONS,
+ ET_MAX = 44
};
bool is_configured_[ET_MAX];
@@ -552,7 +565,7 @@ protected:
bool has_issued_methods_warning_;
bool has_issued_clients_warning_;
- std::uint32_t udp_receive_buffer_size_;
+ int udp_receive_buffer_size_;
std::chrono::nanoseconds npdu_default_debounce_requ_;
std::chrono::nanoseconds npdu_default_debounce_resp_;
@@ -568,6 +581,14 @@ protected:
uint32_t statistics_interval_;
uint32_t statistics_min_freq_;
uint32_t statistics_max_messages_;
+ uint8_t max_remote_subscribers_;
+
+ mutable std::mutex partitions_mutex_;
+ std::map<service_t,
+ std::map<instance_t,
+ partition_id_t
+ >
+ > partitions_;
};
} // namespace cfg
diff --git a/implementation/configuration/include/internal.hpp.in b/implementation/configuration/include/internal.hpp.in
index cc21616..efd9ba0 100644
--- a/implementation/configuration/include/internal.hpp.in
+++ b/implementation/configuration/include/internal.hpp.in
@@ -88,6 +88,8 @@
#define VSOMEIP_DEFAULT_STATISTICS_MIN_FREQ 50
#define VSOMEIP_DEFAULT_STATISTICS_INTERVAL 10000
+#define VSOMEIP_DEFAULT_MAX_REMOTE_SUBSCRIBERS 3
+
#define VSOMEIP_MAX_WAIT_SENT 5
#define VSOMEIP_COMMAND_HEADER_SIZE 7
@@ -138,6 +140,9 @@
#define VSOMEIP_UPDATE_SECURITY_CREDENTIALS 0x27
#define VSOMEIP_DISTRIBUTE_SECURITY_POLICIES 0x28
#define VSOMEIP_UPDATE_SECURITY_POLICY_INT 0x29
+#define VSOMEIP_EXPIRED_SUBSCRIPTION 0x2A
+
+#define VSOMEIP_SUSPEND 0x30
#define VSOMEIP_SEND_COMMAND_SIZE 13
#define VSOMEIP_SEND_COMMAND_INSTANCE_POS_MIN 7
@@ -170,6 +175,7 @@
#define VSOMEIP_REGISTER_APPLICATION_COMMAND_SIZE 7
#define VSOMEIP_DEREGISTER_APPLICATION_COMMAND_SIZE 7
#define VSOMEIP_REGISTERED_ACK_COMMAND_SIZE 7
+#define VSOMEIP_EXPIRED_SUBSCRIPTION_COMMAND_SIZE 17
#ifndef _WIN32
@@ -233,6 +239,9 @@ enum class port_type_e {
PT_UNKNOWN
};
+typedef uint8_t partition_id_t;
+const partition_id_t VSOMEIP_DEFAULT_PARTITION_ID = 0;
+
} // namespace vsomeip_v3
#endif // VSOMEIP_V3_INTERNAL_HPP_
diff --git a/implementation/configuration/include/internal_android.hpp b/implementation/configuration/include/internal_android.hpp
index 25ecb4e..8ecd2b5 100644
--- a/implementation/configuration/include/internal_android.hpp
+++ b/implementation/configuration/include/internal_android.hpp
@@ -72,6 +72,8 @@
#define VSOMEIP_DEFAULT_STATISTICS_MIN_FREQ 50
#define VSOMEIP_DEFAULT_STATISTICS_INTERVAL 10000
+#define VSOMEIP_DEFAULT_MAX_REMOTE_SUBSCRIBERS 3
+
#define VSOMEIP_MAX_WAIT_SENT 5
#define VSOMEIP_COMMAND_HEADER_SIZE 7
@@ -122,6 +124,9 @@
#define VSOMEIP_UPDATE_SECURITY_CREDENTIALS 0x27
#define VSOMEIP_DISTRIBUTE_SECURITY_POLICIES 0x28
#define VSOMEIP_UPDATE_SECURITY_POLICY_INT 0x29
+#define VSOMEIP_EXPIRED_SUBSCRIPTION 0x2A
+
+#define VSOMEIP_SUSPEND 0x30
#define VSOMEIP_SEND_COMMAND_SIZE 13
#define VSOMEIP_SEND_COMMAND_INSTANCE_POS_MIN 7
@@ -154,6 +159,7 @@
#define VSOMEIP_REGISTER_APPLICATION_COMMAND_SIZE 7
#define VSOMEIP_DEREGISTER_APPLICATION_COMMAND_SIZE 7
#define VSOMEIP_REGISTERED_ACK_COMMAND_SIZE 7
+#define VSOMEIP_EXPIRED_SUBSCRIPTION_COMMAND_SIZE 17
#include <pthread.h>
@@ -214,6 +220,9 @@ enum class port_type_e {
PT_UNKNOWN
};
+typedef uint8_t partition_id_t;
+const partition_id_t VSOMEIP_DEFAULT_PARTITION_ID = 0;
+
} // namespace vsomeip_v3
#endif // VSOMEIP_V3_INTERNAL_HPP_
diff --git a/implementation/configuration/src/configuration_impl.cpp b/implementation/configuration/src/configuration_impl.cpp
index 0e9ca51..6fdbb67 100644
--- a/implementation/configuration/src/configuration_impl.cpp
+++ b/implementation/configuration/src/configuration_impl.cpp
@@ -94,7 +94,8 @@ configuration_impl::configuration_impl()
log_statistics_(true),
statistics_interval_(VSOMEIP_DEFAULT_STATISTICS_INTERVAL),
statistics_min_freq_(VSOMEIP_DEFAULT_STATISTICS_MIN_FREQ),
- statistics_max_messages_(VSOMEIP_DEFAULT_STATISTICS_MAX_MSG) {
+ statistics_max_messages_(VSOMEIP_DEFAULT_STATISTICS_MAX_MSG),
+ max_remote_subscribers_(VSOMEIP_DEFAULT_MAX_REMOTE_SUBSCRIBERS) {
unicast_ = unicast_.from_string(VSOMEIP_UNICAST_ADDRESS);
netmask_ = netmask_.from_string(VSOMEIP_NETMASK);
for (auto i = 0; i < ET_MAX; i++)
@@ -199,6 +200,7 @@ configuration_impl::configuration_impl(const configuration_impl &_other)
statistics_interval_ = _other.statistics_interval_;
statistics_min_freq_ = _other.statistics_min_freq_;
statistics_max_messages_ = _other.statistics_max_messages_;
+ max_remote_subscribers_ = _other.max_remote_subscribers_;
}
configuration_impl::~configuration_impl() {
@@ -510,6 +512,7 @@ bool configuration_impl::load_data(const std::vector<configuration_element> &_el
load_debounce(e);
load_acceptances(e);
load_secure_services(e);
+ load_partitions(e);
}
}
@@ -1320,6 +1323,24 @@ void configuration_impl::load_service_discovery(
load_ttl_factors(i->second, &ttl_factors_subscriptions_);
is_configured_[ET_SERVICE_DISCOVERY_TTL_FACTOR_SUBSCRIPTIONS] = true;
}
+ } else if (its_key == "max_remote_subscribers") {
+ if (!is_overlay_ && is_configured_[ET_MAX_REMOTE_SUBSCRIBERS]) {
+ VSOMEIP_WARNING << "Multiple definitions for service_discovery.max_remote_subscribers."
+ " Ignoring definition from " << _element.name_;
+ } else {
+ int tmp;
+ its_converter << its_value;
+ its_converter >> tmp;
+ max_remote_subscribers_ = (tmp > (std::numeric_limits<std::uint8_t>::max)()) ?
+ (std::numeric_limits<std::uint8_t>::max)() :
+ static_cast<std::uint8_t>(tmp);
+ if (max_remote_subscribers_ == 0) {
+ VSOMEIP_WARNING << "max_remote_subscribers_ = 0 is not allowed. Using default ("
+ << std::dec << VSOMEIP_DEFAULT_MAX_REMOTE_SUBSCRIBERS << ")";
+ max_remote_subscribers_ = VSOMEIP_DEFAULT_MAX_REMOTE_SUBSCRIBERS;
+ }
+ is_configured_[ET_MAX_REMOTE_SUBSCRIBERS] = true;
+ }
}
}
} catch (...) {
@@ -1832,6 +1853,10 @@ void configuration_impl::load_client(const boost::property_tree::ptree &_tree) {
its_client->remote_ports_[false] = std::make_pair(ILLEGAL_PORT, ILLEGAL_PORT);
its_client->client_ports_[true] = std::make_pair(ILLEGAL_PORT, ILLEGAL_PORT);
its_client->client_ports_[false] = std::make_pair(ILLEGAL_PORT, ILLEGAL_PORT);
+ its_client->last_used_specific_client_port_[true] = ILLEGAL_PORT;
+ its_client->last_used_specific_client_port_[false] = ILLEGAL_PORT;
+ its_client->last_used_client_port_[true] = ILLEGAL_PORT;
+ its_client->last_used_client_port_[false] = ILLEGAL_PORT;
for (auto i = _tree.begin(); i != _tree.end(); ++i) {
std::string its_key(i->first);
@@ -2128,6 +2153,92 @@ void configuration_impl::load_selective_broadcasts_support(const configuration_e
}
}
+
+void
+configuration_impl::load_partitions(const configuration_element &_element) {
+
+ try {
+ auto its_partitions = _element.tree_.get_child("partitions");
+ for (auto i = its_partitions.begin(); i != its_partitions.end(); ++i) {
+ load_partition(i->second);
+ }
+ } catch (...) {
+ }
+}
+
+void
+configuration_impl::load_partition(const boost::property_tree::ptree &_tree) {
+
+ static partition_id_t its_partition_id(VSOMEIP_DEFAULT_PARTITION_ID);
+
+ try {
+
+ std::stringstream its_converter;
+ std::map<service_t, std::set<instance_t> > its_partition_members;
+
+ for (auto i = _tree.begin(); i != _tree.end(); ++i) {
+ service_t its_service(0x0);
+ instance_t its_instance(0x0);
+ std::string its_service_s, its_instance_s;
+
+ for (auto j = i->second.begin(); j != i->second.end(); ++j) {
+ std::string its_key(j->first);
+ std::string its_data(j->second.data());
+
+ its_converter.str("");
+ its_converter.clear();
+
+ if (its_data.find("0x") != std::string::npos)
+ its_converter << std::hex;
+ else
+ its_converter << std::dec;
+ its_converter << its_data;
+
+ if (its_key == "service") {
+ its_converter >> its_service;
+ its_service_s = its_data;
+ } else if (its_key == "instance") {
+ its_converter >> its_instance;
+ its_instance_s = its_data;
+ }
+ }
+
+ if (its_service > 0 && its_instance > 0)
+ its_partition_members[its_service].insert(its_instance);
+ else
+ VSOMEIP_ERROR << "P: <" << its_service_s << "."
+ << its_instance_s << "> is no valid service instance.";
+
+ }
+
+ if (!its_partition_members.empty()) {
+ std::lock_guard<std::mutex> its_lock(partitions_mutex_);
+ its_partition_id++;
+
+ std::stringstream its_log;
+ its_log << "P"
+ << std::dec << static_cast<int>(its_partition_id)
+ << " [";
+
+ for (const auto &i : its_partition_members) {
+ for (const auto j : i.second) {
+ partitions_[i.first][j] = its_partition_id;
+ its_log << "<"
+ << std::setw(4) << std::setfill('0') << std::hex
+ << i.first << "."
+ << std::setw(4) << std::setfill('0') << std::hex
+ << j
+ << ">";
+ }
+ }
+
+ its_log << "]";
+ VSOMEIP_INFO << its_log.str();
+ }
+ } catch (...) {
+ }
+}
+
///////////////////////////////////////////////////////////////////////////////
// Internal helper
///////////////////////////////////////////////////////////////////////////////
@@ -2351,19 +2462,14 @@ bool configuration_impl::get_client_port(
std::map<bool, std::set<uint16_t> > &_used_client_ports,
uint16_t &_client_port) const {
bool is_configured(false);
-
_client_port = ILLEGAL_PORT;
- auto its_client = find_client(_service, _instance);
- // Check for service, instance specific port configuration
- if (its_client && !its_client->ports_[_reliable].empty()) {
+ uint16_t its_specific_port(ILLEGAL_PORT);
+ if (find_specific_port(its_specific_port, _service, _instance, _reliable, _used_client_ports)) {
is_configured = true;
- for (auto its_port : its_client->ports_[_reliable]) {
- // Found free configured port
- if (_used_client_ports[_reliable].find(its_port) == _used_client_ports[_reliable].end()) {
- _client_port = its_port;
- return true;
- }
+ if (its_specific_port != ILLEGAL_PORT) {
+ _client_port = its_specific_port;
+ return true;
}
}
@@ -2615,18 +2721,120 @@ bool configuration_impl::find_port(uint16_t &_port, uint16_t _remote, bool _reli
std::list<std::shared_ptr<client>>::const_iterator it;
for (it = clients_.begin(); it != clients_.end(); ++it) {
- if (is_in_port_range(_remote, (*it)->remote_ports_[_reliable])) {
+ if (_remote != ILLEGAL_PORT && is_in_port_range(_remote,
+ (*it)->remote_ports_[_reliable])) {
is_configured = true;
- for (uint16_t its_port = (*it)->client_ports_[_reliable].first;
- its_port <= (*it)->client_ports_[_reliable].second; its_port++ ) {
- if (_used_client_ports[_reliable].find(its_port) == _used_client_ports[_reliable].end()) {
+ uint16_t its_port(ILLEGAL_PORT);
+ if ((*it)->last_used_client_port_[_reliable] != ILLEGAL_PORT &&
+ is_in_port_range(((*it)->last_used_client_port_[_reliable])++,
+ (*it)->client_ports_[_reliable])) {
+ its_port = ((*it)->last_used_client_port_[_reliable])++;
+ } else {
+ // on initial start of port search
+ if ((*it)->last_used_client_port_[_reliable] == ILLEGAL_PORT) {
+ its_port = (*it)->client_ports_[_reliable].first;
+ } else {
+ continue;
+ }
+ }
+ while (its_port <= (*it)->client_ports_[_reliable].second) {
+ if (_used_client_ports[_reliable].find(its_port)
+ == _used_client_ports[_reliable].end()) {
+ _port = its_port;
+ (*it)->last_used_client_port_[_reliable] = its_port;
+ return true;
+ }
+ its_port++;
+ }
+ }
+ }
+ // no free port was found in _used_client_ports or last_used_port
+ // cannot be incremented for any client port range
+ // -> reset last used port for all available client port ranges
+ for (it = clients_.begin(); it != clients_.end(); ++it) {
+ if (_remote != ILLEGAL_PORT && is_in_port_range(_remote,
+ (*it)->remote_ports_[_reliable])) {
+ (*it)->last_used_client_port_[_reliable] = ILLEGAL_PORT;
+ }
+ }
+ // ensure that all configured client ports are checked from beginning
+ for (it = clients_.begin(); it != clients_.end(); ++it) {
+ if (_remote != ILLEGAL_PORT && is_in_port_range(_remote,
+ (*it)->remote_ports_[_reliable])) {
+ uint16_t its_port(ILLEGAL_PORT);
+ its_port = (*it)->client_ports_[_reliable].first;
+ while (its_port <= (*it)->client_ports_[_reliable].second) {
+ if (_used_client_ports[_reliable].find(its_port)
+ == _used_client_ports[_reliable].end()) {
_port = its_port;
+ (*it)->last_used_client_port_[_reliable] = its_port;
return true;
}
+ its_port++;
}
}
}
+ return is_configured;
+}
+
+bool configuration_impl::find_specific_port(uint16_t &_port, service_t _service,
+ instance_t _instance, bool _reliable,
+ std::map<bool, std::set<uint16_t> > &_used_client_ports) const {
+ bool is_configured(false);
+ bool check_all(false);
+ std::list<std::shared_ptr<client>>::const_iterator it;
+ auto its_client = find_client(_service, _instance);
+ // Check for service, instance specific port configuration
+ if (its_client && !its_client->ports_[_reliable].empty()) {
+ is_configured = true;
+ std::set<uint16_t>::const_iterator it;
+ if (its_client->last_used_specific_client_port_[_reliable] == ILLEGAL_PORT) {
+ it = its_client->ports_[_reliable].begin();
+ } else {
+ it = its_client->ports_[_reliable].find(
+ its_client->last_used_specific_client_port_[_reliable]);
+ auto it_next = std::next(it, 1);
+ if (it_next != its_client->ports_[_reliable].end()) {
+ check_all = true;
+ it = it_next;
+ } else {
+ it = its_client->ports_[_reliable].begin();
+ }
+ }
+ while (it != its_client->ports_[_reliable].end()) {
+ if (_used_client_ports[_reliable].find(*it)
+ == _used_client_ports[_reliable].end()) {
+ _port = *it;
+ its_client->last_used_specific_client_port_[_reliable] = *it;
+ VSOMEIP_INFO << "configuration_impl:find_specific_port #1:"
+ << " service: " << std::hex << _service
+ << " instance: " << _instance
+ << " reliable: " << std::dec << _reliable
+ << " return specific port: " << (uint32_t)_port;
+ return true;
+ }
+ ++it;
+ }
+ if (check_all) {
+ // no free port was found
+ // ensure that all configured client ports are checked from beginning
+ for (auto its_port : _used_client_ports[_reliable]) {
+ if (_used_client_ports[_reliable].find(its_port)
+ == _used_client_ports[_reliable].end()) {
+ _port = its_port;
+ its_client->last_used_specific_client_port_[_reliable] = its_port;
+ VSOMEIP_INFO << "configuration_impl:find_specific_port #2:"
+ << " service: " << std::hex << _service
+ << " instance: " << _instance
+ << " reliable: " << std::dec << _reliable
+ << " return specific port: " << (uint32_t)_port;
+ return true;
+ }
+ }
+ }
+ its_client->last_used_specific_client_port_[_reliable] = ILLEGAL_PORT;
+ }
return is_configured;
}
@@ -3414,23 +3622,54 @@ configuration_impl::load_acceptance_data(
// If optional was not set, use default!
if (!has_optional) {
const auto its_optional_client = boost::icl::interval<std::uint16_t>::closed(30491, 30499);
+ const auto its_optional_client_spare = boost::icl::interval<std::uint16_t>::closed(30898, 30998);
const auto its_optional_server = boost::icl::interval<std::uint16_t>::closed(30501, 30599);
its_ports.operator [](is_reliable).first.insert(its_optional_client);
+ its_ports.operator [](is_reliable).first.insert(its_optional_client_spare);
its_ports.operator [](is_reliable).first.insert(its_optional_server);
}
// If secure was not set, use default!
if (!has_secure) {
const auto its_secure_client = boost::icl::interval<std::uint16_t>::closed(32491, 32499);
+ const auto its_secure_client_spare = boost::icl::interval<std::uint16_t>::closed(32898, 32998);
const auto its_secure_server = boost::icl::interval<std::uint16_t>::closed(32501, 32599);
its_ports.operator [](is_reliable).second.insert(its_secure_client);
+ its_ports.operator [](is_reliable).second.insert(its_secure_client_spare);
its_ports.operator [](is_reliable).second.insert(its_secure_server);
}
}
}
+ // If no ports are specified, use default!
+ if (its_ports.empty()) {
+ const auto its_optional_client = boost::icl::interval<std::uint16_t>::closed(30491, 30499);
+ const auto its_optional_client_spare = boost::icl::interval<std::uint16_t>::closed(30898, 30998);
+ const auto its_optional_server = boost::icl::interval<std::uint16_t>::closed(30501, 30599);
+
+ // optional
+ its_ports.operator [](false).first.insert(its_optional_client);
+ its_ports.operator [](false).first.insert(its_optional_client_spare);
+ its_ports.operator [](false).first.insert(its_optional_server);
+ its_ports.operator [](true).first.insert(its_optional_client);
+ its_ports.operator [](true).first.insert(its_optional_client_spare);
+ its_ports.operator [](true).first.insert(its_optional_server);
+
+ // secure
+ const auto its_secure_client = boost::icl::interval<std::uint16_t>::closed(32491, 32499);
+ const auto its_secure_client_spare = boost::icl::interval<std::uint16_t>::closed(32898, 32998);
+ const auto its_secure_server = boost::icl::interval<std::uint16_t>::closed(32501, 32599);
+
+ its_ports.operator [](false).second.insert(its_secure_client);
+ its_ports.operator [](false).second.insert(its_secure_client_spare);
+ its_ports.operator [](false).second.insert(its_secure_server);
+ its_ports.operator [](true).second.insert(its_secure_client);
+ its_ports.operator [](true).second.insert(its_secure_client_spare);
+ its_ports.operator [](true).second.insert(its_secure_server);
+ }
+
if (!its_address.is_unspecified()) {
sd_acceptance_rules_.insert(
std::make_pair(its_address,
@@ -3572,8 +3811,7 @@ configuration_impl::load_udp_receive_buffer_size(const configuration_element &_e
} else {
const std::string s(_element.tree_.get_child(urbs).data());
try {
- udp_receive_buffer_size_ = static_cast<std::uint32_t>(std::stoul(
- s.c_str(), NULL, 10));
+ udp_receive_buffer_size_ = std::stoi(s.c_str(), NULL, 10);
} catch (const std::exception &e) {
VSOMEIP_ERROR<< __func__ << ": " << urbs << " " << e.what();
}
@@ -3774,8 +4012,11 @@ void configuration_impl::set_sd_acceptance_rule(
std::lock_guard<std::mutex> its_lock(sd_acceptance_required_ips_mutex_);
const auto its_optional_client = boost::icl::interval<std::uint16_t>::closed(30491, 30499);
+ const auto its_optional_client_spare = boost::icl::interval<std::uint16_t>::closed(30898, 30998);
const auto its_optional_server = boost::icl::interval<std::uint16_t>::closed(30501, 30599);
+
const auto its_secure_client = boost::icl::interval<std::uint16_t>::closed(32491, 32499);
+ const auto its_secure_client_spare = boost::icl::interval<std::uint16_t>::closed(32898, 32998);
const auto its_secure_server = boost::icl::interval<std::uint16_t>::closed(32501, 32599);
const bool rules_active = (sd_acceptance_rules_active_.find(_address)
@@ -3801,8 +4042,10 @@ void configuration_impl::set_sd_acceptance_rule(
(found_reliability->second.first.empty()
&& found_reliability->second.second.empty())) {
found_reliability->second.first.add(its_optional_client);
+ found_reliability->second.first.add(its_optional_client_spare);
found_reliability->second.first.add(its_optional_server);
found_reliability->second.second.add(its_secure_client);
+ found_reliability->second.second.add(its_secure_client_spare);
found_reliability->second.second.add(its_secure_server);
if (!rules_active) {
sd_acceptance_rules_active_.insert(_address);
@@ -3819,8 +4062,10 @@ void configuration_impl::set_sd_acceptance_rule(
}
} else {
found_reliability->second.first.erase(its_optional_client);
+ found_reliability->second.first.erase(its_optional_client_spare);
found_reliability->second.first.erase(its_optional_server);
found_reliability->second.second.erase(its_secure_client);
+ found_reliability->second.second.erase(its_secure_client_spare);
found_reliability->second.second.erase(its_secure_server);
if (found_reliability->second.first.empty()
&& found_reliability->second.second.empty()) {
@@ -3836,9 +4081,11 @@ void configuration_impl::set_sd_acceptance_rule(
} else if (_enable) {
boost::icl::interval_set<std::uint16_t> its_optional_default;
its_optional_default.add(its_optional_client);
+ its_optional_default.add(its_optional_client_spare);
its_optional_default.add(its_optional_server);
boost::icl::interval_set<std::uint16_t> its_secure_default;
its_secure_default.add(its_secure_client);
+ its_secure_default.add(its_secure_client_spare);
its_secure_default.add(its_secure_server);
found_address->second.second.emplace(
@@ -3857,9 +4104,11 @@ void configuration_impl::set_sd_acceptance_rule(
} else if (_enable) {
boost::icl::interval_set<std::uint16_t> its_optional_default;
its_optional_default.add(its_optional_client);
+ its_optional_default.add(its_optional_client_spare);
its_optional_default.add(its_optional_server);
boost::icl::interval_set<std::uint16_t> its_secure_default;
its_secure_default.add(its_secure_client);
+ its_secure_default.add(its_secure_client_spare);
its_secure_default.add(its_secure_server);
sd_acceptance_rules_.emplace(std::make_pair(_address,
@@ -3921,7 +4170,7 @@ bool configuration_impl::is_secure_service(service_t _service, instance_t _insta
return (false);
}
-std::uint32_t configuration_impl::get_udp_receive_buffer_size() const {
+int configuration_impl::get_udp_receive_buffer_size() const {
return udp_receive_buffer_size_;
}
@@ -4001,5 +4250,27 @@ uint32_t configuration_impl::get_statistics_max_messages() const {
return statistics_max_messages_;
}
-} // namespace config
+uint8_t configuration_impl::get_max_remote_subscribers() const {
+ return max_remote_subscribers_;
+}
+
+partition_id_t
+configuration_impl::get_partition_id(
+ service_t _service, instance_t _instance) const {
+
+ partition_id_t its_id(VSOMEIP_DEFAULT_PARTITION_ID);
+
+ std::lock_guard<std::mutex> its_lock(partitions_mutex_);
+ auto find_service = partitions_.find(_service);
+ if (find_service != partitions_.end()) {
+ auto find_instance = find_service->second.find(_instance);
+ if (find_instance != find_service->second.end()) {
+ its_id = find_instance->second;
+ }
+ }
+
+ return (its_id);
+}
+
+} // namespace cfg
} // namespace vsomeip_v3
diff --git a/implementation/endpoints/include/client_endpoint_impl.hpp b/implementation/endpoints/include/client_endpoint_impl.hpp
index 4411a50..518e696 100644
--- a/implementation/endpoints/include/client_endpoint_impl.hpp
+++ b/implementation/endpoints/include/client_endpoint_impl.hpp
@@ -70,6 +70,7 @@ public:
virtual std::uint16_t get_remote_port() const;
std::uint16_t get_local_port() const;
+ void set_local_port(uint16_t _port);
virtual bool is_reliable() const = 0;
size_t get_queue_size() const;
@@ -93,7 +94,8 @@ protected:
CONNECTED,
ESTABLISHED
};
- virtual void send_queued() = 0;
+ message_buffer_ptr_t get_front();
+ virtual void send_queued(message_buffer_ptr_t _buffer) = 0;
virtual void get_configured_times_from_endpoint(
service_t _service, method_t _method,
std::chrono::nanoseconds *_debouncing,
diff --git a/implementation/endpoints/include/endpoint.hpp b/implementation/endpoints/include/endpoint.hpp
index ccfe96b..3eafc3a 100644
--- a/implementation/endpoints/include/endpoint.hpp
+++ b/implementation/endpoints/include/endpoint.hpp
@@ -52,6 +52,7 @@ public:
virtual void remove_default_target(service_t _service) = 0;
virtual std::uint16_t get_local_port() const = 0;
+ virtual void set_local_port(uint16_t _port) = 0;
virtual bool is_reliable() const = 0;
virtual bool is_local() const = 0;
diff --git a/implementation/endpoints/include/endpoint_host.hpp b/implementation/endpoints/include/endpoint_host.hpp
index 61c012c..2af1697 100644
--- a/implementation/endpoints/include/endpoint_host.hpp
+++ b/implementation/endpoints/include/endpoint_host.hpp
@@ -29,6 +29,7 @@ public:
virtual void on_connect(std::shared_ptr<endpoint> _endpoint) = 0;
virtual void on_disconnect(std::shared_ptr<endpoint> _endpoint) = 0;
+ virtual bool on_bind_error(std::shared_ptr<endpoint> _endpoint, uint16_t _remote_port) = 0;
virtual void on_error(const byte_t *_data, length_t _length,
endpoint* const _receiver,
const boost::asio::ip::address &_remote_address,
diff --git a/implementation/endpoints/include/endpoint_impl.hpp b/implementation/endpoints/include/endpoint_impl.hpp
index 953201c..76f4698 100644
--- a/implementation/endpoints/include/endpoint_impl.hpp
+++ b/implementation/endpoints/include/endpoint_impl.hpp
@@ -43,6 +43,7 @@ public:
void remove_default_target(service_t);
virtual std::uint16_t get_local_port() const = 0;
+ virtual void set_local_port(uint16_t _port) = 0;
virtual bool is_reliable() const = 0;
void increment_use_count();
diff --git a/implementation/endpoints/include/endpoint_manager_base.hpp b/implementation/endpoints/include/endpoint_manager_base.hpp
index 2a766f9..aa21269 100644
--- a/implementation/endpoints/include/endpoint_manager_base.hpp
+++ b/implementation/endpoints/include/endpoint_manager_base.hpp
@@ -50,6 +50,7 @@ public:
// endpoint_host interface
virtual void on_connect(std::shared_ptr<endpoint> _endpoint);
virtual void on_disconnect(std::shared_ptr<endpoint> _endpoint);
+ virtual bool on_bind_error(std::shared_ptr<endpoint> _endpoint, uint16_t _remote_port);
virtual void on_error(const byte_t *_data, length_t _length,
endpoint* const _receiver,
const boost::asio::ip::address &_remote_address,
diff --git a/implementation/endpoints/include/endpoint_manager_impl.hpp b/implementation/endpoints/include/endpoint_manager_impl.hpp
index a7d28c6..3354947 100644
--- a/implementation/endpoints/include/endpoint_manager_impl.hpp
+++ b/implementation/endpoints/include/endpoint_manager_impl.hpp
@@ -82,6 +82,8 @@ public:
// endpoint_host interface
void on_connect(std::shared_ptr<endpoint> _endpoint);
void on_disconnect(std::shared_ptr<endpoint> _endpoint);
+ bool on_bind_error(std::shared_ptr<endpoint> _endpoint,
+ std::uint16_t _remote_port);
void on_error(const byte_t *_data, length_t _length,
endpoint* const _receiver,
const boost::asio::ip::address &_remote_address,
@@ -113,8 +115,15 @@ private:
std::map<bool, std::shared_ptr<endpoint>>>> remote_services_t;
remote_services_t remote_services_;
- typedef std::map<boost::asio::ip::address, std::map<uint16_t,
- std::map<bool, std::shared_ptr<endpoint>>>> client_endpoints_by_ip_t;
+ typedef std::map<boost::asio::ip::address,
+ std::map<uint16_t,
+ std::map<bool,
+ std::map<partition_id_t,
+ std::shared_ptr<endpoint>
+ >
+ >
+ >
+ > client_endpoints_by_ip_t;
client_endpoints_by_ip_t client_endpoints_by_ip_;
std::map<service_t, std::map<endpoint *, instance_t> > service_instances_;
diff --git a/implementation/endpoints/include/local_client_endpoint_impl.hpp b/implementation/endpoints/include/local_client_endpoint_impl.hpp
index 0e81bf1..3eae191 100644
--- a/implementation/endpoints/include/local_client_endpoint_impl.hpp
+++ b/implementation/endpoints/include/local_client_endpoint_impl.hpp
@@ -62,7 +62,7 @@ public:
std::chrono::nanoseconds *_debouncing,
std::chrono::nanoseconds *_maximum_retention) const;
private:
- void send_queued();
+ void send_queued(message_buffer_ptr_t _buffer);
void send_magic_cookie();
diff --git a/implementation/endpoints/include/local_server_endpoint_impl.hpp b/implementation/endpoints/include/local_server_endpoint_impl.hpp
index 965f03c..8fbb619 100644
--- a/implementation/endpoints/include/local_server_endpoint_impl.hpp
+++ b/implementation/endpoints/include/local_server_endpoint_impl.hpp
@@ -83,6 +83,7 @@ public:
bool is_reliable() const;
std::uint16_t get_local_port() const;
+ void set_local_port(std::uint16_t _port);
client_t assign_client(const byte_t *_data, uint32_t _size);
diff --git a/implementation/endpoints/include/server_endpoint_impl.hpp b/implementation/endpoints/include/server_endpoint_impl.hpp
index 193043c..dfa22e6 100644
--- a/implementation/endpoints/include/server_endpoint_impl.hpp
+++ b/implementation/endpoints/include/server_endpoint_impl.hpp
@@ -59,6 +59,7 @@ public:
virtual bool is_reliable() const = 0;
virtual std::uint16_t get_local_port() const = 0;
+ virtual void set_local_port(uint16_t _port) = 0;
public:
void connect_cbk(boost::system::error_code const &_error);
@@ -98,8 +99,10 @@ protected:
protected:
queue_type queues_;
- std::mutex clients_mutex_;
- std::map<client_t, std::map<session_t, endpoint_type> > clients_;
+ std::mutex requests_mutex_;
+ std::map<client_t,
+ std::map<std::tuple<session_t, service_t, instance_t>, endpoint_type>
+ > requests_;
std::map<endpoint_type, std::shared_ptr<train>> trains_;
diff --git a/implementation/endpoints/include/tcp_client_endpoint_impl.hpp b/implementation/endpoints/include/tcp_client_endpoint_impl.hpp
index e8c2c9a..137571c 100644
--- a/implementation/endpoints/include/tcp_client_endpoint_impl.hpp
+++ b/implementation/endpoints/include/tcp_client_endpoint_impl.hpp
@@ -42,7 +42,7 @@ public:
void send_cbk(boost::system::error_code const &_error, std::size_t _bytes,
const message_buffer_ptr_t& _sent_msg);
private:
- void send_queued();
+ void send_queued(message_buffer_ptr_t _buffer);
void get_configured_times_from_endpoint(
service_t _service, method_t _method,
std::chrono::nanoseconds *_debouncing,
diff --git a/implementation/endpoints/include/tcp_server_endpoint_impl.hpp b/implementation/endpoints/include/tcp_server_endpoint_impl.hpp
index af9a724..bf0e1b9 100644
--- a/implementation/endpoints/include/tcp_server_endpoint_impl.hpp
+++ b/implementation/endpoints/include/tcp_server_endpoint_impl.hpp
@@ -52,6 +52,7 @@ public:
bool get_default_target(service_t, endpoint_type &) const;
std::uint16_t get_local_port() const;
+ void set_local_port(uint16_t _port);
bool is_reliable() const;
bool is_local() const;
diff --git a/implementation/endpoints/include/udp_client_endpoint_impl.hpp b/implementation/endpoints/include/udp_client_endpoint_impl.hpp
index 05c63c4..3a3fdcb 100644
--- a/implementation/endpoints/include/udp_client_endpoint_impl.hpp
+++ b/implementation/endpoints/include/udp_client_endpoint_impl.hpp
@@ -47,8 +47,11 @@ public:
bool is_local() const;
void print_status();
bool is_reliable() const;
+
+ void send_cbk(boost::system::error_code const &_error, std::size_t _bytes,
+ const message_buffer_ptr_t &_sent_msg);
private:
- void send_queued();
+ void send_queued(message_buffer_ptr_t _buffer);
void get_configured_times_from_endpoint(
service_t _service, method_t _method,
std::chrono::nanoseconds *_debouncing,
@@ -66,7 +69,7 @@ private:
private:
const boost::asio::ip::address remote_address_;
const std::uint16_t remote_port_;
- const std::uint32_t udp_receive_buffer_size_;
+ int udp_receive_buffer_size_;
std::shared_ptr<tp::tp_reassembler> tp_reassembler_;
};
diff --git a/implementation/endpoints/include/udp_server_endpoint_impl.hpp b/implementation/endpoints/include/udp_server_endpoint_impl.hpp
index 4ceefb6..fef09dc 100644
--- a/implementation/endpoints/include/udp_server_endpoint_impl.hpp
+++ b/implementation/endpoints/include/udp_server_endpoint_impl.hpp
@@ -57,6 +57,7 @@ public:
bool get_default_target(service_t _service, endpoint_type &_target) const;
std::uint16_t get_local_port() const;
+ void set_local_port(uint16_t _port);
bool is_local() const;
void print_status();
diff --git a/implementation/endpoints/include/virtual_server_endpoint_impl.hpp b/implementation/endpoints/include/virtual_server_endpoint_impl.hpp
index 38db284..adf3972 100644
--- a/implementation/endpoints/include/virtual_server_endpoint_impl.hpp
+++ b/implementation/endpoints/include/virtual_server_endpoint_impl.hpp
@@ -50,6 +50,7 @@ public:
bool get_remote_address(boost::asio::ip::address &_address) const;
std::uint16_t get_local_port() const;
+ void set_local_port(uint16_t _port);
std::uint16_t get_remote_port() const;
bool is_reliable() const;
bool is_local() const;
diff --git a/implementation/endpoints/src/client_endpoint_impl.cpp b/implementation/endpoints/src/client_endpoint_impl.cpp
index 9b31cc1..66b3138 100644
--- a/implementation/endpoints/src/client_endpoint_impl.cpp
+++ b/implementation/endpoints/src/client_endpoint_impl.cpp
@@ -120,9 +120,24 @@ void client_endpoint_impl<Protocol>::stop() {
connect_timer_.cancel(ec);
}
connect_timeout_ = VSOMEIP_DEFAULT_CONNECT_TIMEOUT;
- shutdown_and_close_socket(false);
+
+ // bind to strand as stop() might be called from different thread
+ strand_.dispatch(std::bind(&client_endpoint_impl::shutdown_and_close_socket,
+ this->shared_from_this(),
+ false)
+ );
+}
+
+template<typename Protocol>
+message_buffer_ptr_t client_endpoint_impl<Protocol>::get_front() {
+ message_buffer_ptr_t its_buffer;
+ if (queue_.size())
+ its_buffer = queue_.front();
+
+ return (its_buffer);
}
+
template<typename Protocol>
bool client_endpoint_impl<Protocol>::send_to(
const std::shared_ptr<endpoint_definition> _target, const byte_t *_data,
@@ -317,7 +332,11 @@ void client_endpoint_impl<Protocol>::send_segments(
// respect minimal debounce time
wait_until_debounce_time_reached();
// ignore retention time and send immediately as the train is full anyway
- send_queued();
+ auto its_buffer = get_front();
+ if (its_buffer) {
+ strand_.dispatch(std::bind(&client_endpoint_impl::send_queued,
+ this->shared_from_this(), its_buffer));
+ }
}
train_.last_departure_ = std::chrono::steady_clock::now();
}
@@ -397,8 +416,10 @@ void client_endpoint_impl<Protocol>::connect_cbk(
if (was_not_connected_) {
was_not_connected_ = false;
std::lock_guard<std::mutex> its_lock(mutex_);
- if (queue_.size() > 0) {
- send_queued();
+ auto its_buffer = get_front();
+ if (its_buffer) {
+ strand_.dispatch(std::bind(&client_endpoint_impl::send_queued,
+ this->shared_from_this(), its_buffer));
VSOMEIP_WARNING << __func__ << ": resume sending to: "
<< get_remote_information();
}
@@ -415,7 +436,9 @@ template<typename Protocol>
void client_endpoint_impl<Protocol>::wait_connect_cbk(
boost::system::error_code const &_error) {
if (!_error && !client_endpoint_impl<Protocol>::sending_blocked_) {
- connect();
+ auto self = this->shared_from_this();
+ strand_.dispatch(std::bind(&client_endpoint_impl::connect,
+ this->shared_from_this()));
}
}
@@ -429,7 +452,9 @@ void client_endpoint_impl<Protocol>::send_cbk(
if (queue_.size() > 0) {
queue_size_ -= queue_.front()->size();
queue_.pop_front();
- send_queued();
+ auto its_buffer = get_front();
+ if (its_buffer)
+ send_queued(its_buffer);
}
} else if (_error == boost::asio::error::broken_pipe) {
state_ = cei_state_e::CLOSED;
@@ -475,7 +500,8 @@ void client_endpoint_impl<Protocol>::send_cbk(
}
was_not_connected_ = true;
shutdown_and_close_socket(true);
- connect();
+ strand_.dispatch(std::bind(&client_endpoint_impl::connect,
+ this->shared_from_this()));
} else if (_error == boost::asio::error::not_connected
|| _error == boost::asio::error::bad_descriptor
|| _error == boost::asio::error::no_permission) {
@@ -490,7 +516,8 @@ void client_endpoint_impl<Protocol>::send_cbk(
}
was_not_connected_ = true;
shutdown_and_close_socket(true);
- connect();
+ strand_.dispatch(std::bind(&client_endpoint_impl::connect,
+ this->shared_from_this()));
} else if (_error == boost::asio::error::operation_aborted) {
VSOMEIP_WARNING << "cei::send_cbk received error: " << _error.message();
// endpoint was stopped
@@ -585,6 +612,11 @@ std::uint16_t client_endpoint_impl<Protocol>::get_local_port() const {
}
template<typename Protocol>
+void client_endpoint_impl<Protocol>::set_local_port(uint16_t _port) {
+ local_port_ = _port;
+}
+
+template<typename Protocol>
void client_endpoint_impl<Protocol>::start_connect_timer() {
std::lock_guard<std::mutex> its_lock(connect_timer_mutex_);
connect_timer_.expires_from_now(
@@ -665,7 +697,11 @@ void client_endpoint_impl<Protocol>::queue_train(bool _queue_size_zero_on_entry)
queue_size_ += train_.buffer_->size();
train_.buffer_ = std::make_shared<message_buffer_t>();
if (_queue_size_zero_on_entry && !queue_.empty()) { // no writing in progress
- send_queued();
+ auto its_buffer = get_front();
+ if (its_buffer) {
+ strand_.dispatch(std::bind(&client_endpoint_impl::send_queued,
+ this->shared_from_this(), its_buffer));
+ }
}
}
diff --git a/implementation/endpoints/src/endpoint_manager_base.cpp b/implementation/endpoints/src/endpoint_manager_base.cpp
index a79ae48..cfddc87 100644
--- a/implementation/endpoints/src/endpoint_manager_base.cpp
+++ b/implementation/endpoints/src/endpoint_manager_base.cpp
@@ -123,6 +123,13 @@ void endpoint_manager_base::on_disconnect(std::shared_ptr<endpoint> _endpoint) {
rm_->on_disconnect(_endpoint);
}
+bool endpoint_manager_base::on_bind_error(std::shared_ptr<endpoint> _endpoint, uint16_t _remote_port) {
+ (void)_endpoint;
+ (void)_remote_port;
+ return true;
+ // intentionally left blank
+}
+
void endpoint_manager_base::on_error(
const byte_t *_data, length_t _length, endpoint* const _receiver,
const boost::asio::ip::address &_remote_address,
@@ -158,7 +165,7 @@ endpoint_manager_base::log_client_states() const {
{
std::lock_guard<std::mutex> its_lock(local_endpoint_mutex_);
- for (const auto& e : local_endpoints_) {
+ for (const auto &e : local_endpoints_) {
size_t its_queue_size = e.second->get_queue_size();
if (its_queue_size > VSOMEIP_DEFAULT_QUEUE_WARN_SIZE) {
its_client_queue_sizes.push_back(
diff --git a/implementation/endpoints/src/endpoint_manager_impl.cpp b/implementation/endpoints/src/endpoint_manager_impl.cpp
index a82a173..dbb2107 100644
--- a/implementation/endpoints/src/endpoint_manager_impl.cpp
+++ b/implementation/endpoints/src/endpoint_manager_impl.cpp
@@ -328,8 +328,10 @@ bool endpoint_manager_impl::remove_server_endpoint(uint16_t _port, bool _reliabl
return ret;
}
-void endpoint_manager_impl::clear_client_endpoints(service_t _service, instance_t _instance,
- bool _reliable) {
+void
+endpoint_manager_impl::clear_client_endpoints(
+ service_t _service, instance_t _instance, bool _reliable) {
+
std::shared_ptr<endpoint> endpoint_to_delete;
bool other_services_reachable_through_endpoint(false);
{
@@ -371,8 +373,12 @@ void endpoint_manager_impl::clear_client_endpoints(service_t _service, instance_
}
if (!other_services_reachable_through_endpoint) {
- std::uint16_t its_port(0);
+ partition_id_t its_partition;
boost::asio::ip::address its_address;
+ std::uint16_t its_port(0);
+
+ its_partition = configuration_->get_partition_id(_service, _instance);
+
if (_reliable) {
std::shared_ptr<tcp_client_endpoint_impl> ep =
std::dynamic_pointer_cast<tcp_client_endpoint_impl>(endpoint_to_delete);
@@ -392,15 +398,21 @@ void endpoint_manager_impl::clear_client_endpoints(service_t _service, instance_
if (found_ip != client_endpoints_by_ip_.end()) {
const auto found_port = found_ip->second.find(its_port);
if (found_port != found_ip->second.end()) {
- const auto found_reliable = found_port->second.find(_reliable);
+ auto found_reliable = found_port->second.find(_reliable);
if (found_reliable != found_port->second.end()) {
- if (found_reliable->second == endpoint_to_delete) {
- found_port->second.erase(_reliable);
- // delete if necessary
- if (!found_port->second.size()) {
- found_ip->second.erase(found_port);
- if (!found_ip->second.size()) {
- client_endpoints_by_ip_.erase(found_ip);
+ const auto found_partition = found_reliable->second.find(its_partition);
+ if (found_partition != found_reliable->second.end()) {
+ if (found_partition->second == endpoint_to_delete) {
+ found_reliable->second.erase(its_partition);
+ // delete if necessary
+ if (0 == found_reliable->second.size()) {
+ found_port->second.erase(_reliable);
+ if (0 == found_port->second.size()) {
+ found_ip->second.erase(found_port);
+ if (0 == found_ip->second.size()) {
+ client_endpoints_by_ip_.erase(found_ip);
+ }
+ }
}
}
}
@@ -455,8 +467,14 @@ void endpoint_manager_impl::find_or_create_multicast_endpoint(
std::lock_guard<std::recursive_mutex> its_lock(endpoint_mutex_);
service_instances_multicast_[_service][_sender] = _instance;
}
- dynamic_cast<udp_server_endpoint_impl*>(its_endpoint.get())->join_unlocked(
- _address.to_string());
+
+ auto its_udp_server_endpoint
+ = std::dynamic_pointer_cast<udp_server_endpoint_impl>(its_endpoint);
+ if (_port != configuration_->get_sd_port()) {
+ its_udp_server_endpoint->join(_address.to_string());
+ } else {
+ its_udp_server_endpoint->join_unlocked(_address.to_string());
+ }
} else {
VSOMEIP_ERROR <<"Could not find/create multicast endpoint!";
}
@@ -540,11 +558,13 @@ void endpoint_manager_impl::print_status() const {
VSOMEIP_INFO << "status start remote client endpoints:";
std::uint32_t num_remote_client_endpoints(0);
// normal endpoints
- for (const auto &a : client_endpoints_by_ip) {
- for (const auto& p : a.second) {
- for (const auto& ru : p.second) {
- ru.second->print_status();
- num_remote_client_endpoints++;
+ for (const auto &its_address : client_endpoints_by_ip) {
+ for (const auto &its_port : its_address.second) {
+ for (const auto &its_reliability : its_port.second) {
+ for (const auto &its_partition : its_reliability.second) {
+ its_partition.second->print_status();
+ num_remote_client_endpoints++;
+ }
}
}
}
@@ -800,6 +820,37 @@ void endpoint_manager_impl::on_disconnect(std::shared_ptr<endpoint> _endpoint) {
}
}
+bool endpoint_manager_impl::on_bind_error(std::shared_ptr<endpoint> _endpoint, std::uint16_t _remote_port) {
+ std::lock_guard<std::recursive_mutex> its_ep_lock(endpoint_mutex_);
+ for (auto &its_service : remote_services_) {
+ for (auto &its_instance : its_service.second) {
+ const bool is_reliable = _endpoint->is_reliable();
+ auto found_endpoint = its_instance.second.find(is_reliable);
+ if (found_endpoint != its_instance.second.end()) {
+ if (found_endpoint->second == _endpoint) {
+ // get a new client port using service / instance / remote port
+ uint16_t its_old_local_port = _endpoint->get_local_port();
+ uint16_t its_new_local_port(ILLEGAL_PORT);
+
+ std::unique_lock<std::mutex> its_lock(used_client_ports_mutex_);
+ if (configuration_->get_client_port(its_service.first,
+ its_instance.first,
+ _remote_port,
+ is_reliable,
+ used_client_ports_,
+ its_new_local_port)) {
+ _endpoint->set_local_port(its_new_local_port);
+ its_lock.unlock();
+ release_port(its_old_local_port, _endpoint->is_reliable());
+ return true;
+ }
+ }
+ }
+ }
+ }
+ return false;
+}
+
void endpoint_manager_impl::on_error(
const byte_t *_data, length_t _length, endpoint* const _receiver,
const boost::asio::ip::address &_remote_address,
@@ -820,8 +871,10 @@ void endpoint_manager_impl::release_port(uint16_t _port, bool _reliable) {
used_client_ports_[_reliable].erase(_port);
}
-std::shared_ptr<endpoint> endpoint_manager_impl::find_remote_client(
+std::shared_ptr<endpoint>
+endpoint_manager_impl::find_remote_client(
service_t _service, instance_t _instance, bool _reliable) {
+
std::shared_ptr<endpoint> its_endpoint;
auto found_service = remote_services_.find(_service);
if (found_service != remote_services_.end()) {
@@ -837,35 +890,46 @@ std::shared_ptr<endpoint> endpoint_manager_impl::find_remote_client(
return its_endpoint;
}
- // If another service is hosted on the same server_endpoint
- // reuse the existing client_endpoint.
+ // Endpoint did not yet exist. Get the partition id to check
+ // whether the client endpoint for the partition does exist.
+ partition_id_t its_partition_id
+ = configuration_->get_partition_id(_service, _instance);
+
+ // If another service within the same partition 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()) {
+ 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()) {
+ 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<endpoint_definition> its_ep_def =
- found_reliable->second;
+ if (found_reliable != found_instance->second.end()) {
+ std::shared_ptr<endpoint_definition> 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()) {
+ 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][_reliable] =
- its_endpoint;
- service_instances_[_service][its_endpoint.get()] = _instance;
- // add endpoint to serviceinfo object
- auto found_service_info = rm_->find_service(_service,_instance);
- if (found_service_info) {
- found_service_info->set_endpoint(its_endpoint, _reliable);
+ if (found_port != found_address->second.end()) {
+ auto found_reliable2
+ = found_port->second.find(_reliable);
+ if (found_reliable2 != found_port->second.end()) {
+ auto found_partition
+ = found_reliable2->second.find(its_partition_id);
+ if (found_partition != found_reliable2->second.end()) {
+ its_endpoint = found_partition->second;
+
+ // store the endpoint under this service/instance id
+ // as well - needed for later cleanup
+ remote_services_[_service][_instance][_reliable]
+ = its_endpoint;
+ service_instances_[_service][its_endpoint.get()] = _instance;
+
+ // add endpoint to serviceinfo object
+ auto found_service_info = rm_->find_service(_service,_instance);
+ if (found_service_info) {
+ found_service_info->set_endpoint(its_endpoint, _reliable);
+ }
}
}
}
@@ -873,7 +937,8 @@ std::shared_ptr<endpoint> endpoint_manager_impl::find_remote_client(
}
}
}
- return its_endpoint;
+
+ return (its_endpoint);
}
std::shared_ptr<endpoint> endpoint_manager_impl::create_remote_client(
@@ -910,6 +975,8 @@ std::shared_ptr<endpoint> endpoint_manager_impl::create_remote_client(
}
if (its_endpoint) {
+ partition_id_t its_partition
+ = configuration_->get_partition_id(_service, _instance);
used_client_ports_[_reliable].insert(its_local_port);
its_lock.unlock();
service_instances_[_service][its_endpoint.get()] = _instance;
@@ -917,12 +984,19 @@ std::shared_ptr<endpoint> endpoint_manager_impl::create_remote_client(
client_endpoints_by_ip_[its_endpoint_def->get_address()]
[its_endpoint_def->get_port()]
- [_reliable] = its_endpoint;
+ [_reliable]
+ [its_partition]= its_endpoint;
// Set the basic route to the service in the service info
auto found_service_info = rm_->find_service(_service, _instance);
if (found_service_info) {
found_service_info->set_endpoint(its_endpoint, _reliable);
}
+ boost::system::error_code ec;
+ VSOMEIP_INFO << "endpoint_manager_impl::create_remote_client: "
+ << its_endpoint_def->get_address().to_string(ec)
+ << ":" << std::dec << its_endpoint_def->get_port()
+ << " reliable: " << _reliable
+ << " using local port: " << std::dec << its_local_port;
}
}
}
@@ -983,18 +1057,20 @@ endpoint_manager_impl::log_client_states() const {
its_client_endpoints = client_endpoints_by_ip_;
}
- for (const auto& its_address : its_client_endpoints) {
- for (const auto& its_port : its_address.second) {
- for (const auto& its_reliability : its_port.second) {
- size_t its_queue_size = its_reliability.second->get_queue_size();
- if (its_queue_size > VSOMEIP_DEFAULT_QUEUE_WARN_SIZE)
- its_client_queue_sizes.push_back(
- std::make_pair(
- std::make_tuple(
- its_address.first,
- its_port.first,
- its_reliability.first),
- its_queue_size));
+ for (const auto &its_address : its_client_endpoints) {
+ for (const auto &its_port : its_address.second) {
+ for (const auto &its_reliability : its_port.second) {
+ for (const auto &its_partition : its_reliability.second) {
+ size_t its_queue_size = its_partition.second->get_queue_size();
+ if (its_queue_size > VSOMEIP_DEFAULT_QUEUE_WARN_SIZE)
+ its_client_queue_sizes.push_back(
+ std::make_pair(
+ std::make_tuple(
+ its_address.first,
+ its_port.first,
+ its_reliability.first),
+ its_queue_size));
+ }
}
}
}
@@ -1040,8 +1116,8 @@ endpoint_manager_impl::log_server_states() const {
its_server_endpoints = server_endpoints_;
}
- for (const auto& its_port : its_server_endpoints) {
- for (const auto& its_reliability : its_port.second) {
+ for (const auto &its_port : its_server_endpoints) {
+ for (const auto &its_reliability : its_port.second) {
size_t its_queue_size = its_reliability.second->get_queue_size();
if (its_queue_size > VSOMEIP_DEFAULT_QUEUE_WARN_SIZE)
its_client_queue_sizes.push_back(
diff --git a/implementation/endpoints/src/local_client_endpoint_impl.cpp b/implementation/endpoints/src/local_client_endpoint_impl.cpp
index 7e58e67..04c7787 100644
--- a/implementation/endpoints/src/local_client_endpoint_impl.cpp
+++ b/implementation/endpoints/src/local_client_endpoint_impl.cpp
@@ -203,20 +203,13 @@ bool local_client_endpoint_impl::send(const uint8_t *_data, uint32_t _size) {
return ret;
}
-void local_client_endpoint_impl::send_queued() {
+void local_client_endpoint_impl::send_queued(message_buffer_ptr_t _buffer) {
static const byte_t its_start_tag[] = { 0x67, 0x37, 0x6D, 0x07 };
static const byte_t its_end_tag[] = { 0x07, 0x6D, 0x37, 0x67 };
std::vector<boost::asio::const_buffer> bufs;
- message_buffer_ptr_t its_buffer;
- if(queue_.size()) {
- its_buffer = queue_.front();
- } else {
- return;
- }
-
bufs.push_back(boost::asio::buffer(its_start_tag));
- bufs.push_back(boost::asio::buffer(*its_buffer));
+ bufs.push_back(boost::asio::buffer(*_buffer));
bufs.push_back(boost::asio::buffer(its_end_tag));
{
@@ -231,7 +224,7 @@ void local_client_endpoint_impl::send_queued() {
>(shared_from_this()),
std::placeholders::_1,
std::placeholders::_2,
- its_buffer
+ _buffer
)
);
}
diff --git a/implementation/endpoints/src/local_server_endpoint_impl.cpp b/implementation/endpoints/src/local_server_endpoint_impl.cpp
index 1d412e4..ebf913f 100644
--- a/implementation/endpoints/src/local_server_endpoint_impl.cpp
+++ b/implementation/endpoints/src/local_server_endpoint_impl.cpp
@@ -946,6 +946,10 @@ std::uint16_t local_server_endpoint_impl::get_local_port() const {
return 0;
}
+void local_server_endpoint_impl::set_local_port(std::uint16_t _port) {
+ (void) _port;
+}
+
bool local_server_endpoint_impl::check_packetizer_space(
queue_iterator_type _queue_iterator, message_buffer_ptr_t* _packetizer,
std::uint32_t _size) {
diff --git a/implementation/endpoints/src/server_endpoint_impl.cpp b/implementation/endpoints/src/server_endpoint_impl.cpp
index cfb5ea1..ddf6b25 100644
--- a/implementation/endpoints/src/server_endpoint_impl.cpp
+++ b/implementation/endpoints/src/server_endpoint_impl.cpp
@@ -185,38 +185,45 @@ template<typename Protocol>bool server_endpoint_impl<Protocol>::send(const uint8
const service_t its_service = VSOMEIP_BYTES_TO_WORD(
_data[VSOMEIP_SERVICE_POS_MIN], _data[VSOMEIP_SERVICE_POS_MAX]);
+ const method_t its_method = VSOMEIP_BYTES_TO_WORD(
+ _data[VSOMEIP_METHOD_POS_MIN], _data[VSOMEIP_METHOD_POS_MAX]);
const client_t its_client = VSOMEIP_BYTES_TO_WORD(
_data[VSOMEIP_CLIENT_POS_MIN], _data[VSOMEIP_CLIENT_POS_MAX]);
const session_t its_session = VSOMEIP_BYTES_TO_WORD(
_data[VSOMEIP_SESSION_POS_MIN], _data[VSOMEIP_SESSION_POS_MAX]);
- clients_mutex_.lock();
- auto found_client = clients_.find(its_client);
- if (found_client != clients_.end()) {
- auto found_session = found_client->second.find(its_session);
- if (found_session != found_client->second.end()) {
- its_target = found_session->second;
+ requests_mutex_.lock();
+ auto found_client = requests_.find(its_client);
+ if (found_client != requests_.end()) {
+ auto its_request = std::make_tuple(its_service, its_method, its_session);
+ auto found_request = found_client->second.find(its_request);
+ if (found_request != found_client->second.end()) {
+ its_target = found_request->second;
is_valid_target = true;
- found_client->second.erase(its_session);
+ found_client->second.erase(found_request);
} else {
- VSOMEIP_WARNING << "server_endpoint::send: session_id 0x"
- << std::hex << its_session
- << " not found for client 0x" << its_client;
- const method_t its_method =
- VSOMEIP_BYTES_TO_WORD(_data[VSOMEIP_METHOD_POS_MIN],
- _data[VSOMEIP_METHOD_POS_MAX]);
+ VSOMEIP_WARNING << "server_endpoint::send: request ["
+ << std::hex << std::setw(4) << std::setfill('0')
+ << its_service << "."
+ << std::hex << std::setw(4) << std::setfill('0')
+ << its_method << "/"
+ << std::hex << std::setw(4) << std::setfill('0')
+ << its_client << "."
+ << std::hex << std::setw(4) << std::setfill('0')
+ << its_session
+ << "] could not be found.";
if (its_service == VSOMEIP_SD_SERVICE
&& its_method == VSOMEIP_SD_METHOD) {
VSOMEIP_ERROR << "Clearing clients map as a request was "
"received on SD port";
- clients_.clear();
+ requests_.clear();
is_valid_target = get_default_target(its_service, its_target);
}
}
} else {
is_valid_target = get_default_target(its_service, its_target);
}
- clients_mutex_.unlock();
+ requests_mutex_.unlock();
if (is_valid_target) {
is_valid_target = send_intern(its_target, _data, _size);
@@ -757,7 +764,7 @@ size_t server_endpoint_impl<Protocol>::get_queue_size() const {
{
std::lock_guard<std::mutex> its_lock(mutex_);
- for (const auto& q : queues_) {
+ for (const auto &q : queues_) {
its_queue_size += q.second.second.size();
}
}
diff --git a/implementation/endpoints/src/tcp_client_endpoint_impl.cpp b/implementation/endpoints/src/tcp_client_endpoint_impl.cpp
index 3debcc7..f88d2a2 100644
--- a/implementation/endpoints/src/tcp_client_endpoint_impl.cpp
+++ b/implementation/endpoints/src/tcp_client_endpoint_impl.cpp
@@ -50,6 +50,7 @@ tcp_client_endpoint_impl::tcp_client_endpoint_impl(
tcp_restart_aborts_max_(configuration_->get_max_tcp_restart_aborts()),
tcp_connect_time_max_(configuration_->get_max_tcp_connect_time()),
aborted_restart_count_(0),
+ is_sending_(false),
sent_timer_(_io) {
is_supporting_magic_cookies_ = true;
@@ -67,64 +68,71 @@ bool tcp_client_endpoint_impl::is_local() const {
}
void tcp_client_endpoint_impl::start() {
- connect();
+ strand_.dispatch(std::bind(&client_endpoint_impl::connect,
+ this->shared_from_this()));
}
void tcp_client_endpoint_impl::restart(bool _force) {
- if (!_force && state_ == cei_state_e::CONNECTING) {
- std::chrono::steady_clock::time_point its_current
- = std::chrono::steady_clock::now();
- long its_connect_duration = std::chrono::duration_cast<std::chrono::milliseconds>(
- its_current - connect_timepoint_).count();
- if (aborted_restart_count_ < tcp_restart_aborts_max_
- && its_connect_duration < tcp_connect_time_max_) {
- aborted_restart_count_++;
- return;
- } else {
- VSOMEIP_WARNING << "tce::restart: maximum number of aborted restarts ["
- << tcp_restart_aborts_max_ << "] reached! its_connect_duration: "
- << its_connect_duration;
+ auto self = std::dynamic_pointer_cast< tcp_client_endpoint_impl >(shared_from_this());
+ auto restart_func = [self, _force] {
+ if (!_force && self->state_ == cei_state_e::CONNECTING) {
+ std::chrono::steady_clock::time_point its_current
+ = std::chrono::steady_clock::now();
+ long its_connect_duration = std::chrono::duration_cast<std::chrono::milliseconds>(
+ its_current - self->connect_timepoint_).count();
+ if (self->aborted_restart_count_ < self->tcp_restart_aborts_max_
+ && its_connect_duration < self->tcp_connect_time_max_) {
+ self->aborted_restart_count_++;
+ return;
+ } else {
+ VSOMEIP_WARNING << "tce::restart: maximum number of aborted restarts ["
+ << self->tcp_restart_aborts_max_ << "] reached! its_connect_duration: "
+ << its_connect_duration;
+ }
}
- }
- state_ = cei_state_e::CONNECTING;
- std::string address_port_local;
- {
- std::lock_guard<std::mutex> its_lock(socket_mutex_);
- address_port_local = get_address_port_local();
- shutdown_and_close_socket_unlocked(true);
- recv_buffer_ = std::make_shared<message_buffer_t>(recv_buffer_size_initial_, 0);
- }
- was_not_connected_ = true;
- reconnect_counter_ = 0;
- {
- std::lock_guard<std::mutex> its_lock(mutex_);
- for (const auto&m : queue_) {
- const service_t its_service = VSOMEIP_BYTES_TO_WORD(
- (*m)[VSOMEIP_SERVICE_POS_MIN],
- (*m)[VSOMEIP_SERVICE_POS_MAX]);
- const method_t its_method = VSOMEIP_BYTES_TO_WORD(
- (*m)[VSOMEIP_METHOD_POS_MIN],
- (*m)[VSOMEIP_METHOD_POS_MAX]);
- const client_t its_client = VSOMEIP_BYTES_TO_WORD(
- (*m)[VSOMEIP_CLIENT_POS_MIN],
- (*m)[VSOMEIP_CLIENT_POS_MAX]);
- const session_t its_session = VSOMEIP_BYTES_TO_WORD(
- (*m)[VSOMEIP_SESSION_POS_MIN],
- (*m)[VSOMEIP_SESSION_POS_MAX]);
- VSOMEIP_WARNING << "tce::restart: dropping message: "
- << "remote:" << get_address_port_remote() << " ("
- << std::hex << std::setw(4) << std::setfill('0') << its_client <<"): ["
- << std::hex << std::setw(4) << std::setfill('0') << its_service << "."
- << std::hex << std::setw(4) << std::setfill('0') << its_method << "."
- << std::hex << std::setw(4) << std::setfill('0') << its_session << "]"
- << " size: " << std::dec << m->size();
+ self->state_ = cei_state_e::CONNECTING;
+ std::string address_port_local;
+ {
+ std::lock_guard<std::mutex> its_lock(self->socket_mutex_);
+ address_port_local = self->get_address_port_local();
+ self->shutdown_and_close_socket_unlocked(true);
+ self->recv_buffer_ = std::make_shared<message_buffer_t>(self->recv_buffer_size_initial_, 0);
}
- queue_.clear();
- queue_size_ = 0;
- }
- VSOMEIP_WARNING << "tce::restart: local: " << address_port_local
- << " remote: " << get_address_port_remote();
- start_connect_timer();
+ self->was_not_connected_ = true;
+ self->reconnect_counter_ = 0;
+ {
+ std::lock_guard<std::mutex> its_lock(self->mutex_);
+ for (const auto&m : self->queue_) {
+ const service_t its_service = VSOMEIP_BYTES_TO_WORD(
+ (*m)[VSOMEIP_SERVICE_POS_MIN],
+ (*m)[VSOMEIP_SERVICE_POS_MAX]);
+ const method_t its_method = VSOMEIP_BYTES_TO_WORD(
+ (*m)[VSOMEIP_METHOD_POS_MIN],
+ (*m)[VSOMEIP_METHOD_POS_MAX]);
+ const client_t its_client = VSOMEIP_BYTES_TO_WORD(
+ (*m)[VSOMEIP_CLIENT_POS_MIN],
+ (*m)[VSOMEIP_CLIENT_POS_MAX]);
+ const session_t its_session = VSOMEIP_BYTES_TO_WORD(
+ (*m)[VSOMEIP_SESSION_POS_MIN],
+ (*m)[VSOMEIP_SESSION_POS_MAX]);
+ VSOMEIP_WARNING << "tce::restart: dropping message: "
+ << "remote:" << self->get_address_port_remote() << " ("
+ << std::hex << std::setw(4) << std::setfill('0') << its_client <<"): ["
+ << std::hex << std::setw(4) << std::setfill('0') << its_service << "."
+ << std::hex << std::setw(4) << std::setfill('0') << its_method << "."
+ << std::hex << std::setw(4) << std::setfill('0') << its_session << "]"
+ << " size: " << std::dec << m->size();
+ }
+ self->queue_.clear();
+ self->queue_size_ = 0;
+ }
+ VSOMEIP_WARNING << "tce::restart: local: " << address_port_local
+ << " remote: " << self->get_address_port_remote();
+ self->start_connect_timer();
+ };
+ // bind to strand_ to avoid socket closure if
+ // parallel socket operation is currently active
+ strand_.dispatch(restart_func);
}
void tcp_client_endpoint_impl::connect() {
@@ -169,26 +177,54 @@ void tcp_client_endpoint_impl::connect() {
std::string its_device(configuration_->get_device());
if (its_device != "") {
if (setsockopt(socket_->native_handle(),
- SOL_SOCKET, SO_BINDTODEVICE, its_device.c_str(), (int)its_device.size()) == -1) {
+ SOL_SOCKET, SO_BINDTODEVICE, its_device.c_str(), (socklen_t)its_device.size()) == -1) {
VSOMEIP_WARNING << "TCP Client: Could not bind to device \"" << its_device << "\"";
}
}
#endif
- // Bind address and, optionally, port.
- boost::system::error_code its_bind_error;
- socket_->bind(local_, its_bind_error);
- if(its_bind_error) {
- VSOMEIP_WARNING << "tcp_client_endpoint::connect: "
- "Error binding socket: " << its_bind_error.message()
- << " remote:" << get_address_port_remote();
- try {
- // don't connect on bind error to avoid using a random port
- strand_.post(std::bind(&client_endpoint_impl::connect_cbk,
- shared_from_this(), its_bind_error));
- } catch (const std::exception &e) {
- VSOMEIP_ERROR << "tcp_client_endpoint_impl::connect: "
- << e.what() << " remote:" << get_address_port_remote();
+ // In case a client endpoint port was configured,
+ // bind to it before connecting
+ if (local_.port() != ILLEGAL_PORT) {
+ boost::system::error_code its_bind_error;
+ socket_->bind(local_, its_bind_error);
+ if(its_bind_error) {
+ VSOMEIP_WARNING << "tcp_client_endpoint::connect: "
+ "Error binding socket: " << its_bind_error.message()
+ << " local: " << local_.address().to_string()
+ << ":" << std::dec << local_.port()
+ << " remote:" << get_address_port_remote();
+
+ std::shared_ptr<endpoint_host> its_host = endpoint_host_.lock();
+ if (its_host) {
+ // set new client port depending on service / instance / remote port
+ if (!its_host->on_bind_error(shared_from_this(), remote_port_)) {
+ VSOMEIP_WARNING << "tcp_client_endpoint::connect: "
+ "Failed to set new local port for tce: "
+ << " local: " << local_.address().to_string()
+ << ":" << std::dec << local_.port()
+ << " remote:" << get_address_port_remote();
+ } else {
+ local_.port(local_port_);
+ VSOMEIP_INFO << "tcp_client_endpoint::connect: "
+ "Using new new local port for tce: "
+ << " local: " << local_.address().to_string()
+ << ":" << std::dec << local_.port()
+ << " remote:" << get_address_port_remote();
+ }
+ }
+ try {
+ // don't connect on bind error to avoid using a random port
+ strand_.post(std::bind(&client_endpoint_impl::connect_cbk,
+ shared_from_this(), its_bind_error));
+ } catch (const std::exception &e) {
+ VSOMEIP_ERROR << "tcp_client_endpoint_impl::connect: "
+ << e.what()
+ << " local: " << local_.address().to_string()
+ << ":" << std::dec << local_.port()
+ << " remote:" << get_address_port_remote();
+ }
+ return;
}
return;
}
@@ -220,7 +256,10 @@ void tcp_client_endpoint_impl::receive() {
std::lock_guard<std::mutex> its_lock(socket_mutex_);
its_recv_buffer = recv_buffer_;
}
- receive(its_recv_buffer, 0, 0);
+ auto self = std::dynamic_pointer_cast< tcp_client_endpoint_impl >(shared_from_this());
+ strand_.dispatch([self, &its_recv_buffer](){
+ self->receive(its_recv_buffer, 0, 0);
+ });
}
void tcp_client_endpoint_impl::receive(message_buffer_ptr_t _recv_buffer,
@@ -277,32 +316,26 @@ void tcp_client_endpoint_impl::receive(message_buffer_ptr_t _recv_buffer,
}
}
-void tcp_client_endpoint_impl::send_queued() {
- message_buffer_ptr_t its_buffer;
- if(queue_.size()) {
- its_buffer = queue_.front();
- } else {
- return;
- }
+void tcp_client_endpoint_impl::send_queued(message_buffer_ptr_t _buffer) {
const service_t its_service = VSOMEIP_BYTES_TO_WORD(
- (*its_buffer)[VSOMEIP_SERVICE_POS_MIN],
- (*its_buffer)[VSOMEIP_SERVICE_POS_MAX]);
+ (*_buffer)[VSOMEIP_SERVICE_POS_MIN],
+ (*_buffer)[VSOMEIP_SERVICE_POS_MAX]);
const method_t its_method = VSOMEIP_BYTES_TO_WORD(
- (*its_buffer)[VSOMEIP_METHOD_POS_MIN],
- (*its_buffer)[VSOMEIP_METHOD_POS_MAX]);
+ (*_buffer)[VSOMEIP_METHOD_POS_MIN],
+ (*_buffer)[VSOMEIP_METHOD_POS_MAX]);
const client_t its_client = VSOMEIP_BYTES_TO_WORD(
- (*its_buffer)[VSOMEIP_CLIENT_POS_MIN],
- (*its_buffer)[VSOMEIP_CLIENT_POS_MAX]);
+ (*_buffer)[VSOMEIP_CLIENT_POS_MIN],
+ (*_buffer)[VSOMEIP_CLIENT_POS_MAX]);
const session_t its_session = VSOMEIP_BYTES_TO_WORD(
- (*its_buffer)[VSOMEIP_SESSION_POS_MIN],
- (*its_buffer)[VSOMEIP_SESSION_POS_MAX]);
+ (*_buffer)[VSOMEIP_SESSION_POS_MIN],
+ (*_buffer)[VSOMEIP_SESSION_POS_MAX]);
if (has_enabled_magic_cookies_) {
const std::chrono::steady_clock::time_point now =
std::chrono::steady_clock::now();
if (std::chrono::duration_cast<std::chrono::milliseconds>(
now - last_cookie_sent_) > std::chrono::milliseconds(10000)) {
- send_magic_cookie(its_buffer);
+ send_magic_cookie(_buffer);
last_cookie_sent_ = now;
}
}
@@ -312,9 +345,9 @@ void tcp_client_endpoint_impl::send_queued() {
std::stringstream msg;
msg << "tcei<" << remote_.address() << ":"
<< std::dec << remote_.port() << ">::sq: ";
- for (std::size_t i = 0; i < its_buffer->size(); i++)
+ for (std::size_t i = 0; i < _buffer->size(); i++)
msg << std::hex << std::setw(2) << std::setfill('0')
- << (int)(*its_buffer)[i] << " ";
+ << (int)(*_buffer)[i] << " ";
VSOMEIP_INFO << msg.str();
#endif
{
@@ -326,21 +359,23 @@ void tcp_client_endpoint_impl::send_queued() {
}
boost::asio::async_write(
*socket_,
- boost::asio::buffer(*its_buffer),
- std::bind(&tcp_client_endpoint_impl::write_completion_condition,
- std::static_pointer_cast<tcp_client_endpoint_impl>(shared_from_this()),
- std::placeholders::_1,
- std::placeholders::_2,
- its_buffer->size(),
- its_service, its_method, its_client, its_session,
- std::chrono::steady_clock::now()),
+ boost::asio::buffer(*_buffer),
std::bind(
+ &tcp_client_endpoint_impl::write_completion_condition,
+ std::static_pointer_cast<tcp_client_endpoint_impl>(shared_from_this()),
+ std::placeholders::_1,
+ std::placeholders::_2,
+ _buffer->size(),
+ its_service, its_method, its_client, its_session,
+ std::chrono::steady_clock::now()),
+ strand_.wrap(
+ std::bind(
&tcp_client_endpoint_base_impl::send_cbk,
shared_from_this(),
std::placeholders::_1,
std::placeholders::_2,
- its_buffer
- )
+ _buffer
+ ))
);
}
}
@@ -675,7 +710,10 @@ void tcp_client_endpoint_impl::receive_cbk(
}
}
its_lock.unlock();
- receive(_recv_buffer, _recv_buffer_size, its_missing_capacity);
+ auto self = std::dynamic_pointer_cast< tcp_client_endpoint_impl >(shared_from_this());
+ strand_.dispatch([self, &_recv_buffer, _recv_buffer_size, its_missing_capacity](){
+ self->receive(_recv_buffer, _recv_buffer_size, its_missing_capacity);
+ });
} else {
VSOMEIP_WARNING << "tcp_client_endpoint receive_cbk: "
<< _error.message() << "(" << std::dec << _error.value()
@@ -700,7 +738,10 @@ void tcp_client_endpoint_impl::receive_cbk(
}
} else {
its_lock.unlock();
- receive(_recv_buffer, _recv_buffer_size, its_missing_capacity);
+ auto self = std::dynamic_pointer_cast< tcp_client_endpoint_impl >(shared_from_this());
+ strand_.dispatch([self, &_recv_buffer, _recv_buffer_size, its_missing_capacity](){
+ self->receive(_recv_buffer, _recv_buffer_size, its_missing_capacity);
+ });
}
}
}
@@ -838,7 +879,13 @@ void tcp_client_endpoint_impl::send_cbk(boost::system::error_code const &_error,
if (queue_.size() > 0) {
queue_size_ -= queue_.front()->size();
queue_.pop_front();
- send_queued();
+ auto its_buffer = get_front();
+ if (its_buffer) {
+ auto self = std::dynamic_pointer_cast< tcp_client_endpoint_impl >(shared_from_this());
+ strand_.dispatch(
+ [self, its_buffer]() { self->send_queued(its_buffer);}
+ );
+ }
}
} else if (_error == boost::system::errc::destination_address_required) {
VSOMEIP_WARNING << "tce::send_cbk received error: " << _error.message()
diff --git a/implementation/endpoints/src/tcp_server_endpoint_impl.cpp b/implementation/endpoints/src/tcp_server_endpoint_impl.cpp
index 1cd2b5b..37db3f5 100644
--- a/implementation/endpoints/src/tcp_server_endpoint_impl.cpp
+++ b/implementation/endpoints/src/tcp_server_endpoint_impl.cpp
@@ -50,7 +50,7 @@ tcp_server_endpoint_impl::tcp_server_endpoint_impl(
std::string its_device(configuration_->get_device());
if (its_device != "") {
if (setsockopt(acceptor_.native_handle(),
- SOL_SOCKET, SO_BINDTODEVICE, its_device.c_str(), (int)its_device.size()) == -1) {
+ SOL_SOCKET, SO_BINDTODEVICE, its_device.c_str(), (socklen_t)its_device.size()) == -1) {
VSOMEIP_WARNING << "TCP Server: Could not bind to device \"" << its_device << "\"";
}
}
@@ -152,6 +152,38 @@ void tcp_server_endpoint_impl::send_queued(const queue_iterator_type _queue_iter
<< static_cast<std::uint16_t>(_queue_iterator->first.port())
<< " dropping outstanding messages (" << std::dec
<< _queue_iterator->second.second.size() << ").";
+
+ if (_queue_iterator->second.second.size()) {
+ std::set<service_t> its_services;
+
+ // check all outstanding messages of this connection
+ // whether stop handlers need to be called
+ for (const auto &its_buffer : _queue_iterator->second.second) {
+ if (its_buffer && its_buffer->size() > VSOMEIP_SESSION_POS_MAX) {
+ service_t its_service = VSOMEIP_BYTES_TO_WORD(
+ (*its_buffer)[VSOMEIP_SERVICE_POS_MIN],
+ (*its_buffer)[VSOMEIP_SERVICE_POS_MAX]);
+ its_services.insert(its_service);
+ }
+ }
+
+ for (auto its_service : its_services) {
+ auto found_cbk = prepare_stop_handlers_.find(its_service);
+ if (found_cbk != prepare_stop_handlers_.end()) {
+ VSOMEIP_INFO << "Calling prepare stop handler "
+ << "for service: 0x"
+ << std::hex << std::setw(4) << std::setfill('0')
+ << its_service;
+ auto handler = found_cbk->second;
+ auto ptr = this->shared_from_this();
+ service_.post([ptr, handler, its_service](){
+ handler(ptr, its_service);
+ });
+ prepare_stop_handlers_.erase(found_cbk);
+ }
+ }
+ }
+
queues_.erase(_queue_iterator->first);
}
}
@@ -259,6 +291,10 @@ std::uint16_t tcp_server_endpoint_impl::get_local_port() const {
return local_port_;
}
+void tcp_server_endpoint_impl::set_local_port(std::uint16_t _port) {
+ (void)_port;
+}
+
bool tcp_server_endpoint_impl::is_reliable() const {
return true;
}
@@ -551,12 +587,19 @@ void tcp_server_endpoint_impl::connection::receive_cbk(
recv_buffer_[its_iteration_gap + VSOMEIP_CLIENT_POS_MIN],
recv_buffer_[its_iteration_gap + VSOMEIP_CLIENT_POS_MAX]);
if (its_client != MAGIC_COOKIE_CLIENT) {
+ const service_t its_service = VSOMEIP_BYTES_TO_WORD(
+ recv_buffer_[its_iteration_gap + VSOMEIP_SERVICE_POS_MIN],
+ recv_buffer_[its_iteration_gap + VSOMEIP_SERVICE_POS_MAX]);
+ const method_t its_method = VSOMEIP_BYTES_TO_WORD(
+ recv_buffer_[its_iteration_gap + VSOMEIP_METHOD_POS_MIN],
+ recv_buffer_[its_iteration_gap + VSOMEIP_METHOD_POS_MAX]);
const session_t its_session = VSOMEIP_BYTES_TO_WORD(
recv_buffer_[its_iteration_gap + VSOMEIP_SESSION_POS_MIN],
recv_buffer_[its_iteration_gap + VSOMEIP_SESSION_POS_MAX]);
- its_server->clients_mutex_.lock();
- its_server->clients_[its_client][its_session] = remote_;
- its_server->clients_mutex_.unlock();
+
+ std::lock_guard<std::mutex> its_requests_guard(its_server->requests_mutex_);
+ its_server->requests_[its_client]
+ [std::make_tuple(its_service, its_method, its_session)] = remote_;
}
}
if (!magic_cookies_enabled_) {
diff --git a/implementation/endpoints/src/udp_client_endpoint_impl.cpp b/implementation/endpoints/src/udp_client_endpoint_impl.cpp
index dc7a7bf..3b9a212 100644
--- a/implementation/endpoints/src/udp_client_endpoint_impl.cpp
+++ b/implementation/endpoints/src/udp_client_endpoint_impl.cpp
@@ -14,6 +14,8 @@
#include "../../routing/include/routing_host.hpp"
#include "../include/udp_client_endpoint_impl.hpp"
#include "../../utility/include/utility.hpp"
+#include "../../utility/include/byteorder.hpp"
+
namespace vsomeip_v3 {
@@ -61,27 +63,50 @@ void udp_client_endpoint_impl::connect() {
socket_->set_option(boost::asio::socket_base::reuse_address(true), its_error);
if (its_error) {
VSOMEIP_WARNING << "udp_client_endpoint_impl::connect: couldn't enable "
- << "SO_REUSEADDR: " << its_error.message() << " remote:"
- << get_address_port_remote();
+ << "SO_REUSEADDR: " << its_error.message()
+ << " local port:" << std::dec << local_.port()
+ << " remote:" << get_address_port_remote();
}
+
socket_->set_option(boost::asio::socket_base::receive_buffer_size(
udp_receive_buffer_size_), its_error);
if (its_error) {
VSOMEIP_WARNING << "udp_client_endpoint_impl::connect: couldn't set "
- << "SO_RCVBUF: " << its_error.message() << " to: "
- << std::dec << udp_receive_buffer_size_ << " remote:"
- << get_address_port_remote();
- } else {
- boost::asio::socket_base::receive_buffer_size its_option;
- socket_->get_option(its_option, its_error);
- if (its_error) {
- VSOMEIP_WARNING << "udp_client_endpoint_impl::connect: couldn't get "
- << "SO_RCVBUF: " << its_error.message() << " remote:"
- << get_address_port_remote();
- } else {
- VSOMEIP_INFO << "udp_client_endpoint_impl::connect: SO_RCVBUF is: "
- << std::dec << its_option.value();
+ << "SO_RCVBUF: " << its_error.message()
+ << " to: " << std::dec << udp_receive_buffer_size_
+ << " local port:" << std::dec << local_.port()
+ << " remote:" << get_address_port_remote();
+ }
+
+ boost::asio::socket_base::receive_buffer_size its_option;
+ socket_->get_option(its_option, its_error);
+ #ifdef __linux__
+ // If regular setting of the buffer size did not work, try to force
+ // (requires CAP_NET_ADMIN to be successful)
+ if (its_option.value() < 0
+ || its_option.value() < udp_receive_buffer_size_) {
+ its_error.assign(setsockopt(socket_->native_handle(),
+ SOL_SOCKET, SO_RCVBUFFORCE,
+ &udp_receive_buffer_size_, sizeof(udp_receive_buffer_size_)),
+ boost::system::generic_category());
+ if (!its_error) {
+ VSOMEIP_INFO << "udp_client_endpoint_impl::connect: "
+ << "SO_RCVBUFFORCE successful!";
}
+ socket_->get_option(its_option, its_error);
+ }
+ #endif
+ if (its_error) {
+ VSOMEIP_WARNING << "udp_client_endpoint_impl::connect: couldn't get "
+ << "SO_RCVBUF: " << its_error.message()
+ << " local port:" << std::dec << local_.port()
+ << " remote:" << get_address_port_remote();
+ } else {
+ VSOMEIP_INFO << "udp_client_endpoint_impl::connect: SO_RCVBUF is: "
+ << std::dec << its_option.value()
+ << " (" << udp_receive_buffer_size_ << ")"
+ << " local port:" << std::dec << local_.port()
+ << " remote:" << get_address_port_remote();
}
#ifndef _WIN32
@@ -89,26 +114,53 @@ void udp_client_endpoint_impl::connect() {
std::string its_device(configuration_->get_device());
if (its_device != "") {
if (setsockopt(socket_->native_handle(),
- SOL_SOCKET, SO_BINDTODEVICE, its_device.c_str(), (int)its_device.size()) == -1) {
+ SOL_SOCKET, SO_BINDTODEVICE, its_device.c_str(), (socklen_t)its_device.size()) == -1) {
VSOMEIP_WARNING << "UDP Client: Could not bind to device \"" << its_device << "\"";
}
}
#endif
- // Bind address and, optionally, port.
- boost::system::error_code its_bind_error;
- socket_->bind(local_, its_bind_error);
- if(its_bind_error) {
- VSOMEIP_WARNING << "udp_client_endpoint::connect: "
- "Error binding socket: " << its_bind_error.message()
- << " remote:" << get_address_port_remote();
- try {
- // don't connect on bind error to avoid using a random port
- strand_.post(std::bind(&client_endpoint_impl::connect_cbk,
- shared_from_this(), its_bind_error));
- } catch (const std::exception &e) {
- VSOMEIP_ERROR << "udp_client_endpoint_impl::connect: "
- << e.what() << " remote:" << get_address_port_remote();
+ // In case a client endpoint port was configured,
+ // bind to it before connecting
+ if (local_.port() != ILLEGAL_PORT) {
+ boost::system::error_code its_bind_error;
+ socket_->bind(local_, its_bind_error);
+ if(its_bind_error) {
+ VSOMEIP_WARNING << "udp_client_endpoint::connect: "
+ "Error binding socket: " << its_bind_error.message()
+ << " local: " << local_.address().to_string()
+ << ":" << std::dec << local_.port()
+ << " remote:" << get_address_port_remote();
+
+ std::shared_ptr<endpoint_host> its_host = endpoint_host_.lock();
+ if (its_host) {
+ // set new client port depending on service / instance / remote port
+ if (!its_host->on_bind_error(shared_from_this(), remote_port_)) {
+ VSOMEIP_WARNING << "udp_client_endpoint::connect: "
+ "Failed to set new local port for uce: "
+ << " local: " << local_.address().to_string()
+ << ":" << std::dec << local_.port()
+ << " remote:" << get_address_port_remote();
+ } else {
+ local_.port(local_port_);
+ VSOMEIP_INFO << "udp_client_endpoint::connect: "
+ "Using new new local port for uce: "
+ << " local: " << local_.address().to_string()
+ << ":" << std::dec << local_.port()
+ << " remote:" << get_address_port_remote();
+ }
+ }
+
+
+ try {
+ // don't connect on bind error to avoid using a random port
+ strand_.post(std::bind(&client_endpoint_impl::connect_cbk,
+ shared_from_this(), its_bind_error));
+ } catch (const std::exception &e) {
+ VSOMEIP_ERROR << "udp_client_endpoint_impl::connect: "
+ << e.what() << " remote:" << get_address_port_remote();
+ }
+ return;
}
return;
}
@@ -158,32 +210,26 @@ void udp_client_endpoint_impl::restart(bool _force) {
start_connect_timer();
}
-void udp_client_endpoint_impl::send_queued() {
- message_buffer_ptr_t its_buffer;
- if(queue_.size()) {
- its_buffer = queue_.front();
- } else {
- return;
- }
+void udp_client_endpoint_impl::send_queued(message_buffer_ptr_t _buffer) {
#if 0
std::stringstream msg;
msg << "ucei<" << remote_.address() << ":"
<< std::dec << remote_.port() << ">::sq: ";
- for (std::size_t i = 0; i < its_buffer->size(); i++)
+ for (std::size_t i = 0; i < _buffer->size(); i++)
msg << std::hex << std::setw(2) << std::setfill('0')
- << (int)(*its_buffer)[i] << " ";
+ << (int)(*_buffer)[i] << " ";
VSOMEIP_INFO << msg.str();
#endif
{
std::lock_guard<std::mutex> its_lock(socket_mutex_);
socket_->async_send(
- boost::asio::buffer(*its_buffer),
+ boost::asio::buffer(*_buffer),
std::bind(
&udp_client_endpoint_base_impl::send_cbk,
shared_from_this(),
std::placeholders::_1,
std::placeholders::_2,
- its_buffer
+ _buffer
)
);
}
@@ -354,7 +400,12 @@ void udp_client_endpoint_impl::receive_cbk(
receive();
} else {
if (_error == boost::asio::error::connection_refused) {
- shutdown_and_close_socket(false);
+ VSOMEIP_WARNING << "uce::receive_cbk: local: " << get_address_port_local()
+ << " remote: " << get_address_port_remote()
+ << " error: " << _error.message();
+ std::shared_ptr<endpoint_host> its_ep_host = endpoint_host_.lock();
+ its_ep_host->on_disconnect(shared_from_this());
+ restart(false);
} else {
receive();
}
@@ -415,6 +466,134 @@ std::string udp_client_endpoint_impl::get_remote_information() const {
+ std::to_string(remote_.port());
}
+void udp_client_endpoint_impl::send_cbk(boost::system::error_code const &_error, std::size_t _bytes,
+ const message_buffer_ptr_t &_sent_msg) {
+ (void)_bytes;
+ if (!_error) {
+ std::lock_guard<std::mutex> its_lock(mutex_);
+ if (queue_.size() > 0) {
+ queue_size_ -= queue_.front()->size();
+ queue_.pop_front();
+ auto its_buffer = get_front();
+ if (its_buffer)
+ send_queued(its_buffer);
+ }
+ } else if (_error == boost::asio::error::broken_pipe) {
+ state_ = cei_state_e::CLOSED;
+ bool stopping(false);
+ {
+ std::lock_guard<std::mutex> its_lock(mutex_);
+ stopping = sending_blocked_;
+ if (stopping) {
+ queue_.clear();
+ queue_size_ = 0;
+ } else {
+ service_t its_service(0);
+ method_t its_method(0);
+ client_t its_client(0);
+ session_t its_session(0);
+ if (_sent_msg && _sent_msg->size() > VSOMEIP_SESSION_POS_MAX) {
+ its_service = VSOMEIP_BYTES_TO_WORD(
+ (*_sent_msg)[VSOMEIP_SERVICE_POS_MIN],
+ (*_sent_msg)[VSOMEIP_SERVICE_POS_MAX]);
+ its_method = VSOMEIP_BYTES_TO_WORD(
+ (*_sent_msg)[VSOMEIP_METHOD_POS_MIN],
+ (*_sent_msg)[VSOMEIP_METHOD_POS_MAX]);
+ its_client = VSOMEIP_BYTES_TO_WORD(
+ (*_sent_msg)[VSOMEIP_CLIENT_POS_MIN],
+ (*_sent_msg)[VSOMEIP_CLIENT_POS_MAX]);
+ its_session = VSOMEIP_BYTES_TO_WORD(
+ (*_sent_msg)[VSOMEIP_SESSION_POS_MIN],
+ (*_sent_msg)[VSOMEIP_SESSION_POS_MAX]);
+ }
+ VSOMEIP_WARNING << "uce::send_cbk received error: "
+ << _error.message() << " (" << std::dec
+ << _error.value() << ") " << get_remote_information()
+ << " " << std::dec << queue_.size()
+ << " " << std::dec << queue_size_ << " ("
+ << std::hex << std::setw(4) << std::setfill('0') << its_client <<"): ["
+ << std::hex << std::setw(4) << std::setfill('0') << its_service << "."
+ << std::hex << std::setw(4) << std::setfill('0') << its_method << "."
+ << std::hex << std::setw(4) << std::setfill('0') << its_session << "]";
+ }
+ }
+ if (!stopping) {
+ print_status();
+ }
+ was_not_connected_ = true;
+ shutdown_and_close_socket(true);
+ strand_.dispatch(std::bind(&client_endpoint_impl::connect,
+ this->shared_from_this()));
+ } else if (_error == boost::asio::error::not_connected
+ || _error == boost::asio::error::bad_descriptor
+ || _error == boost::asio::error::no_permission) {
+ state_ = cei_state_e::CLOSED;
+ if (_error == boost::asio::error::no_permission) {
+ VSOMEIP_WARNING << "uce::send_cbk received error: " << _error.message()
+ << " (" << std::dec << _error.value() << ") "
+ << get_remote_information();
+ std::lock_guard<std::mutex> its_lock(mutex_);
+ queue_.clear();
+ queue_size_ = 0;
+ }
+ was_not_connected_ = true;
+ shutdown_and_close_socket(true);
+ strand_.dispatch(std::bind(&client_endpoint_impl::connect,
+ this->shared_from_this()));
+ } else if (_error == boost::asio::error::operation_aborted) {
+ VSOMEIP_WARNING << "uce::send_cbk received error: " << _error.message();
+ // endpoint was stopped
+ sending_blocked_ = true;
+ shutdown_and_close_socket(false);
+ } else if (_error == boost::system::errc::destination_address_required) {
+ VSOMEIP_WARNING << "uce::send_cbk received error: " << _error.message()
+ << " (" << std::dec << _error.value() << ") "
+ << get_remote_information();
+ was_not_connected_ = true;
+ } else {
+ if (state_ == cei_state_e::CONNECTING) {
+ VSOMEIP_WARNING << "uce::send_cbk endpoint is already restarting:"
+ << get_remote_information();
+ } else {
+ state_ = cei_state_e::CONNECTING;
+ shutdown_and_close_socket(false);
+ std::shared_ptr<endpoint_host> its_host = endpoint_host_.lock();
+ if (its_host) {
+ its_host->on_disconnect(shared_from_this());
+ }
+ restart(true);
+ }
+ service_t its_service(0);
+ method_t its_method(0);
+ client_t its_client(0);
+ session_t its_session(0);
+ if (_sent_msg && _sent_msg->size() > VSOMEIP_SESSION_POS_MAX) {
+ its_service = VSOMEIP_BYTES_TO_WORD(
+ (*_sent_msg)[VSOMEIP_SERVICE_POS_MIN],
+ (*_sent_msg)[VSOMEIP_SERVICE_POS_MAX]);
+ its_method = VSOMEIP_BYTES_TO_WORD(
+ (*_sent_msg)[VSOMEIP_METHOD_POS_MIN],
+ (*_sent_msg)[VSOMEIP_METHOD_POS_MAX]);
+ its_client = VSOMEIP_BYTES_TO_WORD(
+ (*_sent_msg)[VSOMEIP_CLIENT_POS_MIN],
+ (*_sent_msg)[VSOMEIP_CLIENT_POS_MAX]);
+ its_session = VSOMEIP_BYTES_TO_WORD(
+ (*_sent_msg)[VSOMEIP_SESSION_POS_MIN],
+ (*_sent_msg)[VSOMEIP_SESSION_POS_MAX]);
+ }
+ VSOMEIP_WARNING << "uce::send_cbk received error: " << _error.message()
+ << " (" << std::dec << _error.value() << ") "
+ << get_remote_information() << " "
+ << " " << std::dec << queue_.size()
+ << " " << std::dec << queue_size_ << " ("
+ << std::hex << std::setw(4) << std::setfill('0') << its_client <<"): ["
+ << std::hex << std::setw(4) << std::setfill('0') << its_service << "."
+ << std::hex << std::setw(4) << std::setfill('0') << its_method << "."
+ << std::hex << std::setw(4) << std::setfill('0') << its_session << "]";
+ print_status();
+ }
+}
+
bool udp_client_endpoint_impl::tp_segmentation_enabled(service_t _service,
method_t _method) const {
return configuration_->tp_segment_messages_client_to_service(_service,
diff --git a/implementation/endpoints/src/udp_server_endpoint_impl.cpp b/implementation/endpoints/src/udp_server_endpoint_impl.cpp
index 7aadf3f..bd44b48 100644
--- a/implementation/endpoints/src/udp_server_endpoint_impl.cpp
+++ b/implementation/endpoints/src/udp_server_endpoint_impl.cpp
@@ -55,7 +55,7 @@ udp_server_endpoint_impl::udp_server_endpoint_impl(
std::string its_device(configuration_->get_device());
if (its_device != "") {
if (setsockopt(unicast_socket_.native_handle(),
- SOL_SOCKET, SO_BINDTODEVICE, its_device.c_str(), (int)its_device.size()) == -1) {
+ SOL_SOCKET, SO_BINDTODEVICE, its_device.c_str(), (socklen_t)its_device.size()) == -1) {
VSOMEIP_WARNING << "UDP Server: Could not bind to device \"" << its_device << "\"";
}
}
@@ -79,28 +79,46 @@ udp_server_endpoint_impl::udp_server_endpoint_impl(
unicast_socket_.set_option(option, ec);
boost::asio::detail::throw_error(ec, "broadcast option");
- const std::uint32_t its_udp_recv_buffer_size =
+ const int its_udp_recv_buffer_size =
configuration_->get_udp_receive_buffer_size();
unicast_socket_.set_option(boost::asio::socket_base::receive_buffer_size(
its_udp_recv_buffer_size), ec);
-
if (ec) {
- VSOMEIP_WARNING << "udp_server_endpoint_impl:: couldn't set "
+ VSOMEIP_WARNING << "udp_server_endpoint_impl: couldn't set "
<< "SO_RCVBUF: " << ec.message() << " to: " << std::dec
<< its_udp_recv_buffer_size << " local port: " << std::dec
<< local_port_;
- } else {
- boost::asio::socket_base::receive_buffer_size its_option;
- unicast_socket_.get_option(its_option, ec);
- if (ec) {
- VSOMEIP_WARNING << "udp_server_endpoint_impl: couldn't get "
- << "SO_RCVBUF: " << ec.message() << " local port:"
- << std::dec << local_port_;
- } else {
- VSOMEIP_INFO << "udp_server_endpoint_impl: SO_RCVBUF is: "
- << std::dec << its_option.value();
+ }
+
+ boost::asio::socket_base::receive_buffer_size its_option;
+ unicast_socket_.get_option(its_option, ec);
+#ifdef __linux__
+ // If regular setting of the buffer size did not work, try to force
+ // (requires CAP_NET_ADMIN to be successful)
+ if (its_option.value() < 0
+ || its_option.value() < its_udp_recv_buffer_size) {
+ ec.assign(setsockopt(unicast_socket_.native_handle(),
+ SOL_SOCKET, SO_RCVBUFFORCE,
+ &its_udp_recv_buffer_size, sizeof(its_udp_recv_buffer_size)),
+ boost::system::generic_category());
+ if (!ec) {
+ VSOMEIP_INFO << "udp_server_endpoint_impl: "
+ << "SO_RCVBUFFORCE successful.";
}
+ unicast_socket_.get_option(its_option, ec);
}
+#endif
+ if (ec) {
+ VSOMEIP_WARNING << "udp_server_endpoint_impl: couldn't get "
+ << "SO_RCVBUF: " << ec.message() << " local port:"
+ << std::dec << local_port_;
+ } else {
+ VSOMEIP_INFO << "udp_server_endpoint_impl: SO_RCVBUF is: "
+ << std::dec << its_option.value()
+ << " (" << its_udp_recv_buffer_size << ") local port:"
+ << std::dec << local_port_;
+ }
+
#ifdef _WIN32
const char* optval("0001");
@@ -345,29 +363,44 @@ void udp_server_endpoint_impl::join_unlocked(const std::string &_address) {
multicast_socket_->bind(*multicast_local_, ec);
boost::asio::detail::throw_error(ec, "bind multicast");
- const std::uint32_t its_udp_recv_buffer_size =
+ const int its_udp_recv_buffer_size =
configuration_->get_udp_receive_buffer_size();
-
multicast_socket_->set_option(boost::asio::socket_base::receive_buffer_size(
its_udp_recv_buffer_size), ec);
-
if (ec) {
- VSOMEIP_WARNING << "udp_server_endpoint_impl:: couldn't set "
+ VSOMEIP_WARNING << "udp_server_endpoint_impl<multicast>: couldn't set "
<< "SO_RCVBUF: " << ec.message() << " to: " << std::dec
<< its_udp_recv_buffer_size << " local port: " << std::dec
<< local_port_;
- } else {
- boost::asio::socket_base::receive_buffer_size its_option;
- multicast_socket_->get_option(its_option, ec);
+ }
- if (ec) {
- VSOMEIP_WARNING << "udp_server_endpoint_impl: couldn't get "
- << "SO_RCVBUF: " << ec.message() << " local port:"
- << std::dec << local_port_;
- } else {
- VSOMEIP_INFO << "udp_server_endpoint_impl: SO_RCVBUF (Multicast) is: "
- << std::dec << its_option.value();
+ boost::asio::socket_base::receive_buffer_size its_option;
+ multicast_socket_->get_option(its_option, ec);
+ #ifdef __linux__
+ // If regular setting of the buffer size did not work, try to force
+ // (requires CAP_NET_ADMIN to be successful)
+ if (its_option.value() < 0
+ || its_option.value() < its_udp_recv_buffer_size) {
+ ec.assign(setsockopt(multicast_socket_->native_handle(),
+ SOL_SOCKET, SO_RCVBUFFORCE,
+ &its_udp_recv_buffer_size, sizeof(its_udp_recv_buffer_size)),
+ boost::system::generic_category());
+ if (!ec) {
+ VSOMEIP_INFO << "udp_server_endpoint_impl<multicast>: "
+ << "SO_RCVBUFFORCE: successful.";
}
+ multicast_socket_->get_option(its_option, ec);
+ }
+ #endif
+ if (ec) {
+ VSOMEIP_WARNING << "udp_server_endpoint_impl<multicast>: couldn't get "
+ << "SO_RCVBUF: " << ec.message() << " local port:"
+ << std::dec << local_port_;
+ } else {
+ VSOMEIP_INFO << "udp_server_endpoint_impl<multicast>: SO_RCVBUF is: "
+ << std::dec << its_option.value()
+ << " (" << its_udp_recv_buffer_size << ") local port:"
+ << std::dec << local_port_;
}
#ifdef _WIN32
@@ -413,7 +446,8 @@ void udp_server_endpoint_impl::join_unlocked(const std::string &_address) {
joined_group_ = true;
} catch (const std::exception &e) {
- VSOMEIP_ERROR << "udp_server_endpoint_impl::join" << ":" << e.what();
+ VSOMEIP_ERROR << "udp_server_endpoint_impl::join" << ":" << e.what()
+ << " address: " << _address;
}
};
@@ -467,7 +501,8 @@ void udp_server_endpoint_impl::leave_unlocked(const std::string &_address) {
}
}
catch (const std::exception &e) {
- VSOMEIP_ERROR << __func__ << ":" << e.what();
+ VSOMEIP_ERROR << __func__ << ":" << e.what()
+ << " address: " << _address;
}
}
@@ -500,6 +535,10 @@ std::uint16_t udp_server_endpoint_impl::get_local_port() const {
return local_port_;
}
+void udp_server_endpoint_impl::set_local_port(std::uint16_t _port) {
+ (void)_port;
+}
+
void udp_server_endpoint_impl::on_unicast_received(
boost::system::error_code const &_error,
std::size_t _bytes,
@@ -624,9 +663,13 @@ void udp_server_endpoint_impl::on_message_received(
const session_t its_session = VSOMEIP_BYTES_TO_WORD(
_buffer[i + VSOMEIP_SESSION_POS_MIN],
_buffer[i + VSOMEIP_SESSION_POS_MAX]);
- clients_mutex_.lock();
- clients_[its_client][its_session] = _remote;
- clients_mutex_.unlock();
+ const method_t its_method = VSOMEIP_BYTES_TO_WORD(
+ _buffer[i + VSOMEIP_METHOD_POS_MIN],
+ _buffer[i + VSOMEIP_METHOD_POS_MAX]);
+
+ std::lock_guard<std::mutex> its_requests_guard(requests_mutex_);
+ requests_[its_client]
+ [std::make_tuple(its_service, its_method, its_session)] = _remote;
}
} else if (its_service != VSOMEIP_SD_SERVICE
&& utility::is_notification(_buffer[i + VSOMEIP_MESSAGE_TYPE_POS])
@@ -656,11 +699,19 @@ void udp_server_endpoint_impl::on_message_received(
res.second[VSOMEIP_CLIENT_POS_MIN],
res.second[VSOMEIP_CLIENT_POS_MAX]);
if (its_client != MAGIC_COOKIE_CLIENT) {
+ const service_t its_service = VSOMEIP_BYTES_TO_WORD(
+ res.second[VSOMEIP_SERVICE_POS_MIN],
+ res.second[VSOMEIP_SERVICE_POS_MAX]);
+ const method_t its_method = VSOMEIP_BYTES_TO_WORD(
+ res.second[VSOMEIP_METHOD_POS_MIN],
+ res.second[VSOMEIP_METHOD_POS_MAX]);
const session_t its_session = VSOMEIP_BYTES_TO_WORD(
res.second[VSOMEIP_SESSION_POS_MIN],
res.second[VSOMEIP_SESSION_POS_MAX]);
- std::lock_guard<std::mutex> its_client_lock(clients_mutex_);
- clients_[its_client][its_session] = _remote;
+
+ std::lock_guard<std::mutex> its_requests_guard(requests_mutex_);
+ requests_[its_client]
+ [std::make_tuple(its_service, its_method, its_session)] = _remote;
}
} else if (its_service != VSOMEIP_SD_SERVICE
&& utility::is_notification(res.second[VSOMEIP_MESSAGE_TYPE_POS])
diff --git a/implementation/endpoints/src/virtual_server_endpoint_impl.cpp b/implementation/endpoints/src/virtual_server_endpoint_impl.cpp
index c2c917f..5c8981c 100644
--- a/implementation/endpoints/src/virtual_server_endpoint_impl.cpp
+++ b/implementation/endpoints/src/virtual_server_endpoint_impl.cpp
@@ -112,6 +112,10 @@ std::uint16_t virtual_server_endpoint_impl::get_local_port() const {
return port_;
}
+void virtual_server_endpoint_impl::set_local_port(std::uint16_t _port) {
+ port_ = _port;
+}
+
std::uint16_t virtual_server_endpoint_impl::get_remote_port() const {
return ILLEGAL_PORT;
}
diff --git a/implementation/logger/src/message.cpp b/implementation/logger/src/message.cpp
index e4a902f..3363416 100644
--- a/implementation/logger/src/message.cpp
+++ b/implementation/logger/src/message.cpp
@@ -135,7 +135,8 @@ message::~message() {
<< std::endl;
}
}
- } else if (its_configuration->has_dlt_log()) {
+ }
+ if (its_configuration->has_dlt_log()) {
#ifdef USE_DLT
its_logger->log(level_, buffer_.data_.str().c_str());
#endif // USE_DLT
diff --git a/implementation/message/src/deserializer.cpp b/implementation/message/src/deserializer.cpp
index c7464cb..0e33faa 100644
--- a/implementation/message/src/deserializer.cpp
+++ b/implementation/message/src/deserializer.cpp
@@ -111,12 +111,12 @@ bool deserializer::deserialize(uint8_t *_data, std::size_t _length) {
return true;
}
-bool deserializer::deserialize(std::string& _target, std::size_t _length) {
+bool deserializer::deserialize(std::string &_target, std::size_t _length) {
if (_length > remaining_ || _length > _target.capacity()) {
return false;
}
- _target.assign(position_, position_ + _length);
- position_ += _length;
+ _target.assign(position_, position_ + long(_length));
+ position_ += long(_length);
remaining_ -= _length;
return true;
@@ -135,7 +135,7 @@ bool deserializer::deserialize(std::vector< uint8_t >& _value) {
}
bool deserializer::look_ahead(std::size_t _index, uint8_t &_value) const {
- if (_index >= data_.size())
+ if (_index > remaining_)
return false;
_value = *(position_ + static_cast<std::vector<byte_t>::difference_type>(_index));
@@ -144,7 +144,7 @@ bool deserializer::look_ahead(std::size_t _index, uint8_t &_value) const {
}
bool deserializer::look_ahead(std::size_t _index, uint16_t &_value) const {
- if (_index+1 >= data_.size())
+ if (_index+1 > remaining_)
return false;
std::vector< uint8_t >::iterator i = position_ +
@@ -155,7 +155,7 @@ bool deserializer::look_ahead(std::size_t _index, uint16_t &_value) const {
}
bool deserializer::look_ahead(std::size_t _index, uint32_t &_value) const {
- if (_index+3 >= data_.size())
+ if (_index+3 > remaining_)
return false;
std::vector< uint8_t >::const_iterator i = position_ + static_cast<std::vector<byte_t>::difference_type>(_index);
diff --git a/implementation/routing/include/eventgroupinfo.hpp b/implementation/routing/include/eventgroupinfo.hpp
index 32ce5f2..8ec1ac6 100644
--- a/implementation/routing/include/eventgroupinfo.hpp
+++ b/implementation/routing/include/eventgroupinfo.hpp
@@ -42,7 +42,7 @@ public:
VSOMEIP_EXPORT eventgroupinfo(
const service_t _service, const service_t _instance,
const eventgroup_t _eventgroup, const major_version_t _major,
- const ttl_t _ttl);
+ const ttl_t _ttl, const uint8_t _max_remote_subscribers);
VSOMEIP_EXPORT ~eventgroupinfo();
VSOMEIP_EXPORT service_t get_service() const;
@@ -86,6 +86,9 @@ public:
std::set<client_t> &_changed, remote_subscription_id_t &_id,
const bool _is_subscribe);
+ bool is_remote_subscription_limit_reached(
+ const std::shared_ptr<remote_subscription> &_subscription);
+
remote_subscription_id_t add_remote_subscription(
const std::shared_ptr<remote_subscription> &_subscription);
@@ -107,6 +110,10 @@ public:
VSOMEIP_EXPORT void send_initial_events(
const std::shared_ptr<endpoint_definition> &_reliable,
const std::shared_ptr<endpoint_definition> &_unreliable) const;
+
+ VSOMEIP_EXPORT uint8_t get_max_remote_subscribers() const;
+ VSOMEIP_EXPORT void set_max_remote_subscribers(uint8_t _max_remote_subscribers);
+
private:
void update_id();
uint32_t get_unreliable_target_count() const;
@@ -131,9 +138,12 @@ private:
std::shared_ptr<remote_subscription>
> subscriptions_;
remote_subscription_id_t id_;
+ std::map<boost::asio::ip::address, uint8_t> remote_subscribers_count_;
std::atomic<reliability_type_e> reliability_;
std::atomic<bool> reliability_auto_mode_;
+
+ uint8_t max_remote_subscribers_;
};
} // namespace vsomeip_v3
diff --git a/implementation/routing/include/remote_subscription.hpp b/implementation/routing/include/remote_subscription.hpp
index 685aad9..ff94d5b 100644
--- a/implementation/routing/include/remote_subscription.hpp
+++ b/implementation/routing/include/remote_subscription.hpp
@@ -31,6 +31,7 @@ public:
bool operator==(const remote_subscription &_other) const;
bool equals(const std::shared_ptr<remote_subscription> &_other) const;
+ bool address_equals(const std::shared_ptr<remote_subscription> &_other) const;
VSOMEIP_EXPORT void reset(const std::set<client_t> &_clients);
@@ -89,6 +90,8 @@ public:
VSOMEIP_EXPORT std::uint32_t get_answers() const;
VSOMEIP_EXPORT void set_answers(const std::uint32_t _answers);
+ VSOMEIP_EXPORT bool get_ip_address(boost::asio::ip::address &_address) const;
+
private:
std::atomic<remote_subscription_id_t> id_;
std::atomic<bool> is_initial_;
diff --git a/implementation/routing/include/routing_manager_base.hpp b/implementation/routing/include/routing_manager_base.hpp
index acd57fe..270f4c4 100644
--- a/implementation/routing/include/routing_manager_base.hpp
+++ b/implementation/routing/include/routing_manager_base.hpp
@@ -121,6 +121,8 @@ public:
virtual void set_routing_state(routing_state_e _routing_state) = 0;
+ virtual routing_state_e get_routing_state();
+
virtual void register_client_error_handler(client_t _client,
const std::shared_ptr<endpoint> &_endpoint) = 0;
@@ -131,6 +133,7 @@ public:
std::shared_ptr<serviceinfo> find_service(service_t _service, instance_t _instance) const;
client_t find_local_client(service_t _service, instance_t _instance) const;
+ client_t find_local_client_unlocked(service_t _service, instance_t _instance) const;
std::shared_ptr<event> find_event(service_t _service, instance_t _instance,
event_t _event) const;
@@ -208,6 +211,8 @@ protected:
instance_t _instance, method_t _method);
bool is_subscribe_to_any_event_allowed(credentials_t _credentials, client_t _client,
service_t _service, instance_t _instance, eventgroup_t _eventgroup);
+ void unsubscribe_all(service_t _service, instance_t _instance);
+
#ifdef VSOMEIP_ENABLE_COMPAT
void set_incoming_subscription_state(client_t _client, service_t _service, instance_t _instance,
eventgroup_t _eventgroup, event_t _event, subscription_state_e _state);
@@ -259,6 +264,9 @@ protected:
std::mutex event_registration_mutex_;
+ std::mutex routing_state_mutex_;
+ routing_state_e routing_state_;
+
#ifdef USE_DLT
std::shared_ptr<trace::connector_impl> tc_;
#endif
diff --git a/implementation/routing/include/routing_manager_impl.hpp b/implementation/routing/include/routing_manager_impl.hpp
index b5f0ea0..3fd6eed 100644
--- a/implementation/routing/include/routing_manager_impl.hpp
+++ b/implementation/routing/include/routing_manager_impl.hpp
@@ -140,7 +140,7 @@ public:
void on_subscribe_nack(client_t _client, service_t _service,
instance_t _instance, eventgroup_t _eventgroup, event_t _event,
- remote_subscription_id_t _id);
+ remote_subscription_id_t _id, bool _simulated);
// interface to stub
@@ -396,6 +396,12 @@ private:
const std::set<client_t> &_removed,
const remote_subscription_id_t _id);
+ void send_expired_subscription(client_t _offering_client,
+ const service_t _service, const instance_t _instance,
+ const eventgroup_t _eventgroup,
+ const std::set<client_t> &_removed,
+ const remote_subscription_id_t _id);
+
void cleanup_server_endpoint(service_t _service,
const std::shared_ptr<endpoint>& _endpoint);
@@ -414,6 +420,8 @@ private:
method_t _method, length_t _length);
void statistics_log_timer_cbk(boost::system::error_code const & _error);
+ void send_suspend() const;
+
private:
std::shared_ptr<routing_manager_stub> stub_;
std::shared_ptr<sd::service_discovery> discovery_;
@@ -476,7 +484,6 @@ private:
pending_remote_offer_id_t pending_remote_offer_id_;
std::map<pending_remote_offer_id_t, std::pair<service_t, instance_t>> pending_remote_offers_;
- std::mutex last_resume_mutex_;
std::chrono::steady_clock::time_point last_resume_;
std::mutex offer_serialization_mutex_;
@@ -493,6 +500,9 @@ private:
msg_statistic_t> message_statistics_;
std::tuple<service_t, instance_t, method_t> message_to_discard_;
uint32_t ignored_statistics_counter_;
+
+ // synchronize update_remote_subscription() and send_(un)subscription()
+ std::mutex update_remote_subscription_mutex_;
};
} // namespace vsomeip_v3
diff --git a/implementation/routing/include/routing_manager_proxy.hpp b/implementation/routing/include/routing_manager_proxy.hpp
index fd546a0..2b5335a 100644
--- a/implementation/routing/include/routing_manager_proxy.hpp
+++ b/implementation/routing/include/routing_manager_proxy.hpp
@@ -194,6 +194,8 @@ private:
void on_update_security_credentials(const byte_t *_data, uint32_t _size);
void on_client_assign_ack(const client_t &_client);
+ void on_suspend();
+
private:
enum class inner_state_type_e : std::uint8_t {
ST_REGISTERED = 0x0,
diff --git a/implementation/routing/include/routing_manager_stub.hpp b/implementation/routing/include/routing_manager_stub.hpp
index 4c2ff01..aa5796e 100644
--- a/implementation/routing/include/routing_manager_stub.hpp
+++ b/implementation/routing/include/routing_manager_stub.hpp
@@ -66,6 +66,11 @@ public:
instance_t _instance, eventgroup_t _eventgroup,
event_t _event, remote_subscription_id_t _id);
+ bool send_expired_subscription(const std::shared_ptr<endpoint>& _target,
+ client_t _client, service_t _service,
+ instance_t _instance, eventgroup_t _eventgroup,
+ event_t _event, remote_subscription_id_t _id);
+
void send_subscribe_nack(client_t _client, service_t _service,
instance_t _instance, eventgroup_t _eventgroup, event_t _event);
@@ -115,6 +120,8 @@ public:
const std::set<std::shared_ptr<policy> > &_policies);
void remove_requester_policies(uid_t _uid, gid_t _gid);
+ void send_suspend() const;
+
private:
void broadcast(const std::vector<byte_t> &_command) const;
@@ -123,6 +130,9 @@ private:
void distribute_credentials(client_t _hoster, service_t _service, instance_t _instance);
+ void inform_provider(client_t _hoster, service_t _service,
+ instance_t _instance, major_version_t _major, minor_version_t _minor,
+ routing_info_entry_e _entry);
void inform_requesters(client_t _hoster, service_t _service,
instance_t _instance, major_version_t _major,
minor_version_t _minor, routing_info_entry_e _entry,
diff --git a/implementation/routing/include/routing_manager_stub_host.hpp b/implementation/routing/include/routing_manager_stub_host.hpp
index 4707948..6ad0ab1 100644
--- a/implementation/routing/include/routing_manager_stub_host.hpp
+++ b/implementation/routing/include/routing_manager_stub_host.hpp
@@ -51,7 +51,7 @@ public:
virtual void on_subscribe_nack(client_t _client, service_t _service,
instance_t _instance, eventgroup_t _eventgroup, event_t _event,
- remote_subscription_id_t _subscription_id) = 0;
+ remote_subscription_id_t _subscription_id, bool _simulated) = 0;
virtual void on_subscribe_ack(client_t _client, service_t _service,
instance_t _instance, eventgroup_t _eventgroup, event_t _event,
diff --git a/implementation/routing/src/event.cpp b/implementation/routing/src/event.cpp
index bc0ba3e..b63022c 100644
--- a/implementation/routing/src/event.cpp
+++ b/implementation/routing/src/event.cpp
@@ -130,8 +130,10 @@ void event::set_payload(const std::shared_ptr<payload> &_payload, bool _force) {
}
}
} else {
- VSOMEIP_INFO << "Can't set payload for event " << std::hex
- << message_->get_method() << " as it isn't provided";
+ VSOMEIP_INFO << "Can't set payload for event "
+ << std::hex << std::setw(4) << std::setfill('0')
+ << get_service() << "." << get_instance() << "." << get_event()
+ << " as it isn't provided";
}
}
@@ -146,8 +148,10 @@ void event::set_payload(const std::shared_ptr<payload> &_payload, client_t _clie
}
}
} else {
- VSOMEIP_INFO << "Can't set payload for event " << std::hex
- << message_->get_method() << " as it isn't provided";
+ VSOMEIP_INFO << "Can't set payload for event "
+ << std::hex << std::setw(4) << std::setfill('0')
+ << get_service() << "." << get_instance() << "." << get_event()
+ << ". It isn't provided";
}
}
@@ -164,8 +168,10 @@ void event::set_payload(const std::shared_ptr<payload> &_payload,
}
}
} else {
- VSOMEIP_INFO << "Can't set payload for event " << std::hex
- << message_->get_method() << " as it isn't provided";
+ VSOMEIP_INFO << "Can't set payload for event "
+ << std::hex << std::setw(4) << std::setfill('0')
+ << get_service() << "." << get_instance() << "." << get_event()
+ << ". It isn't provided";
}
}
@@ -281,7 +287,9 @@ void event::notify() {
routing_->send(VSOMEIP_ROUTING_CLIENT, message_);
} else {
VSOMEIP_INFO << __func__
- << ": Notifying " << std::hex << get_event()
+ << ": Notifying "
+ << std::hex << std::setw(4) << std::setfill('0')
+ << get_service() << "." << get_instance() << "." << get_event()
<< " failed. Event payload not (yet) set!";
}
}
@@ -293,7 +301,9 @@ void event::notify_one(client_t _client,
notify_one_unlocked(_client, _target);
} else {
VSOMEIP_WARNING << __func__
- << ": Notifying " << std::hex << get_event()
+ << ": Notifying "
+ << std::hex << std::setw(4) << std::setfill('0')
+ << get_service() << "." << get_instance() << "." << get_event()
<< " failed. Target undefined";
}
}
@@ -306,13 +316,17 @@ void event::notify_one_unlocked(client_t _client,
routing_->send_to(_client, _target, message_);
} else {
VSOMEIP_INFO << __func__
- << ": Notifying " << std::hex << get_event()
+ << ": Notifying "
+ << std::hex << std::setw(4) << std::setfill('0')
+ << get_service() << "." << get_instance() << "." << get_event()
<< " failed. Event payload not (yet) set!";
pending_.insert(_target);
}
} else {
VSOMEIP_WARNING << __func__
- << ": Notifying " << std::hex << get_event()
+ << ": Notifying "
+ << std::hex << std::setw(4) << std::setfill('0')
+ << get_service() << "." << get_instance() << "." << get_event()
<< " failed. Target undefined";
}
}
@@ -329,7 +343,8 @@ void event::notify_one_unlocked(client_t _client) {
} else {
VSOMEIP_INFO << __func__
<< ": Notifying "
- << std::hex << message_->get_method()
+ << std::hex << std::setw(4) << std::setfill('0')
+ << get_service() << "." << get_instance() << "." << get_event()
<< " to client " << _client
<< " failed. Event payload not set!";
}
@@ -403,9 +418,12 @@ bool event::add_subscriber(eventgroup_t _eventgroup, client_t _client, bool _for
ret = eventgroups_[_eventgroup].insert(_client).second;
} else {
VSOMEIP_WARNING << __func__ << ": Didnt' insert client "
- << std::hex << std::setw(4) << std::setfill('0') << _client
- << " to eventgroup 0x"
- << std::hex << std::setw(4) << std::setfill('0') << _eventgroup;
+ << std::hex << std::setw(4) << std::setfill('0')
+ << _client
+ << " to eventgroup "
+ << std::hex << std::setw(4) << std::setfill('0')
+ << get_service() << "." << get_instance() << "."
+ << _eventgroup;
}
return ret;
}
diff --git a/implementation/routing/src/eventgroupinfo.cpp b/implementation/routing/src/eventgroupinfo.cpp
index d09ed1b..50bbdb6 100644
--- a/implementation/routing/src/eventgroupinfo.cpp
+++ b/implementation/routing/src/eventgroupinfo.cpp
@@ -26,13 +26,14 @@ eventgroupinfo::eventgroupinfo()
threshold_(0),
id_(PENDING_SUBSCRIPTION_ID),
reliability_(reliability_type_e::RT_UNKNOWN),
- reliability_auto_mode_(false) {
+ reliability_auto_mode_(false),
+ max_remote_subscribers_(VSOMEIP_DEFAULT_MAX_REMOTE_SUBSCRIBERS) {
}
eventgroupinfo::eventgroupinfo(
const service_t _service, const instance_t _instance,
const eventgroup_t _eventgroup, const major_version_t _major,
- const ttl_t _ttl)
+ const ttl_t _ttl, const uint8_t _max_remote_subscribers)
: service_(_service),
instance_(_instance),
eventgroup_(_eventgroup),
@@ -42,7 +43,8 @@ eventgroupinfo::eventgroupinfo(
threshold_(0),
id_(PENDING_SUBSCRIPTION_ID),
reliability_(reliability_type_e::RT_UNKNOWN),
- reliability_auto_mode_(false) {
+ reliability_auto_mode_(false),
+ max_remote_subscribers_(_max_remote_subscribers) {
}
eventgroupinfo::~eventgroupinfo() {
@@ -213,65 +215,123 @@ eventgroupinfo::update_remote_subscription(
const std::chrono::steady_clock::time_point &_expiration,
std::set<client_t> &_changed, remote_subscription_id_t &_id,
const bool _is_subscribe) {
- std::lock_guard<std::mutex> its_lock(subscriptions_mutex_);
- for (const auto& its_item : subscriptions_) {
- if (its_item.second->equals(_subscription)) {
- // update existing subscription
- _changed = its_item.second->update(
- _subscription->get_clients(), _expiration, _is_subscribe);
- _id = its_item.second->get_id();
-
- // Copy acknowledgment states from existing subscription
- for (const auto& its_client : _subscription->get_clients()) {
- _subscription->set_client_state(its_client,
- its_item.second->get_client_state(its_client));
- }
+ bool its_result(false);
+ std::shared_ptr<endpoint_definition> its_subscriber;
+ std::set<std::shared_ptr<event> > its_events;
- if (_is_subscribe) {
- if (!_changed.empty()) {
- // New clients:
- // Let this be a child subscription
- _subscription->set_parent(its_item.second);
- update_id();
- _subscription->set_id(id_);
- subscriptions_[id_] = _subscription;
- } else {
- if (!_subscription->is_pending()) {
- if (!_subscription->force_initial_events()) {
- _subscription->set_initial(false);
- }
+ {
+ std::lock_guard<std::mutex> its_lock(subscriptions_mutex_);
+
+ for (const auto& its_item : subscriptions_) {
+ if (its_item.second->equals(_subscription)) {
+ // update existing subscription
+ _changed = its_item.second->update(
+ _subscription->get_clients(), _expiration, _is_subscribe);
+ _id = its_item.second->get_id();
+
+ // Copy acknowledgment states from existing subscription
+ for (const auto& its_client : _subscription->get_clients()) {
+ const auto its_state = its_item.second->get_client_state(its_client);
+ if (_is_subscribe &&
+ its_state == remote_subscription_state_e::SUBSCRIPTION_UNKNOWN) {
+ _subscription->set_client_state(its_client,
+ remote_subscription_state_e::SUBSCRIPTION_PENDING);
+ _changed.insert(its_client);
} else {
- its_item.second->set_answers(
- its_item.second->get_answers() + 1);
- _subscription->set_parent(its_item.second);
- _subscription->set_answers(0);
+ _subscription->set_client_state(its_client, its_state);
}
}
- } else {
- if (its_item.second->is_pending()) {
- for (const auto &its_event : events_)
- its_event->remove_pending(
- its_item.second->get_subscriber());
+
+ if (_is_subscribe) {
+ if (!_changed.empty()) {
+ // New clients:
+ // Let this be a child subscription
+ _subscription->set_parent(its_item.second);
+ update_id();
+ _subscription->set_id(id_);
+ subscriptions_[id_] = _subscription;
+ } else {
+ if (!_subscription->is_pending()) {
+ if (!_subscription->force_initial_events()) {
+ _subscription->set_initial(false);
+ }
+ } else {
+ its_item.second->set_answers(
+ its_item.second->get_answers() + 1);
+ _subscription->set_parent(its_item.second);
+ _subscription->set_answers(0);
+ }
+ }
+ } else {
+ if (its_item.second->is_pending()) {
+ its_subscriber = its_item.second->get_subscriber();
+ }
}
+
+ its_result = true;
+ break;
}
+ }
+ }
- return true;
+ if (its_subscriber) {
+ {
+ // Build set of events first to avoid having to
+ // hold the "events_mutex_" in parallel to the internal event mutexes.
+ std::lock_guard<std::mutex> its_lock(events_mutex_);
+ for (const auto &its_event : events_)
+ its_events.insert(its_event);
}
+ for (const auto &its_event : its_events)
+ its_event->remove_pending(its_subscriber);
}
- return false;
+ return (its_result);
+}
+
+bool
+eventgroupinfo::is_remote_subscription_limit_reached(
+ const std::shared_ptr<remote_subscription> &_subscription) {
+ bool limit_reached(false);
+
+ if (subscriptions_.size() <= max_remote_subscribers_) {
+ return false;
+ }
+
+ boost::asio::ip::address its_address;
+ if (_subscription->get_ip_address(its_address)) {
+ auto find_address = remote_subscribers_count_.find(its_address);
+ if (find_address != remote_subscribers_count_.end()) {
+ if (find_address->second > max_remote_subscribers_) {
+ VSOMEIP_WARNING << ": remote subscriber limit [" << std::dec
+ << (uint32_t)max_remote_subscribers_ << "] to ["
+ << std::hex << std::setw(4) << std::setfill('0') << service_ << "."
+ << std::hex << std::setw(4) << std::setfill('0') << instance_ << "."
+ << std::hex << std::setw(4) << std::setfill('0') << eventgroup_ << "]"
+ << " reached for remote address: " << its_address.to_string()
+ << " rejecting subscription!";
+ return true;
+ }
+ }
+ }
+ return limit_reached;
}
remote_subscription_id_t
eventgroupinfo::add_remote_subscription(
const std::shared_ptr<remote_subscription> &_subscription) {
std::lock_guard<std::mutex> its_lock(subscriptions_mutex_);
+
update_id();
_subscription->set_id(id_);
subscriptions_[id_] = _subscription;
+ boost::asio::ip::address its_address;
+ if (_subscription->get_ip_address(its_address)) {
+ remote_subscribers_count_[its_address]++;
+ }
return id_;
}
@@ -291,6 +351,20 @@ void
eventgroupinfo::remove_remote_subscription(
const remote_subscription_id_t _id) {
std::lock_guard<std::mutex> its_lock(subscriptions_mutex_);
+
+ auto find_subscription = subscriptions_.find(_id);
+ if (find_subscription != subscriptions_.end()) {
+ boost::asio::ip::address its_address;
+ if (find_subscription->second->get_ip_address(its_address)) {
+ auto find_address = remote_subscribers_count_.find(its_address);
+ if (find_address != remote_subscribers_count_.end()) {
+ if(find_address->second != 0) {
+ find_address->second--;
+ }
+ }
+ }
+ }
+
subscriptions_.erase(_id);
}
@@ -298,6 +372,7 @@ void
eventgroupinfo::clear_remote_subscriptions() {
std::lock_guard<std::mutex> its_lock(subscriptions_mutex_);
subscriptions_.clear();
+ remote_subscribers_count_.clear();
}
std::set<std::shared_ptr<endpoint_definition> >
@@ -390,11 +465,19 @@ eventgroupinfo::send_initial_events(
}
// Send events
- for (const auto& its_event : its_reliable_events)
+ for (const auto &its_event : its_reliable_events)
its_event->notify_one(VSOMEIP_ROUTING_CLIENT, _reliable);
- for (const auto& its_event : its_unreliable_events)
+ for (const auto &its_event : its_unreliable_events)
its_event->notify_one(VSOMEIP_ROUTING_CLIENT, _unreliable);
}
+uint8_t eventgroupinfo::get_max_remote_subscribers() const {
+ return max_remote_subscribers_;
+}
+
+void eventgroupinfo::set_max_remote_subscribers(uint8_t _max_remote_subscribers) {
+ max_remote_subscribers_ = _max_remote_subscribers;
+}
+
} // namespace vsomeip_v3
diff --git a/implementation/routing/src/remote_subscription.cpp b/implementation/routing/src/remote_subscription.cpp
index daec6f9..cb04d93 100644
--- a/implementation/routing/src/remote_subscription.cpp
+++ b/implementation/routing/src/remote_subscription.cpp
@@ -46,6 +46,21 @@ remote_subscription::equals(
return operator ==(*_other);
}
+bool
+remote_subscription::address_equals(
+ const std::shared_ptr<remote_subscription> &_other) const {
+ bool relibale_address_equals(false);
+ bool unrelibale_address_equals(false);
+
+ if (reliable_ && (*_other).reliable_)
+ relibale_address_equals = (reliable_->get_address()
+ == (*_other).reliable_->get_address());
+ if (unreliable_ && (*_other).unreliable_)
+ unrelibale_address_equals = (unreliable_->get_address()
+ == (*_other).unreliable_->get_address());
+ return (relibale_address_equals || unrelibale_address_equals);
+}
+
void
remote_subscription::reset(const std::set<client_t> &_clients) {
auto its_client_state = std::make_pair(
@@ -135,7 +150,7 @@ std::set<client_t>
remote_subscription::get_clients() const {
std::lock_guard<std::mutex> its_lock(mutex_);
std::set<client_t> its_clients;
- for (const auto& its_item : clients_)
+ for (const auto &its_item : clients_)
its_clients.insert(its_item.first);
return its_clients;
}
@@ -313,4 +328,17 @@ remote_subscription::set_answers(const std::uint32_t _answers) {
answers_ = _answers;
}
+bool
+remote_subscription::get_ip_address(boost::asio::ip::address &_address) const {
+ if (reliable_) {
+ _address = reliable_->get_address();
+ return true;
+ }
+ else if (unreliable_) {
+ _address = unreliable_->get_address();
+ return true;
+ }
+ return false;
+}
+
} // namespace vsomeip_v3
diff --git a/implementation/routing/src/routing_manager_base.cpp b/implementation/routing/src/routing_manager_base.cpp
index 960ae60..c787a9e 100644
--- a/implementation/routing/src/routing_manager_base.cpp
+++ b/implementation/routing/src/routing_manager_base.cpp
@@ -24,7 +24,8 @@ routing_manager_base::routing_manager_base(routing_manager_host *_host) :
host_(_host),
io_(host_->get_io()),
client_(host_->get_client()),
- configuration_(host_->get_configuration())
+ configuration_(host_->get_configuration()),
+ routing_state_(routing_state_e::RS_UNKNOWN)
#ifdef USE_DLT
, tc_(trace::connector_impl::get())
#endif
@@ -458,6 +459,8 @@ void routing_manager_base::register_event(client_t _client,
its_eventgroupinfo->set_service(_service);
its_eventgroupinfo->set_instance(_instance);
its_eventgroupinfo->set_eventgroup(eg);
+ its_eventgroupinfo->set_max_remote_subscribers(
+ configuration_->get_max_remote_subscribers());
std::lock_guard<std::mutex> its_lock(eventgroups_mutex_);
eventgroups_[_service][_instance][eg] = its_eventgroupinfo;
}
@@ -549,22 +552,24 @@ bool routing_manager_base::is_response_allowed(client_t _sender, service_t _serv
return true;
}
- if (_sender == find_local_client(_service, _instance)) {
- // sender is still offering the service
- return true;
- }
+ {
+ std::lock_guard<std::mutex> its_lock(local_services_mutex_);
+ if (_sender == find_local_client_unlocked(_service, _instance)) {
+ // sender is still offering the service
+ return true;
+ }
- std::lock_guard<std::mutex> its_lock(local_services_mutex_);
- auto found_service = local_services_history_.find(_service);
- if (found_service != local_services_history_.end()) {
- auto found_instance = found_service->second.find(_instance);
- if (found_instance != found_service->second.end()) {
- auto found_client = found_instance->second.find(_sender);
- if (found_client != found_instance->second.end()) {
- // sender was offering the service and is still connected
- return true;
+ auto found_service = local_services_history_.find(_service);
+ if (found_service != local_services_history_.end()) {
+ auto found_instance = found_service->second.find(_instance);
+ if (found_instance != found_service->second.end()) {
+ auto found_client = found_instance->second.find(_sender);
+ if (found_client != found_instance->second.end()) {
+ // sender was offering the service and is still connected
+ return true;
+ }
}
- }
+ }
}
// service is now offered by another client
@@ -648,6 +653,21 @@ void routing_manager_base::unsubscribe(client_t _client, uid_t _uid, gid_t _gid,
}
}
+void
+routing_manager_base::unsubscribe_all(
+ service_t _service, instance_t _instance) {
+
+ std::lock_guard<std::mutex> its_guard(events_mutex_);
+ auto find_service = events_.find(_service);
+ if (find_service != events_.end()) {
+ auto find_instance = find_service->second.find(_instance);
+ if (find_instance != find_service->second.end()) {
+ for (auto &e : find_instance->second)
+ e.second->clear_subscribers();
+ }
+ }
+}
+
void routing_manager_base::notify(service_t _service, instance_t _instance,
event_t _event, std::shared_ptr<payload> _payload,
bool _force) {
@@ -982,6 +1002,11 @@ std::set<client_t> routing_manager_base::find_local_clients(service_t _service,
client_t routing_manager_base::find_local_client(service_t _service,
instance_t _instance) const {
std::lock_guard<std::mutex> its_lock(local_services_mutex_);
+ return find_local_client_unlocked(_service, _instance);
+}
+
+client_t routing_manager_base::find_local_client_unlocked(service_t _service,
+ instance_t _instance) const {
client_t its_client(VSOMEIP_ROUTING_CLIENT);
auto its_service = local_services_.find(_service);
if (its_service != local_services_.end()) {
@@ -1396,6 +1421,11 @@ routing_manager_base::get_subscriptions(const client_t _client) {
return result;
}
+routing_state_e
+routing_manager_base::get_routing_state() {
+ return routing_state_;
+}
+
#ifdef VSOMEIP_ENABLE_COMPAT
void routing_manager_base::set_incoming_subscription_state(client_t _client, service_t _service, instance_t _instance,
eventgroup_t _eventgroup, event_t _event, subscription_state_e _state) {
diff --git a/implementation/routing/src/routing_manager_impl.cpp b/implementation/routing/src/routing_manager_impl.cpp
index 34150fe..07c0740 100644
--- a/implementation/routing/src/routing_manager_impl.cpp
+++ b/implementation/routing/src/routing_manager_impl.cpp
@@ -532,8 +532,7 @@ void routing_manager_impl::request_service(client_t _client, service_t _service,
_minor, DEFAULT_TTL);
}
its_info->add_client(_client);
- ep_mgr_impl_->find_or_create_remote_client(
- _service, _instance, true);
+ ep_mgr_impl_->find_or_create_remote_client(_service, _instance);
}
}
}
@@ -633,6 +632,7 @@ void routing_manager_impl::subscribe(client_t _client, uid_t _uid, gid_t _gid,
std::unique_lock<std::mutex> its_critical(remote_subscription_state_mutex_);
bool inserted = insert_subscription(_service, _instance, _eventgroup,
_event, _client, &its_already_subscribed_events);
+ const bool subscriber_is_rm_host = (get_client() == _client);
if (inserted) {
if (0 == its_local_client) {
handle_subscription_state(_client, _service, _instance, _eventgroup, _event);
@@ -642,7 +642,11 @@ void routing_manager_impl::subscribe(client_t _client, uid_t _uid, gid_t _gid,
_eventgroup, _event, its_already_subscribed_events);
auto its_info = find_eventgroup(_service, _instance, _eventgroup);
- if (its_info) {
+ // if the subscriber is the rm_host itself: check if service
+ // is available before subscribing via SD otherwise we sent
+ // a StopSubscribe/Subscribe once the first offer is received
+ if (its_info &&
+ (!subscriber_is_rm_host || find_service(_service, _instance))) {
discovery_->subscribe(_service, _instance, _eventgroup,
_major, configured_ttl,
its_info->is_selective() ? _client : VSOMEIP_ROUTING_CLIENT,
@@ -657,7 +661,7 @@ void routing_manager_impl::subscribe(client_t _client, uid_t _uid, gid_t _gid,
}
}
}
- if (get_client() == _client) {
+ if (subscriber_is_rm_host) {
std::lock_guard<std::mutex> ist_lock(pending_subscription_mutex_);
subscription_data_t subscription = {
_service, _instance, _eventgroup, _major, _event, _uid, _gid
@@ -701,6 +705,10 @@ void routing_manager_impl::unsubscribe(client_t _client, uid_t _uid, gid_t _gid,
host_->on_subscription(_service, _instance, _eventgroup, _client, _uid, _gid, false,
[](const bool _subscription_accepted){ (void)_subscription_accepted; });
if (0 == find_local_client(_service, _instance)) {
+ if (get_client() == _client) {
+ std::lock_guard<std::mutex> ist_lock(pending_subscription_mutex_);
+ remove_pending_subscription(_service, _instance, _eventgroup, _event);
+ }
if (last_subscriber_removed) {
unset_all_eventpayloads(_service, _instance, _eventgroup);
{
@@ -784,7 +792,8 @@ bool routing_manager_impl::send(client_t _client, const byte_t *_data,
if (its_target) {
#ifdef USE_DLT
if ((is_request && its_client == get_client()) ||
- (is_response && find_local_client(its_service, _instance) == get_client())) {
+ (is_response && find_local_client(its_service, _instance) == get_client()) ||
+ (is_notification && find_local_client(its_service, _instance) == VSOMEIP_ROUTING_CLIENT)) {
const uint16_t its_data_size
= uint16_t(_size > USHRT_MAX ? USHRT_MAX : _size);
@@ -1201,6 +1210,37 @@ void routing_manager_impl::notify_one(service_t _service, instance_t _instance,
void routing_manager_impl::on_availability(service_t _service, instance_t _instance,
bool _is_available, major_version_t _major, minor_version_t _minor) {
+
+ // insert subscriptions of routing manager into service discovery
+ // to send SubscribeEventgroup after StopOffer / Offer was received
+ if (_is_available) {
+ if (discovery_) {
+ const client_t its_local_client = find_local_client(_service, _instance);
+ // remote service
+ if (VSOMEIP_ROUTING_CLIENT == its_local_client) {
+ static const ttl_t configured_ttl(configuration_->get_sd_ttl());
+
+ std::lock_guard<std::mutex> ist_lock(pending_subscription_mutex_);
+ for (auto &ps : pending_subscriptions_) {
+ if (ps.service_ == _service
+ && ps.instance_ == _instance
+ && ps.major_ == _major) {
+ auto its_info = find_eventgroup(_service, _instance, ps.eventgroup_);
+ if (its_info) {
+ discovery_->subscribe(
+ _service,
+ _instance,
+ ps.eventgroup_,
+ _major,
+ configured_ttl,
+ its_info->is_selective() ? get_client() : VSOMEIP_ROUTING_CLIENT,
+ its_info);
+ }
+ }
+ }
+ }
+ }
+ }
host_->on_availability(_service, _instance, _is_available, _major, _minor);
}
@@ -1719,16 +1759,23 @@ void routing_manager_impl::on_stop_offer_service(client_t _client, service_t _se
erase_offer_command(_service, _instance);
}
- std::lock_guard<std::mutex> its_eventgroups_lock(eventgroups_mutex_);
- auto find_service = eventgroups_.find(_service);
- if (find_service != eventgroups_.end()) {
- auto find_instance = find_service->second.find(_instance);
- if (find_instance != find_service->second.end()) {
- for (auto e : find_instance->second) {
- e.second->clear_remote_subscriptions();
+ std::set<std::shared_ptr<eventgroupinfo> > its_eventgroup_info_set;
+ {
+ std::lock_guard<std::mutex> its_eventgroups_lock(eventgroups_mutex_);
+ auto find_service = eventgroups_.find(_service);
+ if (find_service != eventgroups_.end()) {
+ auto find_instance = find_service->second.find(_instance);
+ if (find_instance != find_service->second.end()) {
+ for (auto e : find_instance->second) {
+ its_eventgroup_info_set.insert(e.second);
+ }
}
}
}
+
+ for (auto e : its_eventgroup_info_set) {
+ e->clear_remote_subscriptions();
+ }
} else {
erase_offer_command(_service, _instance);
}
@@ -1902,6 +1949,11 @@ bool routing_manager_impl::deliver_notification(
}
}
if (!cache_event) {
+ VSOMEIP_WARNING << __func__ << ": dropping ["
+ << std::hex << std::setw(4) << std::setfill('0') << _service << "."
+ << std::hex << std::setw(4) << std::setfill('0') << _instance << "."
+ << std::hex << std::setw(4) << std::setfill('0') << its_event_id
+ << "]. No subscription to corresponding eventgroup.";
return true; // as there is nothing to do
}
}
@@ -1996,13 +2048,10 @@ std::shared_ptr<endpoint> routing_manager_impl::create_service_discovery_endpoin
its_service_endpoint->add_default_target(VSOMEIP_SD_SERVICE,
_address, _port);
if (!_reliable) {
-#if defined(_WIN32) || defined(ANDROID)
- dynamic_cast<udp_server_endpoint_impl*>(
- its_service_endpoint.get())->join(_address);
-#else
- reinterpret_cast<udp_server_endpoint_impl*>(
- its_service_endpoint.get())->join(_address);
-#endif
+ auto its_udp_server_endpoint_impl = std::dynamic_pointer_cast<
+ udp_server_endpoint_impl>(its_service_endpoint);
+ if (its_udp_server_endpoint_impl)
+ its_udp_server_endpoint_impl->join(_address);
}
} else {
VSOMEIP_ERROR<< "Service Discovery endpoint could not be created. "
@@ -2150,6 +2199,7 @@ bool routing_manager_impl::is_field(service_t _service, instance_t _instance,
return false;
}
+//only called from the SD
void routing_manager_impl::add_routing_info(
service_t _service, instance_t _instance,
major_version_t _major, minor_version_t _minor, ttl_t _ttl,
@@ -2158,6 +2208,12 @@ void routing_manager_impl::add_routing_info(
const boost::asio::ip::address &_unreliable_address,
uint16_t _unreliable_port) {
+ std::lock_guard<std::mutex> its_lock(routing_state_mutex_);
+ if (routing_state_ == routing_state_e::RS_SUSPENDED) {
+ VSOMEIP_INFO << "rmi::" << __func__ << " We are suspened --> do nothing.";
+ return;
+ }
+
// Create/Update service info
std::shared_ptr<serviceinfo> its_info(find_service(_service, _instance));
if (!its_info) {
@@ -2259,6 +2315,7 @@ void routing_manager_impl::add_routing_info(
}
} else if (_reliable_port != ILLEGAL_PORT && is_reliable_known) {
std::lock_guard<std::mutex> its_lock(requested_services_mutex_);
+ bool connected(false);
for(const auto &client_id : requested_services_) {
auto found_service = client_id.second.find(_service);
if (found_service != client_id.second.end()) {
@@ -2272,21 +2329,34 @@ void routing_manager_impl::add_routing_info(
|| _minor == DEFAULT_MINOR
|| major_minor_pair.second == ANY_MINOR)) {
std::shared_ptr<endpoint> ep = its_info->get_endpoint(true);
- if (ep && ep->is_established() &&
+ if (ep) {
+ if (ep->is_established() &&
!stub_->contained_in_routing_info(
VSOMEIP_ROUTING_CLIENT, _service, _instance,
its_info->get_major(),
its_info->get_minor())) {
- on_availability(_service, _instance,
- true, its_info->get_major(), its_info->get_minor());
- stub_->on_offer_service(VSOMEIP_ROUTING_CLIENT,
- _service, _instance,
- its_info->get_major(),
- its_info->get_minor());
- if (discovery_) {
- discovery_->on_endpoint_connected(
- _service, _instance, ep);
+ on_availability(_service, _instance,
+ true, its_info->get_major(), its_info->get_minor());
+ stub_->on_offer_service(VSOMEIP_ROUTING_CLIENT,
+ _service, _instance,
+ its_info->get_major(),
+ its_info->get_minor());
+ if (discovery_) {
+ discovery_->on_endpoint_connected(
+ _service, _instance, ep);
+ }
+ }
+ } else {
+ // no endpoint yet, but requested -> create one
+
+ // SWS_SD_00376 establish TCP connection to service
+ // service is marked as available later in on_connect()
+ if (!connected) {
+ ep_mgr_impl_->find_or_create_remote_client(
+ _service, _instance, true);
+ connected = true;
}
+ its_info->add_client(client_id.first);
}
break;
}
@@ -2358,7 +2428,8 @@ void routing_manager_impl::add_routing_info(
&& (major_minor_pair.second <= _minor
|| _minor == DEFAULT_MINOR
|| major_minor_pair.second == ANY_MINOR)) {
- if (!stub_->contained_in_routing_info(
+ if (_reliable_port == ILLEGAL_PORT && !is_reliable_known &&
+ !stub_->contained_in_routing_info(
VSOMEIP_ROUTING_CLIENT, _service, _instance,
its_info->get_major(),
its_info->get_minor())) {
@@ -2411,18 +2482,15 @@ void routing_manager_impl::del_routing_info(service_t _service, instance_t _inst
// do no longer exist and the last received payload is no
// longer valid.
for (auto &its_event : its_eventgroup.second->get_events()) {
- const auto its_subscribers = its_event->get_subscribers();
- for (const auto& its_subscriber : its_subscribers) {
+ const auto& its_subscribers = its_event->get_subscribers();
+ for (const auto its_subscriber : its_subscribers) {
if (its_subscriber != get_client()) {
its_event->remove_subscriber(
its_eventgroup.first, its_subscriber);
}
}
its_events.push_back(its_event);
- remove_pending_subscription(_service, _instance,
- its_eventgroup.first, its_event->get_event());
}
-
}
}
}
@@ -2436,14 +2504,14 @@ void routing_manager_impl::del_routing_info(service_t _service, instance_t _inst
std::set<std::tuple<
service_t, instance_t, eventgroup_t, client_t> > its_invalid;
- for (const auto& its_state : remote_subscription_state_) {
+ for (const auto &its_state : remote_subscription_state_) {
if (std::get<0>(its_state.first) == _service
&& std::get<1>(its_state.first) == _instance) {
its_invalid.insert(its_state.first);
}
}
- for (const auto& its_key : its_invalid)
+ for (const auto &its_key : its_invalid)
remote_subscription_state_.erase(its_key);
}
@@ -2599,8 +2667,15 @@ routing_manager_impl::expire_subscriptions(
const bool expire_all = (_range.first == ANY_PORT
&& _range.second == ANY_PORT);
- std::lock_guard<std::mutex> its_lock(eventgroups_mutex_);
- for (const auto &its_service : eventgroups_) {
+ std::map<service_t,
+ std::map<instance_t,
+ std::map<eventgroup_t,
+ std::shared_ptr<eventgroupinfo> > > >its_eventgroups;
+ {
+ std::lock_guard<std::mutex> its_lock(eventgroups_mutex_);
+ its_eventgroups = eventgroups_;
+ }
+ for (const auto &its_service : its_eventgroups) {
for (const auto &its_instance : its_service.second) {
for (const auto &its_eventgroup : its_instance.second) {
const auto its_info = its_eventgroup.second;
@@ -2743,10 +2818,12 @@ void routing_manager_impl::on_remote_subscribe(
// not exist or is still (partly) pending.
remote_subscription_id_t its_id;
std::set<client_t> its_added;
+ update_remote_subscription_mutex_.lock();
auto its_result = its_eventgroupinfo->update_remote_subscription(
_subscription, its_expiration, its_added, its_id, true);
if (its_result) {
if (!_subscription->is_pending()) { // resubscription without change
+ update_remote_subscription_mutex_.unlock();
_callback(_subscription);
} else if (!its_added.empty()) { // new clients for a selective subscription
const client_t its_offering_client
@@ -2754,6 +2831,7 @@ void routing_manager_impl::on_remote_subscribe(
send_subscription(its_offering_client,
its_service, its_instance, its_eventgroup, its_major,
its_added, _subscription->get_id());
+ update_remote_subscription_mutex_.unlock();
} else { // identical subscription is not yet processed
std::stringstream its_warning;
its_warning << __func__ << " a remote subscription is already pending ["
@@ -2774,9 +2852,21 @@ void routing_manager_impl::on_remote_subscribe(
if (its_reliable && its_unreliable)
its_warning << "]";
VSOMEIP_WARNING << its_warning.str();
+
+ update_remote_subscription_mutex_.unlock();
_callback(_subscription);
}
} else { // new subscription
+ if (its_eventgroupinfo->is_remote_subscription_limit_reached(
+ _subscription)) {
+ _subscription->set_all_client_states(
+ remote_subscription_state_e::SUBSCRIPTION_NACKED);
+
+ update_remote_subscription_mutex_.unlock();
+ _callback(_subscription);
+ return;
+ }
+
auto its_id
= its_eventgroupinfo->add_remote_subscription(_subscription);
@@ -2785,6 +2875,7 @@ void routing_manager_impl::on_remote_subscribe(
send_subscription(its_offering_client,
its_service, its_instance, its_eventgroup, its_major,
_subscription->get_clients(), its_id);
+ update_remote_subscription_mutex_.unlock();
}
}
@@ -2820,6 +2911,7 @@ void routing_manager_impl::on_remote_unsubscribe(
remote_subscription_id_t its_id(0);
std::set<client_t> its_removed;
+ update_remote_subscription_mutex_.lock();
auto its_result = its_info->update_remote_subscription(
_subscription, std::chrono::steady_clock::now(),
its_removed, its_id, false);
@@ -2831,6 +2923,8 @@ void routing_manager_impl::on_remote_unsubscribe(
its_service, its_instance, its_eventgroup, its_major,
its_removed, its_id);
}
+
+ update_remote_subscription_mutex_.unlock();
}
void routing_manager_impl::on_subscribe_ack_with_multicast(
@@ -2931,13 +3025,20 @@ std::shared_ptr<endpoint> routing_manager_impl::find_or_create_remote_client(
void routing_manager_impl::on_subscribe_nack(client_t _client,
service_t _service, instance_t _instance, eventgroup_t _eventgroup,
- event_t _event, remote_subscription_id_t _id) {
+ event_t _event, remote_subscription_id_t _id, bool _simulated) {
(void)_event; // TODO: Remove completely?
auto its_eventgroup = find_eventgroup(_service, _instance, _eventgroup);
if (its_eventgroup) {
auto its_subscription = its_eventgroup->get_remote_subscription(_id);
if (its_subscription) {
+ if (_simulated) {
+ // method was called because a subscription for unoffered
+ // service was received. Therefore, remove the remote_subscription
+ // from the eventgroupinfo to ensure subsequent similar
+ // subscriptions are handled like a new/unknown subscription
+ its_eventgroup->remove_remote_subscription(_id);
+ }
its_subscription->set_client_state(_client,
remote_subscription_state_e::SUBSCRIPTION_NACKED);
@@ -3110,6 +3211,10 @@ void routing_manager_impl::clear_remote_subscriber(
std::chrono::steady_clock::time_point
routing_manager_impl::expire_subscriptions(bool _force) {
+ std::map<service_t,
+ std::map<instance_t,
+ std::map<eventgroup_t,
+ std::shared_ptr<eventgroupinfo> > > >its_eventgroups;
std::map<std::shared_ptr<remote_subscription>,
std::set<client_t> > its_expired_subscriptions;
@@ -3119,24 +3224,25 @@ routing_manager_impl::expire_subscriptions(bool _force) {
= std::chrono::steady_clock::now() + std::chrono::hours(24);
{
std::lock_guard<std::mutex> its_lock(eventgroups_mutex_);
-
- for (auto &its_service : eventgroups_) {
- for (auto &its_instance : its_service.second) {
- for (auto &its_eventgroup : its_instance.second) {
- auto its_subscriptions
- = its_eventgroup.second->get_remote_subscriptions();
- for (auto &s : its_subscriptions) {
- for (auto its_client : s->get_clients()) {
- if (_force) {
- its_expired_subscriptions[s].insert(its_client);
- } else {
- auto its_expiration = s->get_expiration(its_client);
- if (its_expiration != std::chrono::steady_clock::time_point()) {
- if (its_expiration < now) {
- its_expired_subscriptions[s].insert(its_client);
- } else if (its_expiration < its_next_expiration) {
- its_next_expiration = its_expiration;
- }
+ its_eventgroups = eventgroups_;
+ }
+
+ for (auto &its_service : its_eventgroups) {
+ for (auto &its_instance : its_service.second) {
+ for (auto &its_eventgroup : its_instance.second) {
+ auto its_subscriptions
+ = its_eventgroup.second->get_remote_subscriptions();
+ for (auto &s : its_subscriptions) {
+ for (auto its_client : s->get_clients()) {
+ if (_force) {
+ its_expired_subscriptions[s].insert(its_client);
+ } else {
+ auto its_expiration = s->get_expiration(its_client);
+ if (its_expiration != std::chrono::steady_clock::time_point()) {
+ if (its_expiration < now) {
+ its_expired_subscriptions[s].insert(its_client);
+ } else if (its_expiration < its_next_expiration) {
+ its_next_expiration = its_expiration;
}
}
}
@@ -3152,22 +3258,53 @@ routing_manager_impl::expire_subscriptions(bool _force) {
auto its_service = its_info->get_service();
auto its_instance = its_info->get_instance();
auto its_eventgroup = its_info->get_eventgroup();
- auto its_major = its_info->get_major();
remote_subscription_id_t its_id;
+ update_remote_subscription_mutex_.lock();
auto its_result = its_info->update_remote_subscription(
s.first, std::chrono::steady_clock::now(),
s.second, its_id, false);
if (its_result) {
const client_t its_offering_client
= find_local_client(its_service, its_instance);
- send_unsubscription(its_offering_client,
- its_service, its_instance, its_eventgroup, its_major,
+ const auto its_subscription = its_info->get_remote_subscription(its_id);
+ if (its_subscription) {
+ its_info->remove_remote_subscription(its_id);
+
+ std::lock_guard<std::mutex> its_lock(remote_subscribers_mutex_);
+ remote_subscribers_[its_service][its_instance].erase(its_offering_client);
+
+ if (its_info->get_remote_subscriptions().size() == 0) {
+ for (const auto &its_event : its_info->get_events()) {
+ bool has_remote_subscriber(false);
+ for (const auto &its_eventgroup : its_event->get_eventgroups()) {
+ const auto its_eventgroup_info
+ = find_eventgroup(its_service, its_instance, its_eventgroup);
+ if (its_eventgroup_info
+ && its_eventgroup_info->get_remote_subscriptions().size() > 0) {
+ has_remote_subscriber = true;
+ }
+ }
+ if (!has_remote_subscriber && its_event->is_shadow()) {
+ its_event->unset_payload();
+ }
+ }
+ }
+ } else {
+ VSOMEIP_ERROR << __func__
+ << ": Unknown expired subscription " << std::dec << its_id << " for eventgroup ["
+ << std::hex << std::setw(4) << std::setfill('0') << its_service << "."
+ << std::hex << std::setw(4) << std::setfill('0') << its_instance << "."
+ << std::hex << std::setw(4) << std::setfill('0') << its_eventgroup << "]";
+ }
+ send_expired_subscription(its_offering_client,
+ its_service, its_instance, its_eventgroup,
s.second, s.first->get_id());
}
+ update_remote_subscription_mutex_.unlock();
if (s.first->get_unreliable()) {
- VSOMEIP_INFO << "Expired subscription ["
+ VSOMEIP_INFO << (_force ? "Removed" : "Expired") << " subscription ["
<< std::hex << std::setfill('0') << std::setw(4) << its_service << "."
<< std::hex << std::setfill('0') << std::setw(4) << its_instance << "."
<< std::hex << std::setfill('0') << std::setw(4) << its_eventgroup << "] unreliable from "
@@ -3176,7 +3313,7 @@ routing_manager_impl::expire_subscriptions(bool _force) {
}
if (s.first->get_reliable()) {
- VSOMEIP_INFO << "Expired subscription ["
+ VSOMEIP_INFO << (_force ? "Removed" : "Expired") << " subscription ["
<< std::hex << std::setfill('0') << std::setw(4) << its_service << "."
<< std::hex << std::setfill('0') << std::setw(4) << its_instance << "."
<< std::hex << std::setfill('0') << std::setw(4) << its_eventgroup << "] reliable from "
@@ -3205,7 +3342,7 @@ void routing_manager_impl::log_version_timer_cbk(boost::system::error_code const
}
std::stringstream its_last_resume;
{
- std::lock_guard<std::mutex> its_lock(last_resume_mutex_);
+ std::lock_guard<std::mutex> its_lock(routing_state_mutex_);
if (last_resume_ != std::chrono::steady_clock::time_point::min()) {
its_last_resume << " | " << std::dec
<< std::chrono::duration_cast<std::chrono::seconds>(
@@ -3491,15 +3628,31 @@ void routing_manager_impl::send_subscribe(client_t _client, service_t _service,
}
void routing_manager_impl::set_routing_state(routing_state_e _routing_state) {
+
+ // Ignore setting to the current routing state
+ {
+ std::lock_guard<std::mutex> its_lock(routing_state_mutex_);
+ if (routing_state_ == _routing_state) {
+ VSOMEIP_INFO << "rmi::" << __func__ << " No routing state change --> do nothing.";
+ return;
+ }
+
+ routing_state_ = _routing_state;
+ }
+
if(discovery_) {
switch (_routing_state) {
case routing_state_e::RS_SUSPENDED:
{
- VSOMEIP_INFO << "Set routing to suspend mode, diagnosis mode is "
- << ((discovery_->get_diagnosis_mode() == true) ? "active." : "inactive.");
+ VSOMEIP_INFO << "rmi::" << __func__ << " Set routing to suspend mode, diagnosis mode is "
+ << ((discovery_->get_diagnosis_mode() == true) ? "active." : "inactive.");
+
// stop processing of incoming SD messages
discovery_->stop();
+ VSOMEIP_INFO << "rmi::" << __func__ << " Inform all applications that we are going to suspend";
+ send_suspend();
+
// remove all remote subscriptions to remotely offered services on this node
expire_subscriptions(true);
@@ -3520,6 +3673,10 @@ void routing_manager_impl::set_routing_state(routing_state_e _routing_state) {
std::lock_guard<std::mutex> its_lock(remote_subscription_state_mutex_);
remote_subscription_state_.clear();
}
+
+ // send StopSubscribes and clear subscribed_ map
+ discovery_->unsubscribe_all_on_suspend();
+
// mark all external services as offline
services_t its_remote_services;
{
@@ -3528,11 +3685,6 @@ void routing_manager_impl::set_routing_state(routing_state_e _routing_state) {
}
for (const auto &s : its_remote_services) {
for (const auto &i : s.second) {
- // determine existing subscriptions to remote service and send StopSubscribe
- for (auto its_eventgroup : get_subscribed_eventgroups(s.first, i.first)) {
- discovery_->unsubscribe(s.first, i.first, its_eventgroup, VSOMEIP_ROUTING_CLIENT);
- }
-
const bool has_reliable(i.second->get_endpoint(true));
const bool has_unreliable(i.second->get_endpoint(false));
del_routing_info(s.first, i.first, has_reliable, has_unreliable);
@@ -3541,14 +3693,18 @@ void routing_manager_impl::set_routing_state(routing_state_e _routing_state) {
unset_all_eventpayloads(s.first, i.first);
}
}
+
+ VSOMEIP_INFO << "rmi::" << __func__ << " Set routing to suspend mode done, diagnosis mode is "
+ << ((discovery_->get_diagnosis_mode() == true) ? "active." : "inactive.");
+
break;
}
case routing_state_e::RS_RESUMED:
{
- VSOMEIP_INFO << "Set routing to resume mode, diagnosis mode was "
- << ((discovery_->get_diagnosis_mode() == true) ? "active." : "inactive.");
+ VSOMEIP_INFO << "rmi::" << __func__ << " Set routing to resume mode, diagnosis mode was "
+ << ((discovery_->get_diagnosis_mode() == true) ? "active." : "inactive.");
{
- std::lock_guard<std::mutex> its_lock(last_resume_mutex_);
+ std::lock_guard<std::mutex> its_lock(routing_state_mutex_);
last_resume_ = std::chrono::steady_clock::now();
}
@@ -3575,11 +3731,14 @@ void routing_manager_impl::set_routing_state(routing_state_e _routing_state) {
discovery_->offer_service(its_instance.second);
}
}
+
+ VSOMEIP_INFO << "rmi::" << __func__ << " Set routing to resume mode done, diagnosis mode was "
+ << ((discovery_->get_diagnosis_mode() == true) ? "active." : "inactive.");
break;
}
case routing_state_e::RS_DIAGNOSIS:
{
- VSOMEIP_INFO << "Set routing to diagnosis mode.";
+ VSOMEIP_INFO << "rmi::" << __func__ << " Set routing to diagnosis mode.";
discovery_->set_diagnosis_mode(true);
// send StopOffer messages for all someip protocol services
@@ -3591,11 +3750,13 @@ void routing_manager_impl::set_routing_state(routing_state_e _routing_state) {
}
}
}
+
+ VSOMEIP_INFO << "rmi::" << __func__ << " Set routing to diagnosis mode done.";
break;
}
case routing_state_e::RS_RUNNING:
- VSOMEIP_INFO << "Set routing to running mode, diagnosis mode was "
- << ((discovery_->get_diagnosis_mode() == true) ? "active." : "inactive.");
+ VSOMEIP_INFO << "rmi::" << __func__ << " Set routing to running mode, diagnosis mode was "
+ << ((discovery_->get_diagnosis_mode() == true) ? "active." : "inactive.");
// Reset relevant in service info
for (const auto &its_service : get_offered_services()) {
@@ -3619,6 +3780,9 @@ void routing_manager_impl::set_routing_state(routing_state_e _routing_state) {
}
}
}
+
+ VSOMEIP_INFO << "rmi::" << __func__ << " Set routing to running mode done, diagnosis mode was "
+ << ((discovery_->get_diagnosis_mode() == true) ? "active." : "inactive.");
break;
default:
break;
@@ -3724,7 +3888,7 @@ void routing_manager_impl::requested_service_remove(client_t _client,
if (!found_service->second.size()) {
found_client->second.erase(_service);
if (!found_client->second.size()) {
- requested_services_.erase(client_);
+ requested_services_.erase(_client);
}
}
}
@@ -4057,6 +4221,7 @@ routing_manager_impl::on_unsubscribe_ack(client_t _client,
std::shared_ptr<eventgroupinfo> its_info
= find_eventgroup(_service, _instance, _eventgroup);
if (its_info) {
+ update_remote_subscription_mutex_.lock();
const auto its_subscription = its_info->get_remote_subscription(_id);
if (its_subscription) {
its_info->remove_remote_subscription(_id);
@@ -4088,6 +4253,7 @@ routing_manager_impl::on_unsubscribe_ack(client_t _client,
<< std::hex << std::setw(4) << std::setfill('0') << _instance << "."
<< std::hex << std::setw(4) << std::setfill('0') << _eventgroup << "]";
}
+ update_remote_subscription_mutex_.unlock();
} else {
VSOMEIP_ERROR << __func__
<< ": Received StopSubscribe for unknown eventgroup: ("
@@ -4122,7 +4288,7 @@ void routing_manager_impl::send_subscription(
&routing_manager_stub_host::on_subscribe_nack,
std::dynamic_pointer_cast<routing_manager_stub_host>(shared_from_this()),
its_client, _service, _instance,
- _eventgroup, ANY_EVENT, _id);
+ _eventgroup, ANY_EVENT, _id, false);
io_.post(its_callback);
} else {
const auto its_callback = std::bind(
@@ -4146,7 +4312,7 @@ void routing_manager_impl::send_subscription(
&routing_manager_stub_host::on_subscribe_nack,
std::dynamic_pointer_cast<routing_manager_stub_host>(shared_from_this()),
its_client, _service, _instance, _eventgroup,
- ANY_EVENT, _id);
+ ANY_EVENT, _id, true);
io_.post(its_callback);
} catch (const std::exception &e) {
VSOMEIP_ERROR << __func__ << e.what();
@@ -4270,7 +4436,7 @@ routing_manager_impl::send_unsubscription(client_t _offering_client,
host_->on_subscription(_service, _instance,
_eventgroup, its_client, own_uid_, own_gid_, false,
[this, self, _service, _instance, _eventgroup,
- its_client, _id, _offering_client]
+ its_client, _id]
(const bool _is_accepted) {
(void)_is_accepted;
try {
@@ -4303,6 +4469,30 @@ routing_manager_impl::send_unsubscription(client_t _offering_client,
}
}
+void
+routing_manager_impl::send_expired_subscription(client_t _offering_client,
+ service_t _service, instance_t _instance,
+ eventgroup_t _eventgroup,
+ const std::set<client_t> &_removed,
+ remote_subscription_id_t _id) {
+
+ if (host_->get_client() == _offering_client) {
+ auto self = shared_from_this();
+ for (const auto its_client : _removed) {
+ host_->on_subscription(_service, _instance,
+ _eventgroup, its_client, own_uid_, own_gid_, false,
+ [] (const bool _subscription_accepted){
+ (void)_subscription_accepted;
+ });
+ }
+ } else {
+ for (const auto its_client : _removed) {
+ stub_->send_expired_subscription(find_local(_offering_client), its_client,
+ _service, _instance, _eventgroup, ANY_EVENT, _id);
+ }
+ }
+}
+
bool
routing_manager_impl::update_security_policy_configuration(
uint32_t _uid, uint32_t _gid,
@@ -4347,7 +4537,7 @@ bool routing_manager_impl::insert_event_statistics(service_t _service, instance_
// check list for entry with least counter value
uint32_t its_min_count(0xFFFFFFFF);
auto its_tuple_to_discard = std::make_tuple(0xFFFF, 0xFFFF, 0xFFFF);
- for (const auto& it : message_statistics_) {
+ for (const auto &it : message_statistics_) {
if (it.second.counter_ < its_min_count) {
its_min_count = it.second.counter_;
its_tuple_to_discard = it.first;
@@ -4389,7 +4579,7 @@ void routing_manager_impl::statistics_log_timer_cbk(boost::system::error_code co
std::stringstream its_log;
{
std::lock_guard<std::mutex> its_lock(message_statistics_mutex_);
- for (const auto& s : message_statistics_) {
+ for (const auto &s : message_statistics_) {
if (s.second.counter_ / (its_interval / 1000) >= its_min_freq) {
uint16_t its_subscribed(0);
std::shared_ptr<event> its_event = find_event(std::get<0>(s.first), std::get<1>(s.first), std::get<2>(s.first));
@@ -4431,4 +4621,9 @@ void routing_manager_impl::statistics_log_timer_cbk(boost::system::error_code co
}
}
+void routing_manager_impl::send_suspend() const {
+
+ stub_->send_suspend();
+}
+
} // namespace vsomeip_v3
diff --git a/implementation/routing/src/routing_manager_proxy.cpp b/implementation/routing/src/routing_manager_proxy.cpp
index 872067c..06573a5 100644
--- a/implementation/routing/src/routing_manager_proxy.cpp
+++ b/implementation/routing/src/routing_manager_proxy.cpp
@@ -1071,6 +1071,7 @@ void routing_manager_proxy::on_message(const byte_t *_data, length_t _size,
<< " ~> Skip message!";
return;
}
+ cache_event_payload(its_message);
}
}
#ifdef USE_DLT
@@ -1162,34 +1163,35 @@ void routing_manager_proxy::on_message(const byte_t *_data, length_t _size,
[this, self, its_client, its_service, its_instance,
its_eventgroup, its_event, its_subscription_id, its_major]
(const bool _subscription_accepted){
+ std::uint32_t its_count = 0;
if(_subscription_accepted) {
send_subscribe_ack(its_client, its_service, its_instance,
its_eventgroup, its_event, its_subscription_id);
+ std::set<event_t> its_already_subscribed_events;
+ bool inserted = insert_subscription(its_service, its_instance, its_eventgroup,
+ its_event, VSOMEIP_ROUTING_CLIENT, &its_already_subscribed_events);
+ if (inserted) {
+ notify_remote_initially(its_service, its_instance, its_eventgroup,
+ its_already_subscribed_events);
+ }
+#ifdef VSOMEIP_ENABLE_COMPAT
+ send_pending_notify_ones(its_service, its_instance, its_eventgroup, its_client, true);
+#endif
+ its_count = get_remote_subscriber_count(its_service, its_instance, its_eventgroup, true);
} else {
send_subscribe_nack(its_client, its_service, its_instance,
its_eventgroup, its_event, its_subscription_id);
}
- std::set<event_t> its_already_subscribed_events;
- bool inserted = insert_subscription(its_service, its_instance, its_eventgroup,
- its_event, VSOMEIP_ROUTING_CLIENT, &its_already_subscribed_events);
- if (inserted) {
- notify_remote_initially(its_service, its_instance, its_eventgroup,
- its_already_subscribed_events);
- }
-#ifdef VSOMEIP_ENABLE_COMPAT
- send_pending_notify_ones(its_service, its_instance, its_eventgroup, its_client, true);
-#endif
- std::uint32_t its_count = get_remote_subscriber_count(
- its_service, its_instance, its_eventgroup, true);
VSOMEIP_INFO << "SUBSCRIBE("
<< std::hex << std::setw(4) << std::setfill('0') << its_client <<"): ["
<< std::hex << std::setw(4) << std::setfill('0') << its_service << "."
<< std::hex << std::setw(4) << std::setfill('0') << its_instance << "."
<< std::hex << std::setw(4) << std::setfill('0') << its_eventgroup << ":"
<< std::hex << std::setw(4) << std::setfill('0') << its_event << ":"
- << std::dec << (uint16_t)its_major << "]"
+ << std::dec << (uint16_t)its_major << "] "
<< (bool)(its_subscription_id != PENDING_SUBSCRIPTION_ID) << " "
- << std::dec << its_count;
+ << (_subscription_accepted ? std::to_string(its_count) : "-")
+ << (_subscription_accepted ? " ACCEPTED" : " NOT ACCEPTED");
#ifdef VSOMEIP_ENABLE_COMPAT
routing_manager_base::erase_incoming_subscription_state(its_client, its_service,
its_instance, its_eventgroup, its_event);
@@ -1282,7 +1284,7 @@ void routing_manager_proxy::on_message(const byte_t *_data, length_t _size,
case VSOMEIP_UNSUBSCRIBE:
if (_size != VSOMEIP_UNSUBSCRIBE_COMMAND_SIZE) {
- VSOMEIP_WARNING << "Received an UNSUBSCRIBE command with wrong ~> skip!";
+ VSOMEIP_WARNING << "Received an UNSUBSCRIBE command with wrong size ~> skip!";
break;
}
std::memcpy(&its_service, &_data[VSOMEIP_COMMAND_PAYLOAD_POS],
@@ -1320,6 +1322,44 @@ void routing_manager_proxy::on_message(const byte_t *_data, length_t _size,
<< std::dec << its_remote_subscriber_count;
break;
+ case VSOMEIP_EXPIRED_SUBSCRIPTION:
+ if (_size != VSOMEIP_EXPIRED_SUBSCRIPTION_COMMAND_SIZE) {
+ VSOMEIP_WARNING << "Received an VSOMEIP_EXPIRED_SUBSCRIPTION command with wrong size ~> skip!";
+ break;
+ }
+ 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_event, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 6],
+ sizeof(its_event));
+ std::memcpy(&its_subscription_id, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 8],
+ sizeof(its_subscription_id));
+ host_->on_subscription(its_service, its_instance, its_eventgroup, its_client, its_sender_uid, its_sender_gid, false, [](const bool _subscription_accepted){ (void)_subscription_accepted; });
+ if (its_subscription_id == PENDING_SUBSCRIPTION_ID) {
+ // Local subscriber: withdraw subscription
+ routing_manager_base::unsubscribe(its_client, its_sender_uid, its_sender_gid, its_service, its_instance, its_eventgroup, its_event);
+ } else {
+ // Remote subscriber: withdraw subscription only if no more remote subscriber exists
+ its_remote_subscriber_count = get_remote_subscriber_count(its_service,
+ its_instance, its_eventgroup, false);
+ if (!its_remote_subscriber_count) {
+ routing_manager_base::unsubscribe(VSOMEIP_ROUTING_CLIENT, ANY_UID, ANY_GID, its_service,
+ its_instance, its_eventgroup, its_event);
+ }
+ }
+ VSOMEIP_INFO << "UNSUBSCRIBE EXPIRED SUBSCRIPTION("
+ << std::hex << std::setw(4) << std::setfill('0') << its_client << "): ["
+ << std::hex << std::setw(4) << std::setfill('0') << its_service << "."
+ << std::hex << std::setw(4) << std::setfill('0') << its_instance << "."
+ << std::hex << std::setw(4) << std::setfill('0') << its_eventgroup << "."
+ << std::hex << std::setw(4) << std::setfill('0') << its_event << "] "
+ << (bool)(its_subscription_id != PENDING_SUBSCRIPTION_ID) << " "
+ << std::dec << its_remote_subscriber_count;
+ break;
+
case VSOMEIP_SUBSCRIBE_NACK:
if (_size != VSOMEIP_SUBSCRIBE_NACK_COMMAND_SIZE) {
VSOMEIP_WARNING << "Received a VSOMEIP_SUBSCRIBE_NACK command with wrong size ~> skip!";
@@ -1538,6 +1578,11 @@ void routing_manager_proxy::on_message(const byte_t *_data, length_t _size,
}
break;
}
+
+ case VSOMEIP_SUSPEND:
+ on_suspend(); // cleanup remote subscribers
+ break;
+
default:
break;
}
@@ -1666,6 +1711,10 @@ void routing_manager_proxy::on_routing_info(const byte_t *_data,
j += uint32_t(sizeof(minor_version_t));
if (routing_info_entry == routing_info_entry_e::RIE_ADD_SERVICE_INSTANCE) {
+ if (get_routing_state() == routing_state_e::RS_SUSPENDED) {
+ VSOMEIP_INFO << "rmp::" <<__func__ << " We are in suspended mode, the service will not be added!";
+ return;
+ }
{
std::lock_guard<std::mutex> its_lock(known_clients_mutex_);
known_clients_.insert(its_client);
@@ -1704,6 +1753,14 @@ void routing_manager_proxy::on_routing_info(const byte_t *_data,
<< std::hex << std::setw(4) << std::setfill('0') << its_service << "."
<< std::hex << std::setw(4) << std::setfill('0') << its_instance
<< ":" << std::dec << int(its_major) << "." << std::dec << its_minor << "]";
+
+ if (its_client == get_client()) {
+ VSOMEIP_INFO << __func__
+ << ": Clearing subscriptions for service ["
+ << std::hex << std::setw(4) << std::setfill('0') << its_service << "."
+ << std::hex << std::setw(4) << std::setfill('0') << its_instance << "]";
+ unsubscribe_all(its_service, its_instance);
+ }
}
its_services_size -= uint32_t(sizeof(instance_t) + sizeof(major_version_t) + sizeof(minor_version_t) );
@@ -2652,4 +2709,26 @@ void routing_manager_proxy::on_client_assign_ack(const client_t &_client) {
}
}
+void routing_manager_proxy::on_suspend() {
+
+ VSOMEIP_INFO << __func__ << ": Application "
+ << std::hex << std::setw(4) << std::setfill('0')
+ << host_->get_client();
+
+ std::lock_guard<std::mutex> its_lock(remote_subscriber_count_mutex_);
+
+ // Unsubscribe everything that is left over.
+ for (const auto &s : remote_subscriber_count_) {
+ for (const auto &i : s.second) {
+ for (const auto e : i.second)
+ routing_manager_base::unsubscribe(
+ VSOMEIP_ROUTING_CLIENT, ANY_UID, ANY_GID,
+ s.first, i.first, e.first, ANY_EVENT);
+ }
+ }
+
+ // Remove all entries.
+ remote_subscriber_count_.clear();
+}
+
} // namespace vsomeip_v3
diff --git a/implementation/routing/src/routing_manager_stub.cpp b/implementation/routing/src/routing_manager_stub.cpp
index 9668352..406b0d9 100644
--- a/implementation/routing/src/routing_manager_stub.cpp
+++ b/implementation/routing/src/routing_manager_stub.cpp
@@ -399,7 +399,8 @@ void routing_manager_stub::on_message(const byte_t *_data, length_t _size,
std::memcpy(&its_subscription_id, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 10],
sizeof(its_subscription_id));
host_->on_subscribe_nack(its_subscriber, its_service,
- its_instance, its_eventgroup, its_notifier, its_subscription_id);
+ its_instance, its_eventgroup, its_notifier,
+ its_subscription_id, false);
VSOMEIP_INFO << "SUBSCRIBE NACK("
<< std::hex << std::setw(4) << std::setfill('0') << its_client << "): ["
<< std::hex << std::setw(4) << std::setfill('0') << its_service << "."
@@ -946,6 +947,8 @@ void routing_manager_stub::on_stop_offer_service(client_t _client,
if (0 == found_service->second.size()) {
found_client->second.second.erase(_service);
}
+ inform_provider(_client, _service, _instance, _major, _minor,
+ routing_info_entry_e::RIE_DEL_SERVICE_INSTANCE);
inform_requesters(_client, _service, _instance, _major, _minor,
routing_info_entry_e::RIE_DEL_SERVICE_INSTANCE, false);
} else if( _major == DEFAULT_MAJOR && _minor == DEFAULT_MINOR) {
@@ -953,6 +956,8 @@ void routing_manager_stub::on_stop_offer_service(client_t _client,
if (0 == found_service->second.size()) {
found_client->second.second.erase(_service);
}
+ inform_provider(_client, _service, _instance, _major, _minor,
+ routing_info_entry_e::RIE_DEL_SERVICE_INSTANCE);
inform_requesters(_client, _service, _instance, _major, _minor,
routing_info_entry_e::RIE_DEL_SERVICE_INSTANCE, false);
}
@@ -1285,16 +1290,9 @@ void routing_manager_stub::distribute_credentials(client_t _hoster, service_t _s
for (auto its_requesting_client : service_requests_) {
auto its_service = its_requesting_client.second.find(_service);
if (its_service != its_requesting_client.second.end()) {
- for (auto its_instance : its_service->second) {
- if (its_instance.first == ANY_INSTANCE ||
- its_instance.first == _instance) {
- its_requesting_clients.insert(its_requesting_client.first);
- } else {
- auto found_instance = its_service->second.find(_instance);
- if (found_instance != its_service->second.end()) {
- its_requesting_clients.insert(its_requesting_client.first);
- }
- }
+ if (its_service->second.find(_instance) != its_service->second.end()
+ || its_service->second.find(ANY_INSTANCE) != its_service->second.end()) {
+ its_requesting_clients.insert(its_requesting_client.first);
}
}
}
@@ -1302,11 +1300,11 @@ void routing_manager_stub::distribute_credentials(client_t _hoster, service_t _s
// search for UID / GID linked with the client ID that offers the requested services
std::pair<uint32_t, uint32_t> its_uid_gid;
if (security::get()->get_client_to_uid_gid_mapping(_hoster, its_uid_gid)) {
+ its_credentials.insert(its_uid_gid);
for (auto its_requesting_client : its_requesting_clients) {
std::pair<uint32_t, uint32_t> its_requester_uid_gid;
if (security::get()->get_client_to_uid_gid_mapping(its_requesting_client, its_requester_uid_gid)) {
if (its_uid_gid != its_requester_uid_gid) {
- its_credentials.insert(std::make_pair(std::get<0>(its_uid_gid), std::get<1>(its_uid_gid)));
create_client_credentials_info(its_requesting_client);
insert_client_credentials_info(its_requesting_client, its_credentials);
send_client_credentials_info(its_requesting_client);
@@ -1316,20 +1314,27 @@ void routing_manager_stub::distribute_credentials(client_t _hoster, service_t _s
}
}
+void routing_manager_stub::inform_provider(client_t _hoster, service_t _service,
+ instance_t _instance, major_version_t _major, minor_version_t _minor,
+ routing_info_entry_e _entry) {
+
+ if (_hoster != VSOMEIP_ROUTING_CLIENT
+ && _hoster != host_->get_client()) {
+ create_client_routing_info(_hoster);
+ insert_client_routing_info(_hoster, _entry, _hoster,
+ _service, _instance, _major, _minor);
+ send_client_routing_info(_hoster);
+ }
+};
+
void routing_manager_stub::inform_requesters(client_t _hoster, service_t _service,
instance_t _instance, major_version_t _major, minor_version_t _minor,
routing_info_entry_e _entry, bool _inform_service) {
for (auto its_client : service_requests_) {
auto its_service = its_client.second.find(_service);
if (its_service != its_client.second.end()) {
- bool send(false);
- for (auto its_instance : its_service->second) {
- if (its_instance.first == ANY_INSTANCE ||
- its_instance.first == _instance) {
- send = true;
- }
- }
- if (send) {
+ if (its_service->second.find(_instance) != its_service->second.end()
+ || its_service->second.find(ANY_INSTANCE) != its_service->second.end()) {
if (_inform_service) {
if (_hoster != VSOMEIP_ROUTING_CLIENT &&
_hoster != host_->get_client()) {
@@ -1447,6 +1452,44 @@ bool routing_manager_stub::send_unsubscribe(
}
}
+bool routing_manager_stub::send_expired_subscription(
+ const std::shared_ptr<endpoint>& _target,
+ client_t _client, service_t _service, instance_t _instance,
+ eventgroup_t _eventgroup, event_t _event,
+ remote_subscription_id_t _id) {
+ if (_target) {
+ byte_t its_command[VSOMEIP_EXPIRED_SUBSCRIPTION_COMMAND_SIZE];
+ uint32_t its_size = VSOMEIP_EXPIRED_SUBSCRIPTION_COMMAND_SIZE
+ - VSOMEIP_COMMAND_HEADER_SIZE;
+ its_command[VSOMEIP_COMMAND_TYPE_POS] = VSOMEIP_EXPIRED_SUBSCRIPTION;
+ 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], &_eventgroup,
+ sizeof(_eventgroup));
+ std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 6], &_event,
+ sizeof(_event));
+ std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 8], &_id,
+ sizeof(_id));
+
+ return _target->send(its_command, sizeof(its_command));
+ } else {
+ VSOMEIP_WARNING << __func__ << " Couldn't send expired subscription to local client ["
+ << std::hex << std::setw(4) << std::setfill('0') << _service << "."
+ << std::hex << std::setw(4) << std::setfill('0') << _instance << "."
+ << std::hex << std::setw(4) << std::setfill('0') << _eventgroup << "."
+ << std::hex << std::setw(4) << std::setfill('0') << _event << "]"
+ << " subscriber: "<< std::hex << std::setw(4) << std::setfill('0')
+ << _client;
+ return false;
+ }
+}
+
void routing_manager_stub::send_subscribe_ack(client_t _client, service_t _service,
instance_t _instance, eventgroup_t _eventgroup, event_t _event) {
@@ -2257,7 +2300,7 @@ routing_manager_stub::send_requester_policies(const std::unordered_set<client_t>
pending_security_update_id_t its_policy_id;
// serialize the policies and send them...
- for (const auto& p : _policies) {
+ for (const auto &p : _policies) {
std::vector<byte_t> its_policy_data;
if (p->serialize(its_policy_data)) {
std::vector<byte_t> its_message;
@@ -2569,4 +2612,12 @@ void routing_manager_stub::on_security_update_response(
}
}
+void routing_manager_stub::send_suspend() const {
+
+ static const std::vector<byte_t> its_suspend(
+ { VSOMEIP_SUSPEND, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 });
+
+ broadcast(its_suspend);
+}
+
} // namespace vsomeip_v3
diff --git a/implementation/runtime/src/application_impl.cpp b/implementation/runtime/src/application_impl.cpp
index aba8647..467bca2 100644
--- a/implementation/runtime/src/application_impl.cpp
+++ b/implementation/runtime/src/application_impl.cpp
@@ -961,7 +961,7 @@ void application_impl::on_subscription(service_t _service, instance_t _instance,
}
}
- if(handler_found) {
+ if (handler_found) {
if(auto its_handler = its_handlers.first) {
// "normal" subscription handler exists
_accepted_cb(its_handler(_client, _uid, _gid, _subscribed));
diff --git a/implementation/security/src/policy.cpp b/implementation/security/src/policy.cpp
index 9630e5f..260198a 100644
--- a/implementation/security/src/policy.cpp
+++ b/implementation/security/src/policy.cpp
@@ -305,7 +305,7 @@ policy::serialize(std::vector<byte_t> &_data) const {
uint32_t its_requests_size(0);
serialize_u32(its_requests_size, _data);
- for (const auto& its_request : requests_) {
+ for (const auto &its_request : requests_) {
for (auto its_service = its_request.first.lower();
its_service <= its_request.first.upper();
its_service++) {
@@ -316,7 +316,7 @@ policy::serialize(std::vector<byte_t> &_data) const {
uint32_t its_instances_size(0);
serialize_u32(its_instances_size, _data);
- for (const auto& i : its_request.second) {
+ for (const auto &i : its_request.second) {
boost::icl::interval_set<instance_t> its_instances;
its_instances.insert(i.first);
serialize_interval_set(its_instances, _data);
diff --git a/implementation/security/src/security_impl.cpp b/implementation/security/src/security_impl.cpp
index 8a3d276..377e310 100644
--- a/implementation/security/src/security_impl.cpp
+++ b/implementation/security/src/security_impl.cpp
@@ -470,7 +470,7 @@ security_impl::update_security_policy(uint32_t _uid, uint32_t _gid,
}
if (its_matching_policy) {
- for (const auto& r : _policy->requests_) {
+ for (const auto &r : _policy->requests_) {
service_t its_lower, its_upper;
get_bounds(r.first, its_lower, its_upper);
for (auto s = its_lower; s <= its_upper; s++) {
@@ -479,7 +479,7 @@ security_impl::update_security_policy(uint32_t _uid, uint32_t _gid,
its_matching_policy->requests_ += std::make_pair(its_service, r.second);
}
}
- for (const auto& o : _policy->offers_) {
+ for (const auto &o : _policy->offers_) {
service_t its_lower, its_upper;
get_bounds(o.first, its_lower, its_upper);
for (auto s = its_lower; s <= its_upper; s++) {
@@ -1081,8 +1081,8 @@ security_impl::get_requester_policies(const std::shared_ptr<policy> _policy,
}
std::lock_guard<std::mutex> its_lock(_policy->mutex_);
- for (const auto& o : _policy->offers_) {
- for (const auto& p : its_policies) {
+ for (const auto &o : _policy->offers_) {
+ for (const auto &p : its_policies) {
if (p == _policy)
continue;
@@ -1091,7 +1091,7 @@ security_impl::get_requester_policies(const std::shared_ptr<policy> _policy,
auto its_policy = std::make_shared<policy>();
its_policy->credentials_ = p->credentials_;
- for (const auto& r : p->requests_) {
+ for (const auto &r : p->requests_) {
// o represents an offer by a service interval and its instances
// (a set of intervals)
// r represents a request by a service interval and its instances
@@ -1109,8 +1109,8 @@ security_impl::get_requester_policies(const std::shared_ptr<policy> _policy,
auto its_service_min = std::max(its_o_lower, its_r_lower);
auto its_service_max = std::min(its_r_upper, its_o_upper);
- for (const auto& i : o.second) {
- for (const auto& j : r.second) {
+ for (const auto &i : o.second) {
+ for (const auto &j : r.second) {
for (const auto& k : j.second) {
instance_t its_i_lower, its_i_upper, its_k_lower, its_k_upper;
get_bounds(i, its_i_lower, its_i_upper);
@@ -1151,7 +1151,7 @@ security_impl::get_clients(uid_t _uid, gid_t _gid,
std::unordered_set<client_t> &_clients) const {
std::lock_guard<std::mutex> its_lock(ids_mutex_);
- for (const auto& i : ids_) {
+ for (const auto &i : ids_) {
if (i.second.first == _uid && i.second.second == _gid)
_clients.insert(i.first);
}
diff --git a/implementation/service_discovery/include/service_discovery.hpp b/implementation/service_discovery/include/service_discovery.hpp
index 778ce08..77b4258 100644
--- a/implementation/service_discovery/include/service_discovery.hpp
+++ b/implementation/service_discovery/include/service_discovery.hpp
@@ -45,6 +45,7 @@ public:
virtual void unsubscribe(service_t _service, instance_t _instance,
eventgroup_t _eventgroup, client_t _client) = 0;
virtual void unsubscribe_all(service_t _service, instance_t _instance) = 0;
+ virtual void unsubscribe_all_on_suspend() = 0;
virtual bool send(bool _is_announcing) = 0;
diff --git a/implementation/service_discovery/include/service_discovery_host.hpp b/implementation/service_discovery/include/service_discovery_host.hpp
index f864571..0f992d7 100644
--- a/implementation/service_discovery/include/service_discovery_host.hpp
+++ b/implementation/service_discovery/include/service_discovery_host.hpp
@@ -86,7 +86,7 @@ public:
virtual void on_subscribe_nack(client_t _client,
service_t _service, instance_t _instance, eventgroup_t _eventgroup,
- event_t _event, remote_subscription_id_t _subscription_id) = 0;
+ event_t _event, remote_subscription_id_t _subscription_id, bool _simulated) = 0;
virtual std::chrono::steady_clock::time_point expire_subscriptions(bool _force) = 0;
diff --git a/implementation/service_discovery/include/service_discovery_impl.hpp b/implementation/service_discovery/include/service_discovery_impl.hpp
index 81bb91f..c4e3835 100644
--- a/implementation/service_discovery/include/service_discovery_impl.hpp
+++ b/implementation/service_discovery/include/service_discovery_impl.hpp
@@ -79,7 +79,8 @@ public:
void unsubscribe(service_t _service, instance_t _instance,
eventgroup_t _eventgroup, client_t _client);
void unsubscribe_all(service_t _service, instance_t _instance);
- void reset_subscriptions(service_t _service, instance_t _instance);
+ void unsubscribe_all_on_suspend();
+ void remove_subscriptions(service_t _service, instance_t _instance);
bool send(bool _is_announcing);
@@ -239,7 +240,7 @@ private:
const std::shared_ptr<endpoint> &_unreliable,
boost::asio::ip::address &_address) const;
- std::shared_ptr<request> find_request(service_t _service, instance_t _instance);
+ void update_request(service_t _service, instance_t _instance);
void start_offer_debounce_timer(bool _first_start);
void on_offer_debounce_timer_expired(const boost::system::error_code &_error);
diff --git a/implementation/service_discovery/src/service_discovery_impl.cpp b/implementation/service_discovery/src/service_discovery_impl.cpp
index ca4e131..74e509b 100644
--- a/implementation/service_discovery/src/service_discovery_impl.cpp
+++ b/implementation/service_discovery/src/service_discovery_impl.cpp
@@ -165,9 +165,10 @@ service_discovery_impl::start() {
}
}
if (endpoint_ && !reliable_) {
- // rejoin multicast group
- dynamic_cast<udp_server_endpoint_impl*>(
- endpoint_.get())->join(sd_multicast_);
+ auto its_endpoint = std::dynamic_pointer_cast<
+ udp_server_endpoint_impl>(endpoint_);
+ if (its_endpoint)
+ its_endpoint->join(sd_multicast_);
}
}
is_suspended_ = false;
@@ -213,17 +214,17 @@ service_discovery_impl::release_service(
}
}
-std::shared_ptr<request>
-service_discovery_impl::find_request(service_t _service, instance_t _instance) {
+void
+service_discovery_impl::update_request(service_t _service, instance_t _instance) {
std::lock_guard<std::mutex> its_lock(requested_mutex_);
auto find_service = requested_.find(_service);
if (find_service != requested_.end()) {
auto find_instance = find_service->second.find(_instance);
if (find_instance != find_service->second.end()) {
- return find_instance->second;
+ find_instance->second->set_sent_counter(
+ std::uint8_t(repetitions_max_ + 1));
}
}
- return nullptr;
}
void
@@ -232,6 +233,13 @@ service_discovery_impl::subscribe(
eventgroup_t _eventgroup, major_version_t _major,
ttl_t _ttl, client_t _client,
const std::shared_ptr<eventgroupinfo> &_info) {
+
+ if (is_suspended_) {
+ VSOMEIP_WARNING << "service_discovery::" << __func__
+ << ": Ignoring subscription as we are suspended.";
+ return;
+ }
+
#ifdef VSOMEIP_ENABLE_COMPAT
bool is_selective(_info ? _info->is_selective() : false);
#endif // VSOMEIP_ENABLE_COMPAT
@@ -248,8 +256,8 @@ service_discovery_impl::subscribe(
if (!its_subscription->is_selective() && is_selective) {
its_subscription->set_selective(true);
its_subscription->remove_client(VSOMEIP_ROUTING_CLIENT);
- for (const auto& e : _info->get_events()) {
- for (const auto& c : e->get_subscribers(_eventgroup)) {
+ for (const auto &e : _info->get_events()) {
+ for (const auto &c : e->get_subscribers(_eventgroup)) {
its_subscription->add_client(c);
}
}
@@ -517,23 +525,65 @@ service_discovery_impl::unsubscribe_all(
}
void
-service_discovery_impl::reset_subscriptions(
+service_discovery_impl::unsubscribe_all_on_suspend() {
+
+ std::map<boost::asio::ip::address,
+ std::vector<std::shared_ptr<message_impl> > > its_stopsubscribes;
+
+ {
+ std::lock_guard<std::mutex> its_lock(subscribed_mutex_);
+ for (auto its_service : subscribed_) {
+ for (auto its_instance : its_service.second) {
+ for (auto &its_eventgroup : its_instance.second) {
+ boost::asio::ip::address its_address;
+ auto its_current_message = std::make_shared<message_impl>();
+ auto its_subscription = its_eventgroup.second;
+ its_subscription->set_ttl(0);
+ const reliability_type_e its_reliability =
+ get_eventgroup_reliability(its_service.first, its_instance.first,
+ its_eventgroup.first, its_subscription);
+ auto its_data = create_eventgroup_entry(its_service.first, its_instance.first,
+ its_eventgroup.first, its_subscription, its_reliability);
+ auto its_reliable = its_subscription->get_endpoint(true);
+ auto its_unreliable = its_subscription->get_endpoint(false);
+ get_subscription_address(
+ its_reliable, its_unreliable, its_address);
+ if (its_data.entry_
+ && its_current_message->add_entry_data(its_data.entry_, its_data.options_)) {
+ its_stopsubscribes[its_address].push_back(its_current_message);
+ } else {
+ VSOMEIP_WARNING << __func__ << ": Failed to create StopSubscribe entry for: "
+ << std::hex << std::setw(4) << std::setfill('0') << its_service.first << "."
+ << std::hex << std::setw(4) << std::setfill('0') << its_instance.first << "."
+ << std::hex << std::setw(4) << std::setfill('0') << its_eventgroup.first
+ << " address: " << its_address.to_string();
+ }
+ }
+ its_instance.second.clear();
+ }
+ its_service.second.clear();
+ }
+ subscribed_.clear();
+ }
+
+ for (auto its_address : its_stopsubscribes) {
+ if (!serialize_and_send(its_address.second, its_address.first)) {
+ VSOMEIP_WARNING << __func__ << ": Failed to send StopSubscribe to address: "
+ << its_address.first.to_string();
+ }
+ }
+}
+
+void
+service_discovery_impl::remove_subscriptions(
service_t _service, instance_t _instance) {
std::lock_guard<std::mutex> 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) {
- auto its_subscription = its_eventgroup.second;
- for (auto its_client : its_subscription->get_clients()) {
- its_subscription->set_state(its_client,
- subscription_state_e::ST_UNKNOWN);
- }
- its_subscription->set_endpoint(nullptr, true);
- its_subscription->set_endpoint(nullptr, false);
- }
+ found_service->second.erase(_instance);
+ if (found_service->second.empty()) {
+ subscribed_.erase(found_service);
}
}
}
@@ -641,16 +691,16 @@ void
service_discovery_impl::insert_find_entries(
std::vector<std::shared_ptr<message_impl> > &_messages,
const requests_t &_requests) {
- std::lock_guard<std::mutex> its_lock(requested_mutex_);
entry_data_t its_data;
its_data.entry_ = its_data.other_ = nullptr;
for (const auto& its_service : _requests) {
for (const auto& its_instance : its_service.second) {
+ std::lock_guard<std::mutex> its_lock(requested_mutex_);
auto its_request = its_instance.second;
- // check if release_service was called
+ // check if release_service was called / offer was received
auto the_service = requested_.find(its_service.first);
if ( the_service != requested_.end() ) {
auto the_instance = the_service->second.find(its_instance.first);
@@ -722,17 +772,37 @@ service_discovery_impl::create_eventgroup_entry(
case reliability_type_e::RT_RELIABLE:
if (its_reliable_endpoint) {
insert_reliable = true;
+ } else {
+ VSOMEIP_WARNING << __func__ << ": Cannot create subscription as "
+ "reliable endpoint is zero: ["
+ << std::hex << std::setw(4) << std::setfill('0') << _service << "."
+ << std::hex << std::setw(4) << std::setfill('0') << _instance << "."
+ << std::hex << std::setw(4) << std::setfill('0') << _eventgroup << "]";
}
break;
case reliability_type_e::RT_UNRELIABLE:
if (its_unreliable_endpoint) {
insert_unreliable = true;
+ } else {
+ VSOMEIP_WARNING << __func__ << ": Cannot create subscription as "
+ "unreliable endpoint is zero: ["
+ << std::hex << std::setw(4) << std::setfill('0') << _service << "."
+ << std::hex << std::setw(4) << std::setfill('0') << _instance << "."
+ << std::hex << std::setw(4) << std::setfill('0') << _eventgroup << "]";
}
break;
case reliability_type_e::RT_BOTH:
if (its_reliable_endpoint && its_unreliable_endpoint) {
insert_reliable = true;
insert_unreliable = true;
+ } else {
+ VSOMEIP_WARNING << __func__ << ": Cannot create subscription as "
+ "endpoint is zero: ["
+ << std::hex << std::setw(4) << std::setfill('0') << _service << "."
+ << std::hex << std::setw(4) << std::setfill('0') << _instance << "."
+ << std::hex << std::setw(4) << std::setfill('0') << _eventgroup << "]"
+ << " reliable: " << !!its_reliable_endpoint
+ << " unreliable: " << !!its_unreliable_endpoint;
}
break;
default:
@@ -817,7 +887,6 @@ service_discovery_impl::create_eventgroup_entry(
its_entry->set_counter(0);
its_entry->set_major_version(_subscription->get_major());
its_entry->set_ttl(_subscription->get_ttl());
-
its_data.entry_ = its_entry;
}
@@ -1008,14 +1077,18 @@ service_discovery_impl::on_message(
}
const bool received_via_mcast = (_destination == sd_multicast_address_);
if (received_via_mcast) {
- std::lock_guard<std::mutex> its_lock(last_msg_received_timer_mutex_);
+ static bool must_start_last_msg_received_timer(true);
boost::system::error_code ec;
- last_msg_received_timer_.cancel(ec);
- last_msg_received_timer_.expires_from_now(
- last_msg_received_timer_timeout_, ec);
- last_msg_received_timer_.async_wait(
- std::bind(&service_discovery_impl::on_last_msg_received_timer_expired,
- shared_from_this(), std::placeholders::_1));
+
+ std::lock_guard<std::mutex> its_lock(last_msg_received_timer_mutex_);
+ if (0 < last_msg_received_timer_.cancel(ec) || must_start_last_msg_received_timer) {
+ must_start_last_msg_received_timer = false;
+ last_msg_received_timer_.expires_from_now(
+ last_msg_received_timer_timeout_, ec);
+ last_msg_received_timer_.async_wait(
+ std::bind(&service_discovery_impl::on_last_msg_received_timer_expired,
+ shared_from_this(), std::placeholders::_1));
+ }
}
current_remote_address_ = _sender;
@@ -1256,17 +1329,15 @@ service_discovery_impl::process_serviceentry(
default:
VSOMEIP_ERROR << __func__ << ": Unsupported service entry type";
}
- } else if (!_sd_ac_state.sd_acceptance_required_ || _sd_ac_state.accept_entries_) {
- std::shared_ptr<request> its_request = find_request(its_service, its_instance);
- if (its_request) {
- std::lock_guard<std::mutex> its_lock(requested_mutex_);
- // ID: SIP_SD_830
- its_request->set_sent_counter(std::uint8_t(repetitions_max_ + 1));
- }
+ } else if (its_type != entry_type_e::FIND_SERVICE
+ && (!_sd_ac_state.sd_acceptance_required_ || _sd_ac_state.accept_entries_)) {
+ // stop sending find service in repetition phase
+ update_request(its_service, its_instance);
+
remove_remote_offer_type(its_service, its_instance,
its_reliable_address, its_reliable_port,
its_unreliable_address, its_unreliable_port);
- reset_subscriptions(its_service, its_instance);
+ remove_subscriptions(its_service, its_instance);
if (!is_diagnosis_ && !is_suspended_) {
host_->del_routing_info(its_service, its_instance,
(its_reliable_port != ILLEGAL_PORT),
@@ -1304,11 +1375,9 @@ service_discovery_impl::process_offerservice_serviceentry(
return;
}
- std::shared_ptr<request> its_request = find_request(_service, _instance);
- if (its_request) {
- std::lock_guard<std::mutex> its_lock(requested_mutex_);
- its_request->set_sent_counter(std::uint8_t(repetitions_max_ + 1));
- }
+ // stop sending find service in repetition phase
+ update_request(_service, _instance);
+
remote_offer_type_e offer_type(remote_offer_type_e::UNKNOWN);
if (_reliable_port != ILLEGAL_PORT
&& _unreliable_port != ILLEGAL_PORT
@@ -1430,17 +1499,9 @@ service_discovery_impl::process_offerservice_serviceentry(
}
}
- host_->add_routing_info(_service, _instance,
- _major, _minor,
- _ttl * get_ttl_factor(_service, _instance, ttl_factor_offers_),
- _reliable_address, _reliable_port,
- _unreliable_address, _unreliable_port);
// No need to resubscribe for unicast offers
if (_received_via_mcast) {
- std::int32_t its_remaining = VSOMEIP_MAX_UDP_MESSAGE_SIZE;
- its_remaining -= _resubscribes.back()->get_size();
-
std::lock_guard<std::mutex> its_lock(subscribed_mutex_);
auto found_service = subscribed_.find(_service);
if (found_service != subscribed_.end()) {
@@ -1482,6 +1543,12 @@ service_discovery_impl::process_offerservice_serviceentry(
}
}
}
+
+ host_->add_routing_info(_service, _instance,
+ _major, _minor,
+ _ttl * get_ttl_factor(_service, _instance, ttl_factor_offers_),
+ _reliable_address, _reliable_port,
+ _unreliable_address, _unreliable_port);
}
void
@@ -1616,7 +1683,7 @@ service_discovery_impl::on_endpoint_connected(
its_subscription->set_endpoint(its_reliable, true);
its_subscription->set_endpoint(its_unreliable, false);
- for (const auto& its_client : its_subscription->get_clients())
+ for (const auto its_client : its_subscription->get_clients())
its_subscription->set_state(its_client,
subscription_state_e::ST_NOT_ACKNOWLEDGED);
@@ -1726,7 +1793,7 @@ service_discovery_impl::process_eventgroupentry(
// We received a subscription for a non-existing eventgroup.
// --> Create dummy eventgroupinfo to send Nack.
its_info = std::make_shared<eventgroupinfo>(its_service, its_instance,
- its_eventgroup, its_major, its_ttl);
+ its_eventgroup, its_major, its_ttl, VSOMEIP_DEFAULT_MAX_REMOTE_SUBSCRIBERS);
boost::system::error_code ec;
VSOMEIP_ERROR << __func__
<< ": Received a SubscribeEventGroup entry for unknown eventgroup "
@@ -1743,6 +1810,16 @@ service_discovery_impl::process_eventgroupentry(
// We received a subscription [n]ack for an eventgroup that does not exist.
// --> Remove subscription.
unsubscribe(its_service, its_instance, its_eventgroup, VSOMEIP_ROUTING_CLIENT);
+
+ boost::system::error_code ec;
+ VSOMEIP_WARNING << __func__
+ << ": Received a SubscribeEventGroup[N]Ack entry for unknown eventgroup "
+ << " from: " << its_sender.to_string(ec) << " for: ["
+ << std::hex << std::setw(4) << std::setfill('0') << its_service << "."
+ << std::hex << std::setw(4) << std::setfill('0') << its_instance << "."
+ << std::hex << std::setw(4) << std::setfill('0') << its_eventgroup
+ << "] session: " << std::hex << std::setw(4) << std::setfill('0')
+ << its_session << ", ttl: " << its_ttl;
}
return;
}
@@ -2226,7 +2303,7 @@ service_discovery_impl::handle_eventgroup_subscription(
if (_major != _info->get_major()) {
// Create a temporary info object with TTL=0 --> send NACK
auto its_info = std::make_shared<eventgroupinfo>(_service, _instance,
- _eventgroup, _major, 0);
+ _eventgroup, _major, 0, VSOMEIP_DEFAULT_MAX_REMOTE_SUBSCRIBERS);
boost::system::error_code ec;
// TODO: Add session id
VSOMEIP_ERROR << __func__
@@ -2325,42 +2402,44 @@ service_discovery_impl::handle_eventgroup_subscription(
}
}
- // Create subscription object
- auto its_subscription = std::make_shared<remote_subscription>();
- its_subscription->set_eventgroupinfo(_info);
- its_subscription->set_subscriber(its_subscriber);
- its_subscription->set_reliable(its_reliable);
- its_subscription->set_unreliable(its_unreliable);
- its_subscription->reset(_clients);
+ if (its_subscriber) {
+ // Create subscription object
+ auto its_subscription = std::make_shared<remote_subscription>();
+ its_subscription->set_eventgroupinfo(_info);
+ its_subscription->set_subscriber(its_subscriber);
+ its_subscription->set_reliable(its_reliable);
+ its_subscription->set_unreliable(its_unreliable);
+ its_subscription->reset(_clients);
- if (_ttl == 0) { // --> unsubscribe
- its_subscription->set_ttl(0);
- if (!_is_stop_subscribe_subscribe) {
- {
- std::lock_guard<std::mutex> its_lock(pending_remote_subscriptions_mutex_);
- pending_remote_subscriptions_[its_subscription] = _acknowledgement;
- _acknowledgement->add_subscription(its_subscription);
+ if (_ttl == 0) { // --> unsubscribe
+ its_subscription->set_ttl(0);
+ if (!_is_stop_subscribe_subscribe) {
+ {
+ std::lock_guard<std::mutex> its_lock(pending_remote_subscriptions_mutex_);
+ pending_remote_subscriptions_[its_subscription] = _acknowledgement;
+ _acknowledgement->add_subscription(its_subscription);
+ }
+ host_->on_remote_unsubscribe(its_subscription);
}
- host_->on_remote_unsubscribe(its_subscription);
+ return;
}
- return;
- }
- if (_force_initial_events) {
- its_subscription->set_force_initial_events(true);
- }
- its_subscription->set_ttl(_ttl
- * get_ttl_factor(_service, _instance, ttl_factor_subscriptions_));
+ if (_force_initial_events) {
+ its_subscription->set_force_initial_events(true);
+ }
+ its_subscription->set_ttl(_ttl
+ * get_ttl_factor(_service, _instance, ttl_factor_subscriptions_));
- {
- std::lock_guard<std::mutex> its_lock(pending_remote_subscriptions_mutex_);
- pending_remote_subscriptions_[its_subscription] = _acknowledgement;
- _acknowledgement->add_subscription(its_subscription);
- }
+ {
+ std::lock_guard<std::mutex> its_lock(pending_remote_subscriptions_mutex_);
+ pending_remote_subscriptions_[its_subscription] = _acknowledgement;
+ _acknowledgement->add_subscription(its_subscription);
+ }
- host_->on_remote_subscribe(its_subscription,
- std::bind(&service_discovery_impl::update_remote_subscription,
- shared_from_this(), std::placeholders::_1));
+ host_->on_remote_subscribe(its_subscription,
+ std::bind(&service_discovery_impl::update_remote_subscription,
+ shared_from_this(), std::placeholders::_1));
+ }
}
void
@@ -2380,7 +2459,7 @@ service_discovery_impl::handle_eventgroup_subscription_nack(
for (const auto& its_client : _clients) {
host_->on_subscribe_nack(its_client,
_service, _instance, _eventgroup, ANY_EVENT,
- PENDING_SUBSCRIPTION_ID); // TODO: This is a dummy call...
+ PENDING_SUBSCRIPTION_ID, false); // TODO: This is a dummy call...
}
@@ -3339,6 +3418,7 @@ service_discovery_impl::get_ttl_factor(
void
service_discovery_impl::on_last_msg_received_timer_expired(
const boost::system::error_code &_error) {
+
if (!_error) {
// We didn't receive a multicast message within 110% of the cyclic_offer_delay_
VSOMEIP_WARNING << "Didn't receive a multicast SD message for " <<
@@ -3346,8 +3426,10 @@ service_discovery_impl::on_last_msg_received_timer_expired(
// Rejoin multicast group
if (endpoint_ && !reliable_) {
- dynamic_cast<udp_server_endpoint_impl*>(
- endpoint_.get())->join(sd_multicast_);
+ auto its_endpoint = std::dynamic_pointer_cast<
+ udp_server_endpoint_impl>(endpoint_);
+ if (its_endpoint)
+ its_endpoint->join(sd_multicast_);
}
{
boost::system::error_code ec;
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 23a62aa..b4f63c7 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -2214,6 +2214,15 @@ if(NOT ${TESTS_BAT})
${TEST_LINK_LIBRARIES}
)
+ set(TEST_OFFER_SERVICE_AVAILABILITY_CHECKER ${TEST_OFFER_NAME}_service_availability_checker)
+ add_executable(${TEST_OFFER_SERVICE_AVAILABILITY_CHECKER} offer_tests/${TEST_OFFER_NAME}_service_availability_checker.cpp)
+ target_link_libraries(${TEST_OFFER_SERVICE_AVAILABILITY_CHECKER}
+ vsomeip3
+ ${Boost_LIBRARIES}
+ ${DL_LIBRARY}
+ ${TEST_LINK_LIBRARIES}
+ )
+
set(TEST_OFFER_EXTERNAL_SD_MESSAGE_SENDER ${TEST_OFFER_NAME}_external_sd_msg_sender)
add_executable(${TEST_OFFER_EXTERNAL_SD_MESSAGE_SENDER} offer_tests/${TEST_OFFER_NAME}_external_sd_msg_sender.cpp)
target_link_libraries(${TEST_OFFER_EXTERNAL_SD_MESSAGE_SENDER}
@@ -2318,7 +2327,11 @@ if(NOT ${TESTS_BAT})
${PROJECT_BINARY_DIR}/test/${TEST_OFFER_EXTERNAL_SLAVE_STARTER}
${TEST_OFFER_SERVICE}
)
-
+ set(TEST_OFFER_EXTERNAL_SLAVE_SD_STARTER ${TEST_OFFER_NAME}_external_slave_sd_starter.sh)
+ copy_to_builddir(${PROJECT_SOURCE_DIR}/test/offer_tests/${TEST_OFFER_EXTERNAL_SLAVE_SD_STARTER}
+ ${PROJECT_BINARY_DIR}/test/${TEST_OFFER_EXTERNAL_SLAVE_SD_STARTER}
+ ${TEST_OFFER_SERVICE}
+ )
# Copy starter scripts for external test to $BUILDDIR/test
set(TEST_OFFER_BIG_MASTER_STARTER ${TEST_OFFER_BIG_NAME}_master_starter.sh)
configure_file(
@@ -3073,6 +3086,73 @@ if(NOT ${TESTS_BAT} AND ${TEST_SECOND_ADDRESS})
endif()
##############################################################################
+# suspend resume tests
+##############################################################################
+if(NOT ${TESTS_BAT})
+
+ set(TEST_SUSPEND_RESUME_NAME suspend_resume_test)
+ set(TEST_SUSPEND_RESUME_SERVICE ${TEST_SUSPEND_RESUME_NAME}_service)
+ set(TEST_SUSPEND_RESUME_CLIENT ${TEST_SUSPEND_RESUME_NAME}_client)
+
+ add_executable(${TEST_SUSPEND_RESUME_SERVICE}
+ suspend_resume_tests/${TEST_SUSPEND_RESUME_SERVICE}.cpp
+ )
+ target_link_libraries(${TEST_SUSPEND_RESUME_SERVICE}
+ vsomeip3
+ ${Boost_LIBRARIES}
+ ${DL_LIBRARY}
+ ${TEST_LINK_LIBRARIES}
+ )
+
+ add_executable(${TEST_SUSPEND_RESUME_CLIENT}
+ suspend_resume_tests/${TEST_SUSPEND_RESUME_CLIENT}.cpp
+ )
+ target_link_libraries(${TEST_SUSPEND_RESUME_CLIENT}
+ vsomeip3
+ ${Boost_LIBRARIES}
+ ${DL_LIBRARY}
+ ${TEST_LINK_LIBRARIES}
+ )
+
+ set(TEST_SUSPEND_RESUME_SERVICE_CONFIG_FILE ${TEST_SUSPEND_RESUME_SERVICE}.json)
+ configure_file(
+ ${PROJECT_SOURCE_DIR}/test/suspend_resume_tests/conf/${TEST_SUSPEND_RESUME_SERVICE_CONFIG_FILE}.in
+ ${PROJECT_SOURCE_DIR}/test/suspend_resume_tests/${TEST_SUSPEND_RESUME_SERVICE_CONFIG_FILE}
+ @ONLY)
+ copy_to_builddir(
+ ${PROJECT_SOURCE_DIR}/test/suspend_resume_tests/${TEST_SUSPEND_RESUME_SERVICE_CONFIG_FILE}
+ ${PROJECT_BINARY_DIR}/test/${TEST_SUSPEND_RESUME_SERVICE_CONFIG_FILE}
+ ${TEST_SUSPEND_RESUME_CLIENT}
+ )
+
+ set(TEST_SUSPEND_RESUME_CLIENT_CONFIG_FILE ${TEST_SUSPEND_RESUME_CLIENT}.json)
+ configure_file(
+ ${PROJECT_SOURCE_DIR}/test/suspend_resume_tests/conf/${TEST_SUSPEND_RESUME_CLIENT_CONFIG_FILE}.in
+ ${PROJECT_SOURCE_DIR}/test/suspend_resume_tests/${TEST_SUSPEND_RESUME_CLIENT_CONFIG_FILE}
+ @ONLY)
+ copy_to_builddir(
+ ${PROJECT_SOURCE_DIR}/test/suspend_resume_tests/${TEST_SUSPEND_RESUME_CLIENT_CONFIG_FILE}
+ ${PROJECT_BINARY_DIR}/test/${TEST_SUSPEND_RESUME_CLIENT_CONFIG_FILE}
+ ${TEST_SUSPEND_RESUME_CLIENT}
+ )
+
+ set(TEST_SUSPEND_RESUME_MASTER_START_SCRIPT ${TEST_SUSPEND_RESUME_NAME}_master_starter.sh)
+ copy_to_builddir(
+ ${PROJECT_SOURCE_DIR}/test/suspend_resume_tests/${TEST_SUSPEND_RESUME_MASTER_START_SCRIPT}
+ ${PROJECT_BINARY_DIR}/test/${TEST_SUSPEND_RESUME_MASTER_START_SCRIPT}
+ ${TEST_SUSPEND_RESUME_CLIENT}
+ )
+
+ set(TEST_SUSPEND_RESUME_SLAVE_START_SCRIPT ${TEST_SUSPEND_RESUME_NAME}_slave_starter.sh)
+ copy_to_builddir(
+ ${PROJECT_SOURCE_DIR}/test/suspend_resume_tests/${TEST_SUSPEND_RESUME_SLAVE_START_SCRIPT}
+ ${PROJECT_BINARY_DIR}/test/${TEST_SUSPEND_RESUME_SLAVE_START_SCRIPT}
+ ${TEST_SUSPEND_RESUME_CLIENT}
+ )
+
+endif()
+
+##############################################################################
# Add for every test a dependency to gtest
##############################################################################
@@ -3109,6 +3189,7 @@ if(NOT ${TESTS_BAT})
add_dependencies(${TEST_OFFER_CLIENT} gtest)
add_dependencies(${TEST_OFFER_SERVICE_EXTERNAL} gtest)
add_dependencies(${TEST_OFFER_EXTERNAL_SD_MESSAGE_SENDER} gtest)
+ add_dependencies(${TEST_OFFER_SERVICE_AVAILABILITY_CHECKER} gtest)
add_dependencies(${TEST_OFFERED_SERVICES_INFO_CLIENT} gtest)
add_dependencies(${TEST_OFFERED_SERVICES_INFO_SERVICE} gtest)
add_dependencies(${TEST_PENDING_SUBSCRIPTION_SERVICE} gtest)
@@ -3143,6 +3224,8 @@ if(NOT ${TESTS_BAT})
add_dependencies(${TEST_SECOND_ADDRESS_CLIENT} gtest)
add_dependencies(${TEST_SECOND_ADDRESS_SERVICE} gtest)
endif()
+ add_dependencies(${TEST_SUSPEND_RESUME_CLIENT} gtest)
+ add_dependencies(${TEST_SUSPEND_RESUME_SERVICE} gtest)
else()
add_dependencies(${TEST_LOCAL_ROUTING_SERVICE} gtest)
add_dependencies(${TEST_LOCAL_ROUTING_CLIENT} gtest)
@@ -3185,6 +3268,7 @@ if(NOT ${TESTS_BAT})
add_dependencies(build_tests ${TEST_OFFER_CLIENT})
add_dependencies(build_tests ${TEST_OFFER_SERVICE_EXTERNAL})
add_dependencies(build_tests ${TEST_OFFER_EXTERNAL_SD_MESSAGE_SENDER})
+ add_dependencies(build_tests ${TEST_OFFER_SERVICE_AVAILABILITY_CHECKER})
add_dependencies(build_tests ${TEST_OFFER_BIG_SERVICE})
add_dependencies(build_tests ${TEST_OFFER_BIG_CLIENT})
add_dependencies(build_tests ${TEST_RESTART_ROUTING_SERVICE})
@@ -3202,8 +3286,8 @@ if(NOT ${TESTS_BAT})
add_dependencies(build_tests ${TEST_E2E_SERVICE})
add_dependencies(build_tests ${TEST_E2E_CLIENT})
if (${TEST_E2E_PROFILE_04})
- add_dependencies(build_tests ${TEST_E2E_PROFILE_04_SERVICE})
- add_dependencies(build_tests ${TEST_E2E_PROFILE_04_CLIENT})
+ add_dependencies(build_tests ${TEST_E2E_PROFILE_04_SERVICE})
+ add_dependencies(build_tests ${TEST_E2E_PROFILE_04_CLIENT})
endif()
add_dependencies(build_tests ${TEST_EVENT_SERVICE})
add_dependencies(build_tests ${TEST_EVENT_CLIENT})
@@ -3223,6 +3307,8 @@ if(NOT ${TESTS_BAT})
add_dependencies(build_tests ${TEST_SECOND_ADDRESS_CLIENT})
add_dependencies(build_tests ${TEST_SECOND_ADDRESS_SERVICE})
endif()
+ add_dependencies(build_tests ${TEST_SUSPEND_RESUME_CLIENT})
+ add_dependencies(build_tests ${TEST_SUSPEND_RESUME_SERVICE})
else()
add_dependencies(build_tests ${TEST_LOCAL_ROUTING_SERVICE})
add_dependencies(build_tests ${TEST_LOCAL_ROUTING_CLIENT})
@@ -3574,6 +3660,10 @@ if(NOT ${TESTS_BAT})
COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_INITIAL_EVENT_MASTER_STARTER} ${TEST_INITIAL_EVENT_DIFF_IDS_DIFF_PORTS_MASTER_CONFIG_FILE} TCP_AND_UDP MULTIPLE_EVENTS SUBSCRIBE_ONLY_ONE)
set_tests_properties(${TEST_INITIAL_EVENT_NAME}_multiple_events_diff_client_ids_diff_ports_partial_subscription_both_tcp_and_udp PROPERTIES TIMEOUT 120)
+ add_test(NAME ${TEST_INITIAL_EVENT_NAME}_diff_client_ids_same_ports_udp_client_subscribes_twice
+ COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_INITIAL_EVENT_MASTER_STARTER} ${TEST_INITIAL_EVENT_DIFF_IDS_SAME_PORTS_MASTER_UDP_CONFIG_FILE} UDP CLIENT_SUBSCRIBES_TWICE)
+ set_tests_properties(${TEST_INITIAL_EVENT_NAME}_diff_client_ids_same_ports_udp_client_subscribes_twice PROPERTIES TIMEOUT 120)
+
# offer tests
add_test(NAME ${TEST_OFFER_NAME}_local
COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_OFFER_LOCAL_STARTER})
@@ -3734,6 +3824,13 @@ if(NOT ${TESTS_BAT})
)
set_tests_properties(${TEST_SECOND_ADDRESS_NAME}_second_ip_address_client_udp PROPERTIES TIMEOUT 180)
endif()
+
+ # suspend resume test
+ add_test(NAME ${TEST_SUSPEND_RESUME_NAME}_initial
+ COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_SUSPEND_RESUME_MASTER_START_SCRIPT} SERVICE
+ )
+ set_tests_properties(${TEST_SUSPEND_RESUME_NAME}_initial PROPERTIES TIMEOUT 80)
+
else()
# Routing tests
add_test(NAME ${TEST_LOCAL_ROUTING_NAME}
diff --git a/test/big_payload_tests/big_payload_test_external_starter.sh b/test/big_payload_tests/big_payload_test_external_starter.sh
index aa2f1a5..9db425d 100755
--- a/test/big_payload_tests/big_payload_test_external_starter.sh
+++ b/test/big_payload_tests/big_payload_test_external_starter.sh
@@ -49,6 +49,12 @@ elif [ ! -z "$USE_DOCKER" ]; then
else
docker exec $DOCKER_IMAGE sh -c "cd $DOCKER_TESTS && ./big_payload_test_service_external_start.sh" &
fi
+elif [ ! -z "$JENKINS" ]; then
+ if [[ $# -gt 0 ]]; then
+ ssh -tt -i $PRV_KEY -o StrictHostKeyChecking=no jenkins@$IP_SLAVE "bash -ci \"set -m; cd $WS_ROOT/build/test; ./big_payload_test_service_external_start.sh $1\" >> $WS_ROOT/slave_test_output 2>&1" &
+ else
+ ssh -tt -i $PRV_KEY -o StrictHostKeyChecking=no jenkins@$IP_SLAVE "bash -ci \"set -m; cd $WS_ROOT/build/test; ./big_payload_test_service_external_start.sh \" >> $WS_ROOT/slave_test_output 2>&1" &
+ fi
else
cat <<End-of-message
*******************************************************************************
diff --git a/test/big_payload_tests/big_payload_test_service.cpp b/test/big_payload_tests/big_payload_test_service.cpp
index 89fe838..ab70046 100644
--- a/test/big_payload_tests/big_payload_test_service.cpp
+++ b/test/big_payload_tests/big_payload_test_service.cpp
@@ -86,6 +86,11 @@ void big_payload_test_service::join_offer_thread()
offer_thread_.join();
}
+void big_payload_test_service::detach_offer_thread()
+{
+ offer_thread_.detach();
+}
+
void big_payload_test_service::offer() {
app_->offer_service(service_id_,
big_payload_test::TEST_SERVICE_INSTANCE_ID);
@@ -241,6 +246,8 @@ TEST(someip_big_payload_test, receive_ten_messages_and_send_reply)
if (test_service.init()) {
test_service.start();
test_service.join_offer_thread();
+ } else {
+ test_service.detach_offer_thread();
}
}
diff --git a/test/big_payload_tests/big_payload_test_service.hpp b/test/big_payload_tests/big_payload_test_service.hpp
index fcb5e9e..44af28a 100644
--- a/test/big_payload_tests/big_payload_test_service.hpp
+++ b/test/big_payload_tests/big_payload_test_service.hpp
@@ -29,6 +29,7 @@ public:
void offer();
void stop_offer();
void join_offer_thread();
+ void detach_offer_thread();
void on_state(vsomeip::state_type_e _state);
void on_message(const std::shared_ptr<vsomeip::message> &_request);
void run();
diff --git a/test/client_id_tests/client_id_test_globals.hpp b/test/client_id_tests/client_id_test_globals.hpp
index 52dd069..e4b2cb8 100644
--- a/test/client_id_tests/client_id_test_globals.hpp
+++ b/test/client_id_tests/client_id_test_globals.hpp
@@ -12,19 +12,20 @@ struct service_info {
vsomeip::service_t service_id;
vsomeip::instance_t instance_id;
vsomeip::method_t method_id;
+ vsomeip::client_t offering_client;
};
static constexpr std::array<service_info, 7> service_infos = {{
// placeholder to be consistent w/ client ids, service ids, app names
- { 0xFFFF, 0xFFFF, 0xFFFF },
+ { 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF },
// node 1
- { 0x1000, 0x1, 0x1111 },
- { 0x2000, 0x1, 0x2222 },
- { 0x3000, 0x1, 0x3333 },
+ { 0x1000, 0x1, 0x1111, 0x1111 },
+ { 0x2000, 0x1, 0x2222, 0x2222},
+ { 0x3000, 0x1, 0x3333, 0x3333},
// node 2
- { 0x4000, 0x1, 0x4444 },
- { 0x5000, 0x1, 0x5555 },
- { 0x6000, 0x1, 0x6666 }
+ { 0x4000, 0x1, 0x4444, 0x4444 },
+ { 0x5000, 0x1, 0x5555, 0x5555 },
+ { 0x6000, 0x1, 0x6666, 0x6666 }
}};
static constexpr int messages_to_send = 10;
diff --git a/test/client_id_tests/client_id_test_master_starter.sh b/test/client_id_tests/client_id_test_master_starter.sh
index eea65af..1351fb1 100755
--- a/test/client_id_tests/client_id_test_master_starter.sh
+++ b/test/client_id_tests/client_id_test_master_starter.sh
@@ -45,6 +45,9 @@ if [ ! -z "$USE_LXC_TEST" ]; then
ssh -tt -i $SANDBOX_ROOT_DIR/commonapi_main/lxc-config/.ssh/mgc_lxc/rsa_key_file.pub -o StrictHostKeyChecking=no root@$LXC_TEST_SLAVE_IP "bash -ci \"set -m; cd \\\$SANDBOX_TARGET_DIR/vsomeip_lib/test; ./client_id_test_slave_starter.sh $CLIENT_JSON_FILE\"" &
elif [ ! -z "$USE_DOCKER" ]; then
docker exec $DOCKER_IMAGE sh -c "cd $DOCKER_TESTS && ./client_id_test_slave_starter.sh $CLIENT_JSON_FILE" &
+elif [ ! -z "$JENKINS" ]; then
+ ssh -tt -i $PRV_KEY -o StrictHostKeyChecking=no jenkins@$IP_SLAVE "bash -ci \"set -m; cd $WS_ROOT/build/test; ./client_id_test_slave_starter.sh $CLIENT_JSON_FILE\" >> $WS_ROOT/slave_test_output 2>&1" &
+
else
cat <<End-of-message
*******************************************************************************
diff --git a/test/client_id_tests/client_id_test_service.cpp b/test/client_id_tests/client_id_test_service.cpp
index b9bb0a1..ca2dc57 100644
--- a/test/client_id_tests/client_id_test_service.cpp
+++ b/test/client_id_tests/client_id_test_service.cpp
@@ -30,6 +30,8 @@ public:
stopped_(false),
stop_thread_(std::bind(&client_id_test_service::wait_for_stop, this)) {
if (!app_->init()) {
+ offer_thread_.detach();
+ stop_thread_.detach();
ADD_FAILURE() << "Couldn't initialize application";
return;
}
@@ -59,14 +61,19 @@ public:
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;
+ other_services_received_request_[i.offering_client] = 0;
}
app_->start();
}
~client_id_test_service() {
- offer_thread_.join();
- stop_thread_.join();
+ if (offer_thread_.joinable()) {
+ offer_thread_.join();
+ }
+ if (stop_thread_.joinable()) {
+ stop_thread_.join();
+ }
}
void offer() {
@@ -128,6 +135,13 @@ public:
std::shared_ptr<vsomeip::message> its_response = vsomeip::runtime::get()
->create_response(_message);
app_->send(its_response);
+
+ other_services_received_request_[_message->get_client()]++;
+ if(all_responses_and_requests_received()) {
+ std::lock_guard<std::mutex> its_lock(stop_mutex_);
+ stopped_ = true;
+ stop_condition_.notify_one();
+ }
}
}
@@ -146,11 +160,7 @@ public:
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::pair<vsomeip::service_t,
- vsomeip::method_t>, std::uint32_t>::value_type& v)
- { return v.second == client_id_test::messages_to_send;})) {
+ if(all_responses_and_requests_received()) {
std::lock_guard<std::mutex> its_lock(stop_mutex_);
stopped_ = true;
stop_condition_.notify_one();
@@ -158,6 +168,21 @@ public:
}
}
+ bool all_responses_and_requests_received() {
+ const bool responses = std::all_of(
+ other_services_received_response_.cbegin(),
+ other_services_received_response_.cend(),
+ [](const std::map<std::pair<vsomeip::service_t,
+ vsomeip::method_t>, std::uint32_t>::value_type& v)
+ { return v.second == client_id_test::messages_to_send;});
+ const bool requests = std::all_of(
+ other_services_received_request_.cbegin(),
+ other_services_received_request_.cend(),
+ [](const std::map<vsomeip::client_t, std::uint32_t>::value_type& v)
+ { return v.second == client_id_test::messages_to_send;});
+ return (responses && requests);
+ }
+
void run() {
std::unique_lock<std::mutex> its_lock(mutex_);
while (!blocked_) {
@@ -212,7 +237,7 @@ public:
}
VSOMEIP_INFO << "[" << std::setw(4) << std::setfill('0') << std::hex
<< service_info_.service_id
- << "] Received responses from all other services, going down";
+ << "] Received responses and requests from all other services, going down";
// let offer thread exit
{
@@ -231,6 +256,7 @@ private:
std::shared_ptr<vsomeip::application> app_;
std::map<std::pair<vsomeip::service_t, vsomeip::instance_t>, bool> other_services_available_;
std::map<std::pair<vsomeip::service_t, vsomeip::method_t>, std::uint32_t> other_services_received_response_;
+ std::map<vsomeip::client_t, std::uint32_t> other_services_received_request_;
bool blocked_;
std::mutex mutex_;
diff --git a/test/cpu_load_tests/cpu_load_test_client.cpp b/test/cpu_load_tests/cpu_load_test_client.cpp
index 6cc0571..05c8cf1 100644
--- a/test/cpu_load_tests/cpu_load_test_client.cpp
+++ b/test/cpu_load_tests/cpu_load_test_client.cpp
@@ -314,7 +314,7 @@ static bool call_service_sync(true);
static bool shutdown_service(true);
-TEST(someip_load_test, send_messages_and_measure_cpu_load)
+TEST(someip_load_test, DISABLED_send_messages_and_measure_cpu_load)
{
cpu_load_test_client test_client_(protocol, number_of_calls, payload_size, call_service_sync, shutdown_service);
}
diff --git a/test/cpu_load_tests/cpu_load_test_master_starter.sh b/test/cpu_load_tests/cpu_load_test_master_starter.sh
index d4c96be..138d00e 100755
--- a/test/cpu_load_tests/cpu_load_test_master_starter.sh
+++ b/test/cpu_load_tests/cpu_load_test_master_starter.sh
@@ -22,6 +22,9 @@ if [ ! -z "$USE_LXC_TEST" ]; then
ssh -tt -i $SANDBOX_ROOT_DIR/commonapi_main/lxc-config/.ssh/mgc_lxc/rsa_key_file.pub -o StrictHostKeyChecking=no root@$LXC_TEST_SLAVE_IP 'bash -ci "set -m; cd \$SANDBOX_TARGET_DIR/vsomeip_lib/test; ./cpu_load_test_slave_starter.sh"' &
elif [ ! -z "$USE_DOCKER" ]; then
docker exec $DOCKER_IMAGE sh -c "cd $DOCKER_TESTS && ./cpu_load_test_slave_starter.sh" &
+elif [ ! -z "$JENKINS" ]; then
+ ssh -tt -i $PRV_KEY -o StrictHostKeyChecking=no jenkins@$IP_SLAVE "bash -ci \"set -m; cd $WS_ROOT/build/test; ./cpu_load_test_slave_starter.sh\" >> $WS_ROOT/slave_test_output 2>&1" &
+
else
cat <<End-of-message
*******************************************************************************
diff --git a/test/cpu_load_tests/cpu_load_test_service.cpp b/test/cpu_load_tests/cpu_load_test_service.cpp
index 35e6c1e..6cc7714 100644
--- a/test/cpu_load_tests/cpu_load_test_service.cpp
+++ b/test/cpu_load_tests/cpu_load_test_service.cpp
@@ -192,7 +192,7 @@ private:
};
-TEST(someip_payload_test, send_response_for_every_request)
+TEST(someip_payload_test, DISABLED_send_response_for_every_request)
{
cpu_load_test_service test_service;
if (test_service.init()) {
diff --git a/test/debounce_tests/debounce_test_client.json b/test/debounce_tests/debounce_test_client.json
new file mode 100644
index 0000000..a19c85b
--- /dev/null
+++ b/test/debounce_tests/debounce_test_client.json
@@ -0,0 +1,52 @@
+{
+ "unicast" : "10.0.3.1",
+ "debounce" :
+ [
+ {
+ "service" : "0xb657",
+ "instance" : "0x0003",
+ "events" :
+ [
+ {
+ "event" : "0x8001",
+ "on_change" : "true",
+ "ignore" :
+ [
+ 0, 5
+ ]
+ },
+ {
+ "event" : "0x8002",
+ "on_change" : "true",
+ "ignore" :
+ [
+ 0, 5, 7, 8, 9, 10
+ ]
+ },
+ {
+ "event" : "0x8004",
+ "on_change" : "true",
+ "ignore" :
+ [
+ {
+ "index" : "0",
+ "mask" : "0x0f"
+ },
+ {
+ "index" : "5",
+ "mask" : "0xfe"
+ }
+ ]
+ }
+ ]
+ }
+ ],
+ "service-discovery" :
+ {
+ "enable" : "true",
+ "multicast" : "224.251.192.252",
+ "port" : "30490",
+ "protocol" : "udp",
+ "cyclic_offer_delay" : "1000"
+ }
+}
diff --git a/test/debounce_tests/debounce_test_service.json b/test/debounce_tests/debounce_test_service.json
new file mode 100644
index 0000000..4aeff9c
--- /dev/null
+++ b/test/debounce_tests/debounce_test_service.json
@@ -0,0 +1,19 @@
+{
+ "unicast" : "10.0.3.188",
+ "services" :
+ [
+ {
+ "service" : "0xb657",
+ "instance" : "0x0003",
+ "unreliable" : "30503"
+ }
+ ],
+ "service-discovery" :
+ {
+ "enable" : "true",
+ "multicast" : "224.251.192.252",
+ "port" : "30490",
+ "protocol" : "udp",
+ "cyclic_offer_delay" : "1000"
+ }
+}
diff --git a/test/e2e_tests/e2e_profile_04_test_external_master_start.sh b/test/e2e_tests/e2e_profile_04_test_external_master_start.sh
index ce16d71..f3d6e34 100755
--- a/test/e2e_tests/e2e_profile_04_test_external_master_start.sh
+++ b/test/e2e_tests/e2e_profile_04_test_external_master_start.sh
@@ -33,7 +33,10 @@ if [ ! -z "$USE_LXC_TEST" ]; then
echo "starting external e2e profile 04 test on slave LXC"
ssh -tt -i $SANDBOX_ROOT_DIR/commonapi_main/lxc-config/.ssh/mgc_lxc/rsa_key_file.pub -o StrictHostKeyChecking=no root@$LXC_TEST_SLAVE_IP "bash -ci \"set -m; cd \\\$SANDBOX_TARGET_DIR/vsomeip_lib/test; ./e2e_profile_04_test_external_slave_start.sh $SERVICE_JSON_FILE\"" &
elif [ ! -z "$USE_DOCKER" ]; then
- docker run --name citms --cap-add NET_ADMIN $DOCKER_IMAGE sh -c "route add -net 224.0.0.0/4 dev eth0 && cd $DOCKER_TESTS && ./e2e_profile_04_test_external_slave_start.sh $SERVICE_JSON_FILE" &
+ docker exec $DOCKER_IMAGE sh -c "cd $DOCKER_TESTS && ./e2e_profile_04_test_external_slave_start.sh $SERVICE_JSON_FILE" &
+elif [ ! -z "$JENKINS" ]; then
+ ssh -tt -i $PRV_KEY -o StrictHostKeyChecking=no jenkins@$IP_SLAVE "bash -ci \"set -m; cd $WS_ROOT/build/test; ./e2e_profile_04_test_external_slave_start.sh $SERVICE_JSON_FILE\" >> $WS_ROOT/slave_test_output 2>&1" &
+
else
cat <<End-of-message
*******************************************************************************
@@ -60,11 +63,6 @@ do
fi
done
-if [ ! -z "$USE_DOCKER" ]; then
- docker stop citms
- docker rm citms
-fi
-
kill $PID_CLIENT
# Check if both exited successfully
diff --git a/test/e2e_tests/e2e_profile_04_test_external_slave_start.sh b/test/e2e_tests/e2e_profile_04_test_external_slave_start.sh
index afd692b..17104b8 100755
--- a/test/e2e_tests/e2e_profile_04_test_external_slave_start.sh
+++ b/test/e2e_tests/e2e_profile_04_test_external_slave_start.sh
@@ -34,11 +34,6 @@ do
fi
done
-if [ ! -z "$USE_DOCKER" ]; then
- docker stop citms
- docker rm citms
-fi
-
kill $PID_SERVICE
# Check if both exited successfully
diff --git a/test/e2e_tests/e2e_test_external_master_start.sh b/test/e2e_tests/e2e_test_external_master_start.sh
index 3e54d9b..e787fcb 100755
--- a/test/e2e_tests/e2e_test_external_master_start.sh
+++ b/test/e2e_tests/e2e_test_external_master_start.sh
@@ -33,7 +33,10 @@ if [ ! -z "$USE_LXC_TEST" ]; then
echo "starting external e2e test on slave LXC"
ssh -tt -i $SANDBOX_ROOT_DIR/commonapi_main/lxc-config/.ssh/mgc_lxc/rsa_key_file.pub -o StrictHostKeyChecking=no root@$LXC_TEST_SLAVE_IP "bash -ci \"set -m; cd \\\$SANDBOX_TARGET_DIR/vsomeip_lib/test; ./e2e_test_external_slave_start.sh $SERVICE_JSON_FILE\"" &
elif [ ! -z "$USE_DOCKER" ]; then
- docker run --name citms --cap-add NET_ADMIN $DOCKER_IMAGE sh -c "route add -net 224.0.0.0/4 dev eth0 && cd $DOCKER_TESTS && ./e2e_test_external_slave_start.sh $SERVICE_JSON_FILE" &
+ docker exec $DOCKER_IMAGE sh -c "cd $DOCKER_TESTS && ./e2e_test_external_slave_start.sh $SERVICE_JSON_FILE" &
+elif [ ! -z "$JENKINS" ]; then
+ ssh -tt -i $PRV_KEY -o StrictHostKeyChecking=no jenkins@$IP_SLAVE "bash -ci \"set -m; cd $WS_ROOT/build/test; ./e2e_test_external_slave_start.sh $SERVICE_JSON_FILE\" >> $WS_ROOT/slave_test_output 2>&1" &
+
else
cat <<End-of-message
*******************************************************************************
@@ -60,11 +63,6 @@ do
fi
done
-if [ ! -z "$USE_DOCKER" ]; then
- docker stop citms
- docker rm citms
-fi
-
kill $PID_CLIENT
# Check if both exited successfully
diff --git a/test/e2e_tests/e2e_test_external_slave_start.sh b/test/e2e_tests/e2e_test_external_slave_start.sh
index ccf6fd5..a6855b1 100755
--- a/test/e2e_tests/e2e_test_external_slave_start.sh
+++ b/test/e2e_tests/e2e_test_external_slave_start.sh
@@ -34,11 +34,6 @@ do
fi
done
-if [ ! -z "$USE_DOCKER" ]; then
- docker stop citms
- docker rm citms
-fi
-
kill $PID_SERVICE
# Check if both exited successfully
diff --git a/test/event_tests/event_test_master_starter.sh b/test/event_tests/event_test_master_starter.sh
index 7c2aec0..e00639f 100755
--- a/test/event_tests/event_test_master_starter.sh
+++ b/test/event_tests/event_test_master_starter.sh
@@ -30,7 +30,10 @@ if [ ! -z "$USE_LXC_TEST" ]; then
echo "starting offer test on slave LXC offer_test_external_slave_starter.sh"
ssh -tt -i $SANDBOX_ROOT_DIR/commonapi_main/lxc-config/.ssh/mgc_lxc/rsa_key_file.pub -o StrictHostKeyChecking=no root@$LXC_TEST_SLAVE_IP "bash -ci \"set -m; cd \\\$SANDBOX_TARGET_DIR/vsomeip_lib/test; ./event_test_slave_starter.sh $COMMUNICATIONMODE\"" &
elif [ ! -z "$USE_DOCKER" ]; then
- docker run --name otems --cap-add NET_ADMIN $DOCKER_IMAGE sh -c "route add -net 224.0.0.0/4 dev eth0 && cd $DOCKER_TESTS && sleep 10; ./event_test_slave_starter.sh $COMMUNICATIONMODE" &
+ docker exec $DOCKER_IMAGE sh -c "cd $DOCKER_TESTS && sleep 10; ./event_test_slave_starter.sh $COMMUNICATIONMODE" &
+elif [ ! -z "$JENKINS" ]; then
+ ssh -tt -i $PRV_KEY -o StrictHostKeyChecking=no jenkins@$IP_SLAVE "bash -ci \"set -m; cd $WS_ROOT/build/test; ./event_test_slave_starter.sh $COMMUNICATIONMODE\" >> $WS_ROOT/slave_test_output 2>&1" &
+
else
cat <<End-of-message
*******************************************************************************
@@ -57,10 +60,5 @@ done
kill $PID_VSOMEIPD
sleep 1
-if [ ! -z "$USE_DOCKER" ]; then
- docker stop otems
- docker rm otems
-fi
-
# Check if everything went well
exit $FAIL
diff --git a/test/initial_event_tests/initial_event_test_client.cpp b/test/initial_event_tests/initial_event_test_client.cpp
index bc9d46a..ef215f1 100644
--- a/test/initial_event_tests/initial_event_test_client.cpp
+++ b/test/initial_event_tests/initial_event_test_client.cpp
@@ -36,13 +36,15 @@ public:
bool _subscribe_on_available, std::uint32_t _events_to_subscribe,
bool _initial_event_strict_checking,
bool _dont_exit, bool _subscribe_only_one,
- vsomeip::reliability_type_e _reliability_type) :
+ vsomeip::reliability_type_e _reliability_type,
+ bool _client_subscribes_twice) :
client_number_(_client_number),
service_infos_(_service_infos),
service_offered_tcp_and_udp_(_service_offered_tcp_and_udp),
app_(vsomeip::runtime::get()->create_application()),
wait_until_registered_(true),
wait_for_stop_(true),
+ is_first(true),
subscribe_on_available_(_subscribe_on_available),
events_to_subscribe_(_events_to_subscribe),
initial_event_strict_checking_(_initial_event_strict_checking),
@@ -50,9 +52,11 @@ public:
subscribe_only_one_(_subscribe_only_one),
stop_thread_(&initial_event_test_client::wait_for_stop, this),
wait_for_signal_handler_registration_(true),
- reliability_type_(_reliability_type)
+ reliability_type_(_reliability_type),
+ client_subscribes_twice_(_client_subscribes_twice)
{
if (!app_->init()) {
+ stop_thread_.detach();
ADD_FAILURE() << "Couldn't initialize application";
return;
}
@@ -92,6 +96,8 @@ public:
if (events_to_subscribe_ == 1) {
app_->subscribe(i.service_id, i.instance_id, i.eventgroup_id,
vsomeip::DEFAULT_MAJOR);
+
+ std::lock_guard<std::mutex> its_lock(received_notifications_mutex_);
other_services_received_notification_[std::make_pair(i.service_id, i.event_id)] = 0;
} else if (events_to_subscribe_ > 1) {
if (!subscribe_only_one_) {
@@ -99,6 +105,7 @@ public:
app_->subscribe(i.service_id, i.instance_id, i.eventgroup_id,
vsomeip::DEFAULT_MAJOR,
static_cast<vsomeip::event_t>(i.event_id + j));
+ std::lock_guard<std::mutex> its_lock(received_notifications_mutex_);
other_services_received_notification_[std::make_pair(i.service_id, i.event_id + j)] = 0;
}
} else {
@@ -134,8 +141,12 @@ public:
}
~initial_event_test_client() {
- stop_thread_.join();
- signal_thread_.join();
+ if (stop_thread_.joinable()) {
+ stop_thread_.join();
+ }
+ if (signal_thread_.joinable()) {
+ signal_thread_.join();
+ }
}
void on_state(vsomeip::state_type_e _state) {
@@ -196,33 +207,79 @@ public:
void on_message(const std::shared_ptr<vsomeip::message> &_message) {
if(_message->get_message_type() == vsomeip::message_type_e::MT_NOTIFICATION) {
- other_services_received_notification_[std::make_pair(_message->get_service(),
- _message->get_method())]++;
-
- VSOMEIP_DEBUG << "[" << std::setw(4) << std::setfill('0') << std::hex
- << client_number_ << "] "
- << "Received a notification 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() <<"] (now have: "
- << std::dec << other_services_received_notification_[std::make_pair(_message->get_service(),
- _message->get_method())] << ")";
+ {
+ std::lock_guard<std::mutex> its_lock(received_notifications_mutex_);
+ other_services_received_notification_[std::make_pair(_message->get_service(),
+ _message->get_method())]++;
+ VSOMEIP_DEBUG << "[" << std::setw(4) << std::setfill('0') << std::hex
+ << client_number_ << "] "
+ << "Received a notification 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() <<"] (now have: "
+ << std::dec << other_services_received_notification_[std::make_pair(_message->get_service(),
+ _message->get_method())] << ")";
+ }
std::shared_ptr<vsomeip::payload> its_payload(_message->get_payload());
EXPECT_EQ(2u, its_payload->get_length());
EXPECT_EQ((_message->get_service() & 0xFF00 ) >> 8, its_payload->get_data()[0]);
EXPECT_EQ((_message->get_service() & 0xFF), its_payload->get_data()[1]);
bool notify(false);
- if (!service_offered_tcp_and_udp_) {
- if (all_notifications_received()) {
- notify = true;
+ if (client_subscribes_twice_) {
+ // only relevant for testcase:
+ // initial_event_test_diff_client_ids_same_ports_udp_client_subscribes_twice
+ // check that a second subscribe triggers another initial event
+ // expect notifications_to_send_after_double_subscribe == 2;
+ if (is_first) {
+ std::this_thread::sleep_for(std::chrono::milliseconds(2000));
+ for(const auto& i : service_infos_) {
+ // subscribe again and expect initial events cached at rm::proxy to be received
+ // as configured routing manager only fires the event once after first susbcribe.
+ if (i.service_id == 0xFFFF && i.instance_id == 0xFFFF) {
+ continue;
+ }
+ if (!subscribe_on_available_) {
+ if (events_to_subscribe_ == 1) {
+ app_->subscribe(i.service_id, i.instance_id, i.eventgroup_id,
+ vsomeip::DEFAULT_MAJOR);
+ } else if (events_to_subscribe_ > 1) {
+ if (!subscribe_only_one_) {
+ for (std::uint32_t j = 0; j < events_to_subscribe_; j++ ) {
+ app_->subscribe(i.service_id, i.instance_id, i.eventgroup_id,
+ vsomeip::DEFAULT_MAJOR,
+ static_cast<vsomeip::event_t>(i.event_id + j));
+ }
+ } else {
+ app_->subscribe(i.service_id, i.instance_id, i.eventgroup_id,
+ vsomeip::DEFAULT_MAJOR,
+ static_cast<vsomeip::event_t>(i.event_id));
+ }
+ }
+ }
+ }
+ is_first = false;
+ } else {
+ bool received_initial_event_twice(false);
+ std::lock_guard<std::mutex> its_lock(received_notifications_mutex_);
+ received_initial_event_twice = all_notifications_received_twice();
+ if (received_initial_event_twice) {
+ notify = true;
+ }
}
} else {
- if (all_notifications_received_tcp_and_udp()) {
- notify = true;
+ if (!service_offered_tcp_and_udp_) {
+ std::lock_guard<std::mutex> its_lock(received_notifications_mutex_);
+ if (all_notifications_received()) {
+ notify = true;
+ }
+ } else {
+ if (all_notifications_received_tcp_and_udp()) {
+ notify = true;
+ }
}
}
@@ -277,7 +334,50 @@ public:
);
}
+ bool all_notifications_received_twice() {
+ return std::all_of(
+ other_services_received_notification_.cbegin(),
+ other_services_received_notification_.cend(),
+ [&](const std::map<std::pair<vsomeip::service_t,
+ vsomeip::method_t>, std::uint32_t>::value_type& v)
+ {
+ bool result;
+ if (v.second == initial_event_test::notifications_to_send * 2) {
+ result = true;
+ } else {
+ if (v.second >= initial_event_test::notifications_to_send * 2) {
+ VSOMEIP_WARNING
+ << __func__ << "[" << std::setw(4) << std::setfill('0') << std::hex
+ << client_number_ << "] "
+ << " Received multiple initial events from service/instance: "
+ << std::setw(4) << std::setfill('0') << std::hex << v.first.first
+ << "."
+ << std::setw(4) << std::setfill('0') << std::hex << v.first.second
+ << " number of received events: " << v.second
+ << ". This is caused by StopSubscribe/Subscribe messages and/or"
+ << " service offered via UDP and TCP";
+ if (initial_event_strict_checking_) {
+ ADD_FAILURE() << __func__ << "[" << std::setw(4) << std::setfill('0') << std::hex
+ << client_number_ << "] "
+ << " Received multiple initial events from service/instance: "
+ << std::setw(4) << std::setfill('0') << std::hex << v.first.first
+ << "."
+ << std::setw(4) << std::setfill('0') << std::hex << v.first.second
+ << " number of received events: " << v.second;
+ }
+ result = initial_event_strict_checking_ ? false : true;
+
+ } else {
+ result = false;
+ }
+ }
+ return result;
+ }
+ );
+ }
+
bool all_notifications_received_tcp_and_udp() {
+ std::lock_guard<std::mutex> its_lock(received_notifications_mutex_);
std::uint32_t received_twice(0);
std::uint32_t received_normal(0);
for(const auto &v : other_services_received_notification_) {
@@ -402,6 +502,7 @@ private:
bool service_offered_tcp_and_udp_;
std::shared_ptr<vsomeip::application> app_;
std::map<std::pair<vsomeip::service_t, vsomeip::instance_t>, bool> other_services_available_;
+ std::mutex received_notifications_mutex_;
std::map<std::pair<vsomeip::service_t, vsomeip::method_t>, std::uint32_t> other_services_received_notification_;
bool wait_until_registered_;
@@ -409,6 +510,7 @@ private:
std::condition_variable condition_;
std::atomic<bool> wait_for_stop_;
+ std::atomic<bool> is_first;
bool subscribe_on_available_;
std::uint32_t events_to_subscribe_;
@@ -424,6 +526,7 @@ private:
std::condition_variable signal_condition_;
std::thread signal_thread_;
vsomeip::reliability_type_e reliability_type_;
+ bool client_subscribes_twice_;
};
static int client_number;
@@ -434,6 +537,8 @@ static std::uint32_t subscribe_multiple_events;
static bool initial_event_strict_checking;
static bool dont_exit;
static bool subscribe_only_one;
+static bool client_subscribes_twice;
+
vsomeip::reliability_type_e reliability_type = vsomeip::reliability_type_e::RT_UNKNOWN;
@@ -450,13 +555,15 @@ TEST(someip_initial_event_test, wait_for_initial_events_of_all_services)
subscribe_on_available, subscribe_multiple_events,
initial_event_strict_checking, dont_exit,
subscribe_only_one,
- reliability_type);
+ reliability_type,
+ client_subscribes_twice);
} else {
initial_event_test_client its_sample(client_number, service_offered_tcp_and_udp,
initial_event_test::service_infos, subscribe_on_available,
subscribe_multiple_events, initial_event_strict_checking, dont_exit,
subscribe_only_one,
- reliability_type);
+ reliability_type,
+ client_subscribes_twice);
}
}
@@ -492,6 +599,7 @@ int main(int argc, char** argv)
subscribe_multiple_events = 1;
dont_exit = false;
subscribe_only_one = false;
+ client_subscribes_twice = false;
if (argc > 2) {
for (int i = 2; i < argc; i++) {
if (std::string("SUBSCRIBE_ON_AVAILABILITY") == std::string(argv[i])) {
@@ -518,6 +626,9 @@ int main(int argc, char** argv)
} else if (std::string("TCP_AND_UDP")== std::string(argv[i])) {
reliability_type = vsomeip::reliability_type_e::RT_BOTH;
std::cout << "Using reliability type RT_BOTH" << std::endl;
+ } else if (std::string("CLIENT_SUBSCRIBES_TWICE")== std::string(argv[i])) {
+ client_subscribes_twice = true;
+ std::cout << "Testing for initial event after a second subscribe from same client CLIENT_SUBSCRIBES_TWICE" << std::endl;
}
}
}
diff --git a/test/initial_event_tests/initial_event_test_master_starter.sh b/test/initial_event_tests/initial_event_test_master_starter.sh
index 8848f62..85607c4 100755
--- a/test/initial_event_tests/initial_event_test_master_starter.sh
+++ b/test/initial_event_tests/initial_event_test_master_starter.sh
@@ -31,6 +31,8 @@ if [ ! -z "$USE_LXC_TEST" ]; then
ssh -tt -i $SANDBOX_ROOT_DIR/commonapi_main/lxc-config/.ssh/mgc_lxc/rsa_key_file.pub -o StrictHostKeyChecking=no root@$LXC_TEST_SLAVE_IP "bash -ci \"set -m; cd \\\$SANDBOX_TARGET_DIR/vsomeip_lib/test; ./initial_event_test_slave_starter.sh $CLIENT_JSON_FILE $REMAINING_OPTIONS\"" &
elif [ ! -z "$USE_DOCKER" ]; then
docker exec $DOCKER_IMAGE sh -c "cd $DOCKER_TESTS && ./initial_event_test_slave_starter.sh $CLIENT_JSON_FILE $REMAINING_OPTIONS" &
+elif [ ! -z "$JENKINS" ]; then
+ ssh -tt -i $PRV_KEY -o StrictHostKeyChecking=no jenkins@$IP_SLAVE "bash -ci \"set -m; cd $WS_ROOT/build/test; ./initial_event_test_slave_starter.sh $CLIENT_JSON_FILE $REMAINING_OPTIONS\" >> $WS_ROOT/slave_test_output 2>&1" &
else
cat <<End-of-message
*******************************************************************************
@@ -70,6 +72,8 @@ export VSOMEIP_APPLICATION_NAME=initial_event_test_service_three
./initial_event_test_service 3 $REMAINING_OPTIONS &
PID_SERVICE_THREE=$!
+sleep 3
+
unset VSOMEIP_APPLICATION_NAME
# Array for client pids
@@ -125,9 +129,10 @@ kill $FIRST_PID
wait $FIRST_PID || FAIL=$(($FAIL+1))
# shutdown the services
-kill $PID_SERVICE_THREE
-kill $PID_SERVICE_TWO
-kill $PID_SERVICE_ONE
+kill $PID_SERVICE_THREE $PID_SERVICE_TWO $PID_SERVICE_ONE
+wait $PID_SERVICE_THREE $PID_SERVICE_TWO $PID_SERVICE_ONE
+
+
sleep 1
echo ""
diff --git a/test/initial_event_tests/initial_event_test_service.cpp b/test/initial_event_tests/initial_event_test_service.cpp
index f075ed6..b7d8281 100644
--- a/test/initial_event_tests/initial_event_test_service.cpp
+++ b/test/initial_event_tests/initial_event_test_service.cpp
@@ -31,6 +31,7 @@ public:
offer_thread_(std::bind(&initial_event_test_service::run, this)),
reliability_type_(_reliability_type) {
if (!app_->init()) {
+ offer_thread_.detach();
ADD_FAILURE() << "Couldn't initialize application";
return;
}
@@ -64,7 +65,9 @@ public:
}
~initial_event_test_service() {
- offer_thread_.join();
+ if (offer_thread_.joinable()) {
+ offer_thread_.join();
+ }
}
void offer() {
diff --git a/test/initial_event_tests/initial_event_test_slave_starter.sh b/test/initial_event_tests/initial_event_test_slave_starter.sh
index e240f5a..6f6bd40 100755
--- a/test/initial_event_tests/initial_event_test_slave_starter.sh
+++ b/test/initial_event_tests/initial_event_test_slave_starter.sh
@@ -41,6 +41,8 @@ export VSOMEIP_APPLICATION_NAME=initial_event_test_service_six
./initial_event_test_service 6 $REMAINING_OPTIONS &
PID_SERVICE_SIX=$!
+sleep 3
+
unset VSOMEIP_APPLICATION_NAME
# Array for client pids
@@ -93,7 +95,7 @@ kill $PID_SERVICE_FOUR
sleep 1
echo ""
-# Check if both exited successfully
+# Check if both exited successfully
if [ $FAIL -eq 0 ]
then
exit 0
diff --git a/test/initial_event_tests/initial_event_test_stop_service.cpp b/test/initial_event_tests/initial_event_test_stop_service.cpp
index 83cd34c..465c837 100644
--- a/test/initial_event_tests/initial_event_test_stop_service.cpp
+++ b/test/initial_event_tests/initial_event_test_stop_service.cpp
@@ -35,6 +35,8 @@ public:
stop_thread_(std::bind(&initial_event_test_stop_service::wait_for_stop, this)),
called_other_node_(false) {
if (!app_->init()) {
+ offer_thread_.detach();
+ stop_thread_.detach();
ADD_FAILURE() << "Couldn't initialize application";
return;
}
@@ -72,8 +74,12 @@ public:
}
~initial_event_test_stop_service() {
- offer_thread_.join();
- stop_thread_.join();
+ if (offer_thread_.joinable()) {
+ offer_thread_.join();
+ }
+ if (stop_thread_.joinable()) {
+ stop_thread_.join();
+ }
}
void offer() {
diff --git a/test/magic_cookies_tests/magic_cookies_test_starter.sh b/test/magic_cookies_tests/magic_cookies_test_starter.sh
index c5342fc..d05a371 100755
--- a/test/magic_cookies_tests/magic_cookies_test_starter.sh
+++ b/test/magic_cookies_tests/magic_cookies_test_starter.sh
@@ -20,6 +20,9 @@ if [ ! -z "$USE_LXC_TEST" ]; then
ssh -tt -i $SANDBOX_ROOT_DIR/commonapi_main/lxc-config/.ssh/mgc_lxc/rsa_key_file.pub -o StrictHostKeyChecking=no root@$LXC_TEST_SLAVE_IP "bash -ci \"set -m; cd \\\$SANDBOX_TARGET_DIR/vsomeip_lib/test; ./magic_cookies_test_client_start.sh\"" &
elif [ ! -z "$USE_DOCKER" ]; then
docker exec $DOCKER_IMAGE sh -c "cd $DOCKER_TESTS && ./magic_cookies_test_client_start.sh" &
+elif [ ! -z "$JENKINS" ]; then
+ ssh -tt -i $PRV_KEY -o StrictHostKeyChecking=no jenkins@$IP_SLAVE "bash -ci \"set -m; cd $WS_ROOT/build/test; ./magic_cookies_test_client_start.sh\" >> $WS_ROOT/slave_test_output 2>&1" &
+
else
cat <<End-of-message
*******************************************************************************
diff --git a/test/malicious_data_tests/conf/malicious_data_test_master_starter.sh.in b/test/malicious_data_tests/conf/malicious_data_test_master_starter.sh.in
index 87bb0d4..2b3c59b 100755
--- a/test/malicious_data_tests/conf/malicious_data_test_master_starter.sh.in
+++ b/test/malicious_data_tests/conf/malicious_data_test_master_starter.sh.in
@@ -42,6 +42,10 @@ elif [ ! -z "$USE_DOCKER" ]; then
echo "Waiting for 5s"
sleep 5
docker exec $DOCKER_IMAGE sh -c "cd $DOCKER_TESTS && sleep 10; ./malicious_data_test_msg_sender @TEST_IP_MASTER@ @TEST_IP_SLAVE@ $TESTMODE" &
+elif [ ! -z "$JENKINS" ]; then
+ echo "Waiting for 5s"
+ sleep 5
+ ssh -tt -i $PRV_KEY -o StrictHostKeyChecking=no jenkins@$IP_SLAVE "bash -ci \"set -m; cd $WS_ROOT/build/test; ./malicious_data_test_msg_sender @TEST_IP_MASTER@ @TEST_IP_SLAVE@ $TESTMODE\" >> $WS_ROOT/slave_test_output 2>&1" &
else
cat <<End-of-message
*******************************************************************************
diff --git a/test/npdu_tests/npdu_test_starter.sh b/test/npdu_tests/npdu_test_starter.sh
index 2e88be6..c405adc 100755
--- a/test/npdu_tests/npdu_test_starter.sh
+++ b/test/npdu_tests/npdu_test_starter.sh
@@ -74,6 +74,10 @@ if [ ! -z "$USE_LXC_TEST" ]; then
ssh -tt -i $SANDBOX_ROOT_DIR/commonapi_main/lxc-config/.ssh/mgc_lxc/rsa_key_file.pub -o StrictHostKeyChecking=no root@$LXC_TEST_SLAVE_IP "bash -ci \"set -m; cd \\\$SANDBOX_TARGET_DIR/vsomeip_lib/test; ./npdu_test_client_npdu_start.sh $*\"" &
elif [ ! -z "$USE_DOCKER" ]; then
docker exec $DOCKER_IMAGE sh -c "cd $DOCKER_TESTS && ./npdu_test_client_npdu_start.sh $*" &
+elif [ ! -z "$JENKINS" ]; then
+ echo "starting npdu_test on slave Docker"
+ ssh -tt -i $PRV_KEY -o StrictHostKeyChecking=no jenkins@$IP_SLAVE "bash -ci \"set -m; cd $WS_ROOT/build/test; ./npdu_test_client_npdu_start.sh $*\" >> $WS_ROOT/slave_test_output 2>&1" &
+
else
sleep 1
cat <<End-of-message
diff --git a/test/offer_tests/conf/offer_test_big_sd_msg_master_starter.sh.in b/test/offer_tests/conf/offer_test_big_sd_msg_master_starter.sh.in
index 07d4079..53f6a2c 100755
--- a/test/offer_tests/conf/offer_test_big_sd_msg_master_starter.sh.in
+++ b/test/offer_tests/conf/offer_test_big_sd_msg_master_starter.sh.in
@@ -33,6 +33,10 @@ elif [ ! -z "$USE_DOCKER" ]; then
echo "Waiting for 5s"
sleep 5
docker exec $DOCKER_IMAGE sh -c "cd $DOCKER_TESTS && sleep 10; ./offer_test_big_sd_msg_slave_starter.sh" &
+elif [ ! -z "$JENKINS" ]; then
+ echo "Waiting for 5s"
+ sleep 5
+ ssh -tt -i $PRV_KEY -o StrictHostKeyChecking=no jenkins@$IP_SLAVE "bash -ci \"set -m; cd $WS_ROOT/build/test; ./offer_test_big_sd_msg_slave_starter.sh\" >> $WS_ROOT/slave_test_output 2>&1" &
else
cat <<End-of-message
*******************************************************************************
diff --git a/test/offer_tests/conf/offer_test_external_master_starter.sh.in b/test/offer_tests/conf/offer_test_external_master_starter.sh.in
index 272689a..2a27a3f 100755
--- a/test/offer_tests/conf/offer_test_external_master_starter.sh.in
+++ b/test/offer_tests/conf/offer_test_external_master_starter.sh.in
@@ -34,18 +34,20 @@ echo "SERVICE_TWO pid $PID_SERVICE_TWO"
CLIENT_PIDS+=($!)
echo "client pid ${CLIENT_PIDS[0]}"
-sleep 1
+# Wait until all clients are finished
+for job in ${CLIENT_PIDS[*]}
+do
+ # Fail gets incremented if a client exits with a non-zero exit code
+ wait $job || FAIL=$(($FAIL+1))
+done
if [ ! -z "$USE_LXC_TEST" ]; then
- echo "Waiting for 5s"
- sleep 5
echo "starting offer test on slave LXC offer_test_external_slave_starter.sh"
ssh -tt -i $SANDBOX_ROOT_DIR/commonapi_main/lxc-config/.ssh/mgc_lxc/rsa_key_file.pub -o StrictHostKeyChecking=no root@$LXC_TEST_SLAVE_IP "bash -ci \"set -m; cd \\\$SANDBOX_TARGET_DIR/vsomeip_lib/test; ./offer_test_external_slave_starter.sh\"" &
- echo "remote ssh pid: $!"
elif [ ! -z "$USE_DOCKER" ]; then
- echo "Waiting for 5s"
- sleep 5
- docker exec $DOCKER_IMAGE sh -c "cd $DOCKER_TESTS && sleep 10; ./offer_test_external_slave_starter.sh" &
+ docker exec $DOCKER_IMAGE sh -c "cd $DOCKER_TESTS; ./offer_test_external_slave_starter.sh" &
+elif [ ! -z "$JENKINS" ]; then
+ ssh -tt -i $PRV_KEY -o StrictHostKeyChecking=no jenkins@$IP_SLAVE "bash -ci \"set -m; cd $WS_ROOT/build/test ; ./offer_test_external_slave_starter.sh\" >> $WS_ROOT/slave_test_output 2>&1" &
else
cat <<End-of-message
*******************************************************************************
@@ -101,19 +103,22 @@ PID_SERVICE_TWO=$!
./offer_test_client SUBSCRIBE &
CLIENT_PIDS+=($!)
echo "client pid ${CLIENT_PIDS[0]}"
+# Wait until all clients and services are finished
+for job in ${CLIENT_PIDS[*]}
+do
+ # Fail gets incremented if a client exits with a non-zero exit code
+ wait $job || FAIL=$(($FAIL+1))
+done
-sleep 1
if [ ! -z "$USE_LXC_TEST" ]; then
- echo "Waiting for 5s"
- sleep 5
echo "starting offer test on slave LXC offer_test_external_sd_msg_sender"
- ssh -tt -i $SANDBOX_ROOT_DIR/commonapi_main/lxc-config/.ssh/mgc_lxc/rsa_key_file.pub -o StrictHostKeyChecking=no root@$LXC_TEST_SLAVE_IP "bash -ci \"set -m; cd \\\$SANDBOX_TARGET_DIR/vsomeip_lib/test; ./offer_test_external_sd_msg_sender $LXC_TEST_MASTER_IP\"" &
+ ssh -tt -i $SANDBOX_ROOT_DIR/commonapi_main/lxc-config/.ssh/mgc_lxc/rsa_key_file.pub -o StrictHostKeyChecking=no root@$LXC_TEST_SLAVE_IP "bash -ci \"set -m; cd \\\$SANDBOX_TARGET_DIR/vsomeip_lib/test; ./offer_test_external_slave_sd_starter.sh $LXC_TEST_MASTER_IP\"" &
echo "remote ssh job id: $!"
elif [ ! -z "$USE_DOCKER" ]; then
- echo "Waiting for 5s"
- sleep 5
- docker exec $DOCKER_IMAGE sh -c "cd $DOCKER_TESTS && sleep 10; ./offer_test_external_sd_msg_sender $DOCKER_IP" &
+ docker exec $DOCKER_IMAGE sh -c "cd $DOCKER_TESTS; ./offer_test_external_slave_sd_starter.sh $DOCKER_IP" &
+elif [ ! -z "$JENKINS" ]; then
+ ssh -tt -i $PRV_KEY -o StrictHostKeyChecking=no jenkins@$IP_SLAVE "bash -ci \"set -m; cd $WS_ROOT/build/test; ./offer_test_external_slave_sd_starter.sh @TEST_IP_MASTER@ \" >> $WS_ROOT/slave_test_output 2>&1" &
else
cat <<End-of-message
*******************************************************************************
@@ -138,7 +143,6 @@ done
# kill the services
kill $PID_VSOMEIPD
-sleep 1
# wait for slave to finish
for job in $(jobs -p)
diff --git a/test/offer_tests/offer_test_external_sd_msg_sender.cpp b/test/offer_tests/offer_test_external_sd_msg_sender.cpp
index 6849b95..cc75b8d 100644
--- a/test/offer_tests/offer_test_external_sd_msg_sender.cpp
+++ b/test/offer_tests/offer_test_external_sd_msg_sender.cpp
@@ -15,11 +15,26 @@ TEST(someip_offer_test, send_offer_service_sd_message)
{
try {
boost::asio::io_service io;
+ boost::system::error_code ec;
boost::asio::ip::udp::socket::endpoint_type target_sd(
boost::asio::ip::address::from_string(std::string(passed_address)),
30490);
- boost::asio::ip::udp::socket udp_socket(io,
- boost::asio::ip::udp::endpoint(boost::asio::ip::udp::v4(), 30490));
+
+ boost::asio::ip::udp::socket udp_socket(io);
+
+ boost::asio::ip::udp::endpoint rx_endpoint_(boost::asio::ip::udp::v4(), 30490);
+ udp_socket.open(rx_endpoint_.protocol(), ec);
+
+ if(ec)
+ std::cout <<" udp_socket open create error "<<std::endl;
+
+ boost::asio::socket_base::reuse_address optionReuseAddress(true);
+ udp_socket.set_option(optionReuseAddress, ec);
+ udp_socket.bind(boost::asio::ip::udp::endpoint(boost::asio::ip::udp::v4(), 30490), ec);
+ if(ec)
+ std::cout <<" udp_socket BIND error "<<std::endl;
+
+ boost::asio::detail::throw_error(ec);
std::uint8_t its_offer_service_message[] = {
0xff, 0xff, 0x81, 0x00,
0x00, 0x00, 0x00, 0x3c,
@@ -39,6 +54,7 @@ TEST(someip_offer_test, send_offer_service_sd_message)
0x0a, 0x00, 0x03, 0x7D, // slave address
0x00, 0x11, 0x75, 0x31
};
+
for (int var = 0; var < 15; ++var) {
udp_socket.send_to(boost::asio::buffer(its_offer_service_message), target_sd);
++its_offer_service_message[11];
@@ -53,8 +69,10 @@ TEST(someip_offer_test, send_offer_service_sd_message)
boost::asio::ip::udp::socket::endpoint_type target_service(
boost::asio::ip::address::from_string(std::string(passed_address)),
30001);
+
udp_socket.send_to(boost::asio::buffer(shutdown_call), target_service);
- } catch (...) {
+ } catch (const std::exception& e) {
+ std::cout << e.what() << std::endl;
ASSERT_FALSE(true);
}
}
diff --git a/test/offer_tests/offer_test_external_slave_sd_starter.sh b/test/offer_tests/offer_test_external_slave_sd_starter.sh
new file mode 100755
index 0000000..8e30086
--- /dev/null
+++ b/test/offer_tests/offer_test_external_slave_sd_starter.sh
@@ -0,0 +1,38 @@
+#!/bin/bash
+# Copyright (C) 2015-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+FAIL=0
+# Rejecting offer for which there is already a remote offer:
+# * start daemon
+# * start application which offers service
+# * start daemon remotely
+# * start same application which offers the same service again remotely
+# -> should be rejected as there is already a service instance
+# running in the network
+
+export VSOMEIP_CONFIGURATION=offer_test_external_slave.json
+# start daemon
+../examples/routingmanagerd/./routingmanagerd &
+PID_VSOMEIPD=$!
+
+echo "calling availabiliy checker"
+
+./offer_test_service_availability_checker &
+
+PID_AVAILABILITY_CHECKER=$!
+
+echo "waiting for offer_test_service_availability_checker"
+
+# wait until the services on the remote node were started as well
+wait $PID_AVAILABILITY_CHECKER
+
+# kill the routing manager services
+kill $PID_VSOMEIPD
+
+./offer_test_external_sd_msg_sender $1 &
+
+
+
diff --git a/test/offer_tests/offer_test_service_availability_checker.cpp b/test/offer_tests/offer_test_service_availability_checker.cpp
new file mode 100644
index 0000000..3cef64f
--- /dev/null
+++ b/test/offer_tests/offer_test_service_availability_checker.cpp
@@ -0,0 +1,118 @@
+// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <chrono>
+#include <condition_variable>
+#include <iomanip>
+#include <iostream>
+#include <sstream>
+#include <thread>
+#include <map>
+#include <algorithm>
+
+#include <gtest/gtest.h>
+
+#include <vsomeip/vsomeip.hpp>
+#include <vsomeip/internal/logger.hpp>
+
+#include "offer_test_globals.hpp"
+
+
+class offer_test_service_availability_checker {
+public:
+ offer_test_service_availability_checker(struct offer_test::service_info _service_info) :
+ service_info_(_service_info),
+ app_(vsomeip::runtime::get()->create_application()),
+ wait_until_registered_(true),
+ wait_for_stop_(true),
+ stop_thread_(std::bind(&offer_test_service_availability_checker::wait_for_stop, this)) {
+ if (!app_->init()) {
+ ADD_FAILURE() << "Couldn't initialize application";
+ return;
+ }
+ app_->register_state_handler(
+ std::bind(&offer_test_service_availability_checker::on_state, this,
+ std::placeholders::_1));
+
+ // register availability for all other services and request their event.
+ app_->register_availability_handler(service_info_.service_id,
+ service_info_.instance_id,
+ std::bind(&offer_test_service_availability_checker::on_availability, this,
+ std::placeholders::_1, std::placeholders::_2,
+ std::placeholders::_3));
+ app_->request_service(service_info_.service_id,
+ service_info_.instance_id);
+
+ app_->start();
+ }
+
+ ~offer_test_service_availability_checker() {
+ stop_thread_.join();
+ }
+
+ void on_state(vsomeip::state_type_e _state) {
+ VSOMEIP_INFO << "MY Application " << app_->get_name() << " is "
+ << (_state == vsomeip::state_type_e::ST_REGISTERED ?
+ "registered." : "deregistered.");
+
+ if (_state == vsomeip::state_type_e::ST_REGISTERED) {
+ std::lock_guard<std::mutex> its_lock(mutex_);
+ wait_until_registered_ = false;
+ condition_.notify_one();
+ }
+ }
+
+ void on_availability(vsomeip::service_t _service,
+ vsomeip::instance_t _instance, bool _is_available) {
+ VSOMEIP_INFO << "MY Service [" << std::setw(4)
+ << std::setfill('0') << std::hex << _service << "." << _instance
+ << "] is " << (_is_available ? "available":"not available") << ".";
+ std::lock_guard<std::mutex> its_lock(mutex_);
+ if(_is_available) {
+ wait_for_stop_ = false;
+ stop_condition_.notify_one();
+ }
+ }
+
+ void wait_for_stop() {
+ VSOMEIP_INFO << " MY offer_test_service_availability_check wait_for_stop() ";
+ std::unique_lock<std::mutex> its_lock(stop_mutex_);
+ while (wait_for_stop_) {
+ stop_condition_.wait(its_lock);
+ }
+ //VSOMEIP_INFO << "[" << std::setw(4) << std::setfill('0') << std::hex
+ // << client_number_ << "] all services are available. Going down";
+ VSOMEIP_INFO << " MY offer_test_service_availability_check is going down ";
+ app_->clear_all_handler();
+ app_->stop();
+ }
+
+private:
+ struct offer_test::service_info service_info_;
+ std::shared_ptr<vsomeip::application> app_;
+
+ bool wait_until_registered_;
+ std::mutex mutex_;
+ std::condition_variable condition_;
+
+ bool wait_for_stop_;
+ std::mutex stop_mutex_;
+ std::condition_variable stop_condition_;
+ std::thread stop_thread_;
+};
+
+TEST(someip_offer_test_external, wait_for_availability_and_exit)
+{
+ offer_test_service_availability_checker its_sample(
+ offer_test::service);
+}
+
+#ifndef _WIN32
+int main(int argc, char** argv)
+{
+ ::testing::InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
+}
+#endif
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 97d195a..f6c2744 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
@@ -62,6 +62,9 @@ if [ ! -z "$USE_LXC_TEST" ]; then
echo "remote ssh job id: $!"
elif [ ! -z "$USE_DOCKER" ]; then
docker exec $DOCKER_IMAGE sh -c "cd $DOCKER_TESTS && ./external_local_payload_test_client_external_start.sh" &
+elif [ ! -z "$JENKINS" ]; then
+ ssh -tt -i $PRV_KEY -o StrictHostKeyChecking=no jenkins@$IP_SLAVE "bash -ci \"set -m; cd $WS_ROOT/build/test; ./external_local_payload_test_client_external_start.sh\" >> $WS_ROOT/slave_test_output 2>&1" &
+
else
cat <<End-of-message
*******************************************************************************
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 b1dd78d..dda58ce 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
@@ -79,6 +79,9 @@ if [ ! -z "$USE_LXC_TEST" ]; then
echo "remote ssh job id: $!"
elif [ ! -z "$USE_DOCKER" ]; then
docker exec $DOCKER_IMAGE sh -c "cd $DOCKER_TESTS && ./external_local_payload_test_client_external_start.sh" &
+elif [ ! -z "$JENKINS" ]; then
+ ssh -tt -i $PRV_KEY -o StrictHostKeyChecking=no jenkins@$IP_SLAVE "bash -ci \"set -m; cd $WS_ROOT/build/test; ./external_local_payload_test_client_external_start.sh\" >> $WS_ROOT/slave_test_output 2>&1" &
+
else
cat <<End-of-message
*******************************************************************************
diff --git a/test/pending_subscription_tests/conf/pending_subscription_test_master_starter.sh.in b/test/pending_subscription_tests/conf/pending_subscription_test_master_starter.sh.in
index a43e3c4..298a3ea 100755
--- a/test/pending_subscription_tests/conf/pending_subscription_test_master_starter.sh.in
+++ b/test/pending_subscription_tests/conf/pending_subscription_test_master_starter.sh.in
@@ -41,6 +41,9 @@ elif [ ! -z "$USE_DOCKER" ]; then
echo "Waiting for 5s"
sleep 5
docker exec $DOCKER_IMAGE sh -c "cd $DOCKER_TESTS && ./pending_subscription_test_sd_msg_sender @TEST_IP_MASTER@ @TEST_IP_SLAVE@ $TESTMODE" &
+elif [ ! -z "$JENKINS" ]; then
+ ssh -tt -i $PRV_KEY -o StrictHostKeyChecking=no jenkins@$IP_SLAVE "bash -ci \"set -m; cd $WS_ROOT/build/test; ./pending_subscription_test_sd_msg_sender @TEST_IP_MASTER@ @TEST_IP_SLAVE@ $TESTMODE\" >> $WS_ROOT/slave_test_output 2>&1" &
+
else
cat <<End-of-message
*******************************************************************************
diff --git a/test/routing_tests/external_local_routing_test_starter.sh b/test/routing_tests/external_local_routing_test_starter.sh
index f8fa2df..7b3d37b 100755
--- a/test/routing_tests/external_local_routing_test_starter.sh
+++ b/test/routing_tests/external_local_routing_test_starter.sh
@@ -82,6 +82,9 @@ then
echo "remote ssh job id: $!"
elif [ ! -z "$USE_DOCKER" ]; then
docker exec $DOCKER_IMAGE sh -c "cd $DOCKER_TESTS && ./external_local_routing_test_client_external_start.sh" &
+ elif [ ! -z "$JENKINS" ]; then
+ ssh -tt -i $PRV_KEY -o StrictHostKeyChecking=no jenkins@$IP_SLAVE "bash -ci \"set -m; cd $WS_ROOT/build/test; ./external_local_routing_test_client_external_start.sh\" >> $WS_ROOT/slave_test_output 2>&1" &
+
else
cat <<End-of-message
*******************************************************************************
diff --git a/test/second_address_tests/second_address_test_master_starter.sh b/test/second_address_tests/second_address_test_master_starter.sh
index a7bcc0a..c68c0b5 100755
--- a/test/second_address_tests/second_address_test_master_starter.sh
+++ b/test/second_address_tests/second_address_test_master_starter.sh
@@ -47,6 +47,9 @@ if [ ! -z "$USE_LXC_TEST" ]; then
ssh -tt -i $SANDBOX_ROOT_DIR/commonapi_main/lxc-config/.ssh/mgc_lxc/rsa_key_file.pub -o StrictHostKeyChecking=no root@$LXC_TEST_SLAVE_IP "bash -ci \"set -m; cd \\\$SANDBOX_TARGET_DIR/vsomeip_lib/test; ./second_address_test_slave_starter.sh $SLAVE_OPERATIONMODE $COMMUNICATIONMODE\"" &
elif [ ! -z "$USE_DOCKER" ]; then
docker exec $DOCKER_IMAGE sh -c "cd $DOCKER_TESTS; sleep 10; ./second_address_test_slave_starter.sh $SLAVE_OPERATIONMODE $COMMUNICATIONMODE" &
+elif [ ! -z "$JENKINS" ]; then
+ ssh -tt -i $PRV_KEY -o StrictHostKeyChecking=no jenkins@$IP_SLAVE "bash -ci \"set -m; cd $WS_ROOT/build/test; ./second_address_test_slave_starter.sh $SLAVE_OPERATIONMODE $COMMUNICATIONMODE\" >> $WS_ROOT/slave_test_output 2>&1" &
+
else
cat <<End-of-message
*******************************************************************************
diff --git a/test/security_tests/security_test_external_master_start.sh b/test/security_tests/security_test_external_master_start.sh
index 75d8667..dc41b8c 100755
--- a/test/security_tests/security_test_external_master_start.sh
+++ b/test/security_tests/security_test_external_master_start.sh
@@ -39,7 +39,10 @@ if [ ! -z "$USE_LXC_TEST" ]; then
echo "starting external security test on slave LXC"
ssh -tt -i $SANDBOX_ROOT_DIR/commonapi_main/lxc-config/.ssh/mgc_lxc/rsa_key_file.pub -o StrictHostKeyChecking=no root@$LXC_TEST_SLAVE_IP "bash -ci \"set -m; cd \\\$SANDBOX_TARGET_DIR/vsomeip_lib/test; ./security_test_external_slave_start.sh $SERVICE_JSON_FILE $2\"" &
elif [ ! -z "$USE_DOCKER" ]; then
- docker run --name citms --cap-add NET_ADMIN $DOCKER_IMAGE sh -c "route add -net 224.0.0.0/4 dev eth0 && cd $DOCKER_TESTS && ./security_test_external_slave_start.sh $SERVICE_JSON_FILE $2" &
+ docker exec $DOCKER_IMAGE sh -c "cd $DOCKER_TESTS && ./security_test_external_slave_start.sh $SERVICE_JSON_FILE $2" &
+elif [ ! -z "$JENKINS" ]; then
+ ssh -tt -i $PRV_KEY -o StrictHostKeyChecking=no jenkins@$IP_SLAVE "bash -ci \"set -m; cd $WS_ROOT/build/test; ./security_test_external_slave_start.sh $SERVICE_JSON_FILE $2\" >> $WS_ROOT/slave_test_output 2>&1" &
+
else
cat <<End-of-message
*******************************************************************************
@@ -66,11 +69,6 @@ do
fi
done
-if [ ! -z "$USE_DOCKER" ]; then
- docker stop citms
- docker rm citms
-fi
-
kill $PID_VSOMEIPD
kill $PID_CLIENT
diff --git a/test/security_tests/security_test_external_slave_start.sh b/test/security_tests/security_test_external_slave_start.sh
index 41b6251..96f578f 100755
--- a/test/security_tests/security_test_external_slave_start.sh
+++ b/test/security_tests/security_test_external_slave_start.sh
@@ -43,11 +43,6 @@ do
fi
done
-if [ ! -z "$USE_DOCKER" ]; then
- docker stop citms
- docker rm citms
-fi
-
kill $PID_VSOMEIPD
kill $PID_SERVICE
diff --git a/test/someip_tp_tests/conf/someip_tp_test_master_starter.sh.in b/test/someip_tp_tests/conf/someip_tp_test_master_starter.sh.in
index c01feea..56e3ddf 100755
--- a/test/someip_tp_tests/conf/someip_tp_test_master_starter.sh.in
+++ b/test/someip_tp_tests/conf/someip_tp_test_master_starter.sh.in
@@ -34,6 +34,10 @@ elif [ ! -z "$USE_DOCKER" ]; then
echo "Waiting for 5s"
sleep 5
docker exec $DOCKER_IMAGE sh -c "cd $DOCKER_TESTS && ./someip_tp_test_msg_sender @TEST_IP_MASTER@ @TEST_IP_SLAVE@ $TESTMODE" &
+elif [ ! -z "$JENKINS" ]; then
+ echo "Waiting for 5s"
+ sleep 5
+ ssh -tt -i $PRV_KEY -o StrictHostKeyChecking=no jenkins@$IP_SLAVE "bash -ci \"set -m; cd $WS_ROOT/build/test; ./someip_tp_test_msg_sender @TEST_IP_MASTER@ @TEST_IP_SLAVE@ $TESTMODE\" >> $WS_ROOT/slave_test_output 2>&1" &
else
cat <<End-of-message
*******************************************************************************
diff --git a/test/subscribe_notify_one_tests/subscribe_notify_one_test_master_starter.sh b/test/subscribe_notify_one_tests/subscribe_notify_one_test_master_starter.sh
index 75e948e..a53104f 100755
--- a/test/subscribe_notify_one_tests/subscribe_notify_one_test_master_starter.sh
+++ b/test/subscribe_notify_one_tests/subscribe_notify_one_test_master_starter.sh
@@ -38,7 +38,7 @@ export VSOMEIP_APPLICATION_NAME=subscribe_notify_one_test_service_three
export VSOMEIP_CONFIGURATION=$MASTER_JSON_FILE
./subscribe_notify_one_test_service 3 $RELIABILITY_TYPE &
-sleep 1
+sleep 3
if [ ! -z "$USE_LXC_TEST" ]; then
echo "starting subscribe_notify_one_test_slave_starter.sh on slave LXC with parameters $CLIENT_JSON_FILE"
@@ -46,6 +46,9 @@ if [ ! -z "$USE_LXC_TEST" ]; then
echo "remote ssh job id: $!"
elif [ ! -z "$USE_DOCKER" ]; then
docker exec $DOCKER_IMAGE sh -c "cd $DOCKER_TESTS && ./subscribe_notify_one_test_slave_starter.sh $RELIABILITY_TYPE $CLIENT_JSON_FILE" &
+elif [ ! -z "$JENKINS" ]; then
+ ssh -tt -i $PRV_KEY -o StrictHostKeyChecking=no jenkins@$IP_SLAVE "bash -ci \"set -m; cd $WS_ROOT/build/test; ./subscribe_notify_one_test_slave_starter.sh $RELIABILITY_TYPE $CLIENT_JSON_FILE\" >> $WS_ROOT/slave_test_output 2>&1" &
+
else
cat <<End-of-message
*******************************************************************************
diff --git a/test/subscribe_notify_one_tests/subscribe_notify_one_test_slave_starter.sh b/test/subscribe_notify_one_tests/subscribe_notify_one_test_slave_starter.sh
index e41852c..830484d 100755
--- a/test/subscribe_notify_one_tests/subscribe_notify_one_test_slave_starter.sh
+++ b/test/subscribe_notify_one_tests/subscribe_notify_one_test_slave_starter.sh
@@ -31,6 +31,8 @@ export VSOMEIP_APPLICATION_NAME=subscribe_notify_one_test_service_six
export VSOMEIP_CONFIGURATION=$2
./subscribe_notify_one_test_service 6 $1 &
+sleep 3
+
# Wait until all applications are finished
for job in $(jobs -p)
do
@@ -39,7 +41,7 @@ do
wait $job || ((FAIL+=1))
done
-# Check if both exited successfully
+# Check if both exited successfully
if [ $FAIL -eq 0 ]
then
exit 0
diff --git a/test/subscribe_notify_tests/conf/subscribe_notify_test_one_event_two_eventgroups_master.json.in b/test/subscribe_notify_tests/conf/subscribe_notify_test_one_event_two_eventgroups_master.json.in
index d0ce9cc..88d5ec9 100644
--- a/test/subscribe_notify_tests/conf/subscribe_notify_test_one_event_two_eventgroups_master.json.in
+++ b/test/subscribe_notify_tests/conf/subscribe_notify_test_one_event_two_eventgroups_master.json.in
@@ -2,7 +2,7 @@
"unicast" : "@TEST_IP_MASTER@",
"logging" :
{
- "level" : "debug",
+ "level" : "warning",
"console" : "true",
"file" : { "enable" : "false", "path" : "/var/log/vsomeip.log" },
"dlt" : "false"
diff --git a/test/subscribe_notify_tests/conf/subscribe_notify_test_one_event_two_eventgroups_tcp_slave.json.in b/test/subscribe_notify_tests/conf/subscribe_notify_test_one_event_two_eventgroups_tcp_slave.json.in
index 318cf3c..f712c07 100644
--- a/test/subscribe_notify_tests/conf/subscribe_notify_test_one_event_two_eventgroups_tcp_slave.json.in
+++ b/test/subscribe_notify_tests/conf/subscribe_notify_test_one_event_two_eventgroups_tcp_slave.json.in
@@ -2,7 +2,7 @@
"unicast" : "@TEST_IP_SLAVE@",
"logging" :
{
- "level" : "debug",
+ "level" : "warning",
"console" : "true",
"file" : { "enable" : "false", "path" : "/tmp/vsomeip.log" },
"dlt" : "false"
diff --git a/test/subscribe_notify_tests/conf/subscribe_notify_test_one_event_two_eventgroups_udp_slave.json.in b/test/subscribe_notify_tests/conf/subscribe_notify_test_one_event_two_eventgroups_udp_slave.json.in
index fa3e4f5..cd6415c 100644
--- a/test/subscribe_notify_tests/conf/subscribe_notify_test_one_event_two_eventgroups_udp_slave.json.in
+++ b/test/subscribe_notify_tests/conf/subscribe_notify_test_one_event_two_eventgroups_udp_slave.json.in
@@ -2,7 +2,7 @@
"unicast" : "@TEST_IP_SLAVE@",
"logging" :
{
- "level" : "debug",
+ "level" : "warning",
"console" : "true",
"file" : { "enable" : "false", "path" : "/tmp/vsomeip.log" },
"dlt" : "false"
diff --git a/test/subscribe_notify_tests/subscribe_notify_test_master_starter.sh b/test/subscribe_notify_tests/subscribe_notify_test_master_starter.sh
index f14550d..f068e99 100755
--- a/test/subscribe_notify_tests/subscribe_notify_test_master_starter.sh
+++ b/test/subscribe_notify_tests/subscribe_notify_test_master_starter.sh
@@ -40,7 +40,7 @@ export VSOMEIP_APPLICATION_NAME=subscribe_notify_test_service_three
export VSOMEIP_CONFIGURATION=$MASTER_JSON_FILE
./subscribe_notify_test_service 3 $RELIABILITY_TYPE $3 &
-sleep 1
+sleep 3
if [ ! -z "$USE_LXC_TEST" ]; then
echo "starting subscribe_notify_test_slave_starter.sh on slave LXC with parameters $CLIENT_JSON_FILE $2"
@@ -48,6 +48,9 @@ if [ ! -z "$USE_LXC_TEST" ]; then
echo "remote ssh job id: $!"
elif [ ! -z "$USE_DOCKER" ]; then
docker exec $DOCKER_IMAGE sh -c "cd $DOCKER_TESTS && ./subscribe_notify_test_slave_starter.sh $RELIABILITY_TYPE $CLIENT_JSON_FILE $3" &
+elif [ ! -z "$JENKINS" ]; then
+ ssh -tt -i $PRV_KEY -o StrictHostKeyChecking=no jenkins@$IP_SLAVE "bash -ci \"set -m; cd $WS_ROOT/build/test; ./subscribe_notify_test_slave_starter.sh $RELIABILITY_TYPE $CLIENT_JSON_FILE $3\" >> $WS_ROOT/slave_test_output 2>&1" &
+
else
cat <<End-of-message
*******************************************************************************
diff --git a/test/subscribe_notify_tests/subscribe_notify_test_one_event_two_eventgroups_master_starter.sh b/test/subscribe_notify_tests/subscribe_notify_test_one_event_two_eventgroups_master_starter.sh
index 8da1ded..c453796 100755
--- a/test/subscribe_notify_tests/subscribe_notify_test_one_event_two_eventgroups_master_starter.sh
+++ b/test/subscribe_notify_tests/subscribe_notify_test_one_event_two_eventgroups_master_starter.sh
@@ -46,6 +46,9 @@ if [ ! -z "$USE_LXC_TEST" ]; then
echo "remote ssh job id: $!"
elif [ ! -z "$USE_DOCKER" ]; then
docker exec $DOCKER_IMAGE sh -c "cd $DOCKER_TESTS && ./subscribe_notify_test_one_event_two_eventgroups_slave_starter.sh $RELIABILITY_TYPE $SLAVE_JSON_FILE" &
+elif [ ! -z "$JENKINS" ]; then
+ ssh -tt -i $PRV_KEY -o StrictHostKeyChecking=no jenkins@$IP_SLAVE "bash -ci \"set -m; cd $WS_ROOT/build/test; ./subscribe_notify_test_one_event_two_eventgroups_slave_starter.sh $RELIABILITY_TYPE $SLAVE_JSON_FILE\" >> $WS_ROOT/slave_test_output 2>&1" &
+
else
cat <<End-of-message
*******************************************************************************
@@ -74,7 +77,6 @@ wait $PID_CLIENT || FAIL=$(($FAIL+1))
kill $PID_VSOMEIPD
wait $PID_VSOMEIPD || FAIL=$(($FAIL+1))
-echo ""
# Check if both exited successfully
if [ $FAIL -eq 0 ]; then
diff --git a/test/subscribe_notify_tests/subscribe_notify_test_one_event_two_eventgroups_slave_starter.sh b/test/subscribe_notify_tests/subscribe_notify_test_one_event_two_eventgroups_slave_starter.sh
index d9f0161..0d663d6 100755
--- a/test/subscribe_notify_tests/subscribe_notify_test_one_event_two_eventgroups_slave_starter.sh
+++ b/test/subscribe_notify_tests/subscribe_notify_test_one_event_two_eventgroups_slave_starter.sh
@@ -32,12 +32,10 @@ PID_SERVICE=$!
# wait until service exits successfully
wait $PID_SERVICE || FAIL=$(($FAIL+1))
-
# kill daemon
kill $PID_VSOMEIPD
wait $PID_VSOMEIPD || FAIL=$(($FAIL+1))
-echo ""
# Check if both exited successfully
if [ $FAIL -eq 0 ]; then
diff --git a/test/subscribe_notify_tests/subscribe_notify_test_slave_starter.sh b/test/subscribe_notify_tests/subscribe_notify_test_slave_starter.sh
index dca9e71..8133161 100755
--- a/test/subscribe_notify_tests/subscribe_notify_test_slave_starter.sh
+++ b/test/subscribe_notify_tests/subscribe_notify_test_slave_starter.sh
@@ -36,6 +36,8 @@ export VSOMEIP_APPLICATION_NAME=subscribe_notify_test_service_six
export VSOMEIP_CONFIGURATION=$SLAVE_JSON_FILE
./subscribe_notify_test_service 6 $RELIABILITY_TYPE $3 &
+sleep 3
+
# Wait until all applications are finished
for job in $(jobs -p)
do
@@ -44,7 +46,7 @@ do
wait $job || ((FAIL+=1))
done
-# Check if both exited successfully
+# Check if both exited successfully
if [ $FAIL -eq 0 ]
then
exit 0
diff --git a/test/suspend_resume_tests/conf/suspend_resume_test_client.json.in b/test/suspend_resume_tests/conf/suspend_resume_test_client.json.in
new file mode 100644
index 0000000..db94cea
--- /dev/null
+++ b/test/suspend_resume_tests/conf/suspend_resume_test_client.json.in
@@ -0,0 +1,32 @@
+{
+ "unicast" : "@TEST_IP_SLAVE@",
+ "netmask" : "255.255.255.0",
+ "logging" :
+ {
+ "level" : "debug",
+ "console" : "true",
+ "file" : { "enable" : "false", "path" : "" },
+ "dlt" : "false"
+ },
+ "applications" :
+ [
+ {
+ "name" : "suspend_resume_test_client",
+ "id" : "0x4567"
+ }
+ ],
+ "routing" : "suspend_resume_test_client",
+ "service-discovery" :
+ {
+ "enable" : "true",
+ "multicast" : "224.0.0.1",
+ "port" : "30490",
+ "protocol" : "udp",
+ "initial_delay_min" : "10",
+ "initial_delay_max" : "10",
+ "repetitions_base_delay" : "30",
+ "repetitions_max" : "3",
+ "cyclic_offer_delay" : "1000",
+ "ttl" : "3"
+ }
+} \ No newline at end of file
diff --git a/test/suspend_resume_tests/conf/suspend_resume_test_service.json.in b/test/suspend_resume_tests/conf/suspend_resume_test_service.json.in
new file mode 100644
index 0000000..44b510b
--- /dev/null
+++ b/test/suspend_resume_tests/conf/suspend_resume_test_service.json.in
@@ -0,0 +1,40 @@
+{
+ "unicast" : "@TEST_IP_MASTER@",
+ "netmask" : "255.255.255.0",
+ "logging" :
+ {
+ "level" : "debug",
+ "console" : "true",
+ "file" : { "enable" : "false", "path" : "" },
+ "dlt" : "false"
+ },
+ "applications" :
+ [
+ {
+ "name" : "suspend_resume_test_service",
+ "id" : "0x7654"
+ }
+ ],
+ "services" :
+ [
+ {
+ "service" : "0x6311",
+ "instance" : "0x0002",
+ "unreliable" : "34504"
+ }
+ ],
+ "routing" : "routingmanagerd",
+ "service-discovery" :
+ {
+ "enable" : "true",
+ "multicast" : "224.0.0.1",
+ "port" : "30490",
+ "protocol" : "udp",
+ "initial_delay_min" : "10",
+ "initial_delay_max" : "10",
+ "repetitions_base_delay" : "30",
+ "repetitions_max" : "3",
+ "cyclic_offer_delay" : "1000",
+ "ttl" : "3"
+ }
+} \ No newline at end of file
diff --git a/test/suspend_resume_tests/suspend_resume_test.hpp b/test/suspend_resume_tests/suspend_resume_test.hpp
new file mode 100644
index 0000000..5271bba
--- /dev/null
+++ b/test/suspend_resume_tests/suspend_resume_test.hpp
@@ -0,0 +1,22 @@
+// Copyright (C) 2021 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 SUSPEND_RESUME_TEST_
+#define SUSPEND_RESUME_TEST_
+
+#define TEST_SERVICE 0x6311
+#define TEST_INSTANCE 0x0002
+#define TEST_MAJOR 0x01
+#define TEST_MINOR 0x0
+
+#define TEST_EVENT 0x8005
+#define TEST_EVENTGROUP 0x0002
+
+#define TEST_METHOD 0x0001
+
+#define TEST_SUSPEND 0x00
+#define TEST_STOP 0xFF
+
+#endif // SUSPEND_RESUME_TEST_
diff --git a/test/suspend_resume_tests/suspend_resume_test_client.cpp b/test/suspend_resume_tests/suspend_resume_test_client.cpp
new file mode 100644
index 0000000..ca2956c
--- /dev/null
+++ b/test/suspend_resume_tests/suspend_resume_test_client.cpp
@@ -0,0 +1,239 @@
+// Copyright (C) 2021 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 <condition_variable>
+#include <mutex>
+#include <thread>
+
+#include <gtest/gtest.h>
+
+#include <vsomeip/vsomeip.hpp>
+#include <vsomeip/internal/logger.hpp>
+
+#include "suspend_resume_test.hpp"
+
+class suspend_resume_test_client {
+public:
+ suspend_resume_test_client()
+ : name_("suspend_resume_test_client"),
+ app_(vsomeip::runtime::get()->create_application(name_)),
+ has_received_(false),
+ runner_(std::bind(&suspend_resume_test_client::run, this)) {
+
+ }
+
+ void run_test() {
+
+ register_state_handler();
+ register_message_handler();
+ register_availability_handler();
+
+ start();
+
+ {
+ VSOMEIP_DEBUG << "Started.";
+ std::unique_lock<std::mutex> its_lock(mutex_);
+ auto r = cv_.wait_for(its_lock, std::chrono::seconds(10));
+ EXPECT_EQ(r, std::cv_status::no_timeout);
+ }
+
+ toggle();
+
+ {
+ VSOMEIP_DEBUG << "Toggled.";
+ std::unique_lock<std::mutex> its_lock(mutex_);
+ if (!has_received_) {
+ auto r = cv_.wait_for(its_lock, std::chrono::seconds(10));
+ EXPECT_EQ(r, std::cv_status::no_timeout);
+ }
+ }
+
+ send_suspend();
+
+ bool was_successful;
+ {
+ VSOMEIP_DEBUG << "Triggered suspend/resume.";
+
+ // Wait for service to become availaber after suspend/resume.
+ std::unique_lock<std::mutex> its_lock(mutex_);
+ auto r = cv_.wait_for(its_lock, std::chrono::seconds(10));
+ EXPECT_EQ(r, std::cv_status::no_timeout);
+
+ // Wait for initial event after suspend/resume.
+ r = cv_.wait_for(its_lock, std::chrono::seconds(10));
+ EXPECT_EQ(r, std::cv_status::no_timeout);
+
+ was_successful = (r == std::cv_status::no_timeout);
+ }
+
+ if (was_successful)
+ send_stop();
+
+ stop();
+ }
+
+private:
+ void register_state_handler() {
+
+ app_->register_state_handler(
+ std::bind(&suspend_resume_test_client::on_state, this, std::placeholders::_1));
+ }
+
+ void register_availability_handler() {
+
+ app_->register_availability_handler(TEST_SERVICE, TEST_INSTANCE,
+ std::bind(&suspend_resume_test_client::on_availability, this,
+ std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
+ }
+
+ void register_message_handler() {
+
+ app_->register_message_handler(TEST_SERVICE, TEST_INSTANCE, TEST_EVENT,
+ std::bind(&suspend_resume_test_client::on_message, this,
+ std::placeholders::_1));
+ }
+
+ void start() {
+
+ app_->init();
+ cv_.notify_one();
+ }
+
+ void run() {
+
+ {
+ std::unique_lock<std::mutex> its_lock(mutex_);
+ cv_.wait(its_lock);
+ }
+
+ app_->start();
+ }
+
+ void stop() {
+
+ app_->stop();
+ runner_.join();
+ }
+
+ void on_state(vsomeip::state_type_e _state) {
+
+ VSOMEIP_DEBUG << __func__ << ": state="
+ << (_state == vsomeip::state_type_e::ST_REGISTERED ?
+ "registered." : "NOT registered.");
+
+ if (_state == vsomeip::state_type_e::ST_REGISTERED) {
+ app_->request_event(TEST_SERVICE, TEST_INSTANCE, TEST_EVENT, { TEST_EVENTGROUP });
+ app_->request_service(TEST_SERVICE, TEST_INSTANCE);
+ }
+ }
+
+ void on_availability(vsomeip::service_t _service, vsomeip::instance_t _instance, bool _is_available) {
+
+ static bool is_available(false);
+
+ if (_service == TEST_SERVICE && _instance == TEST_INSTANCE) {
+
+ VSOMEIP_DEBUG << __func__ << ": Test service is "
+ << (_is_available ? "available." : "NOT available.");
+
+ if (_is_available)
+ cv_.notify_one();
+ else if (is_available)
+ has_received_ = false;
+
+ is_available = _is_available;
+ }
+ }
+
+ void on_message(const std::shared_ptr<vsomeip::message> &_message) {
+
+ if (_message->get_service() == TEST_SERVICE
+ && _message->get_instance() == TEST_INSTANCE
+ && _message->get_method() == TEST_EVENT) {
+
+ VSOMEIP_DEBUG << __func__ << ": Received event.";
+ if (!has_received_) {
+ has_received_ = true;
+ cv_.notify_one();
+ }
+ }
+ }
+
+ void toggle() {
+
+ app_->subscribe(TEST_SERVICE, TEST_INSTANCE, TEST_EVENTGROUP, TEST_MAJOR);
+ std::this_thread::sleep_for(std::chrono::seconds(3));
+ app_->unsubscribe(TEST_SERVICE, TEST_INSTANCE, TEST_EVENTGROUP);
+ app_->subscribe(TEST_SERVICE, TEST_INSTANCE, TEST_EVENTGROUP, TEST_MAJOR);
+ std::this_thread::sleep_for(std::chrono::seconds(2));
+ app_->unsubscribe(TEST_SERVICE, TEST_INSTANCE, TEST_EVENTGROUP);
+ app_->subscribe(TEST_SERVICE, TEST_INSTANCE, TEST_EVENTGROUP, TEST_MAJOR);
+
+ }
+
+
+ void send_suspend() {
+
+ auto its_message = vsomeip::runtime::get()->create_request(false);
+ its_message->set_service(TEST_SERVICE);
+ its_message->set_instance(TEST_INSTANCE);
+ its_message->set_method(TEST_METHOD);
+ its_message->set_interface_version(TEST_MAJOR);
+ its_message->set_message_type(vsomeip::message_type_e::MT_REQUEST_NO_RETURN);
+ its_message->set_return_code(vsomeip::return_code_e::E_OK);
+
+ vsomeip::byte_t its_data[] = { TEST_SUSPEND };
+ auto its_payload = vsomeip::runtime::get()->create_payload();
+ its_payload->set_data(its_data, sizeof(its_data));
+ its_message->set_payload(its_payload);
+
+ app_->send(its_message);
+
+ std::this_thread::sleep_for(std::chrono::milliseconds(50));
+ }
+
+ void send_stop() {
+
+ auto its_message = vsomeip::runtime::get()->create_request(false);
+ its_message->set_service(TEST_SERVICE);
+ its_message->set_instance(TEST_INSTANCE);
+ its_message->set_method(TEST_METHOD);
+ its_message->set_interface_version(TEST_MAJOR);
+ its_message->set_message_type(vsomeip::message_type_e::MT_REQUEST_NO_RETURN);
+ its_message->set_return_code(vsomeip::return_code_e::E_OK);
+
+ vsomeip::byte_t its_data[] = { TEST_STOP };
+ auto its_payload = vsomeip::runtime::get()->create_payload();
+ its_payload->set_data(its_data, sizeof(its_data));
+ its_message->set_payload(its_payload);
+
+ app_->send(its_message);
+
+ std::this_thread::sleep_for(std::chrono::milliseconds(50));
+ }
+
+private: // members
+ std::string name_;
+ std::shared_ptr<vsomeip::application> app_;
+ std::mutex mutex_;
+ std::condition_variable cv_;
+ bool has_received_;
+ std::thread runner_;
+};
+
+TEST(suspend_resume_test, fast)
+{
+ suspend_resume_test_client its_client;
+ its_client.run_test();
+}
+
+#ifndef _WIN32
+int main(int argc, char** argv) {
+
+ ::testing::InitGoogleTest(&argc, argv);
+
+ return RUN_ALL_TESTS();
+}
+#endif // _WIN32
diff --git a/test/suspend_resume_tests/suspend_resume_test_master_starter.sh b/test/suspend_resume_tests/suspend_resume_test_master_starter.sh
new file mode 100755
index 0000000..39a8d73
--- /dev/null
+++ b/test/suspend_resume_tests/suspend_resume_test_master_starter.sh
@@ -0,0 +1,72 @@
+#!/bin/bash
+# Copyright (C) 2021 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
+
+# Start the service
+export VSOMEIP_APPLICATION_NAME=suspend_resume_test_service
+export VSOMEIP_CONFIGURATION=suspend_resume_test_service.json
+
+# start daemon
+../examples/routingmanagerd/./routingmanagerd &
+PID_VSOMEIPD=$!
+
+# start the service
+./suspend_resume_test_service $PID_VSOMEIPD &
+PID_SERVICE=$!
+
+sleep 1
+
+if [ ! -z "$USE_LXC_TEST" ]; then
+ echo "starting suspend_resume_test_slave_starter.sh on slave LXC with parameters $SLAVE_JSON_FILE"
+ ssh -tt -i $SANDBOX_ROOT_DIR/commonapi_main/lxc-config/.ssh/mgc_lxc/rsa_key_file.pub -o StrictHostKeyChecking=no root@$LXC_TEST_SLAVE_IP "bash -ci \"set -m; cd \\\$SANDBOX_TARGET_DIR/vsomeip_lib/test; ./suspend_resume_test_slave_starter.sh\"" &
+ echo "remote ssh job id: $!"
+elif [ ! -z "$USE_DOCKER" ]; then
+ docker exec $DOCKER_IMAGE sh -c "cd $DOCKER_TESTS && ./suspend_resume_test_slave_starter.sh" &
+elif [ ! -z "$JENKINS" ]; then
+ ssh -tt -i $PRV_KEY -o StrictHostKeyChecking=no jenkins@$IP_SLAVE "bash -ci \"set -m; cd $WS_ROOT/build/test; ./suspend_resume_test_slave_starter.sh\" >> $WS_ROOT/slave_test_output 2>&1" &
+
+else
+ cat <<End-of-message
+*******************************************************************************
+*******************************************************************************
+** Please now run:
+** suspend_resume_test_slave_starter.sh
+** from an external host to successfully complete this test.
+**
+** You probably will need to adapt the 'unicast' settings in
+** suspend_resume_test_service.json and
+** suspend_resume_test_client.json to your personal setup.
+*******************************************************************************
+*******************************************************************************
+End-of-message
+fi
+
+if [ ! -z "$USE_DOCKER" ]; then
+ FAIL=0
+fi
+
+# wait until client exits successfully
+wait $PID_SERVICE || FAIL=$(($FAIL+1))
+
+# kill daemon
+kill $PID_VSOMEIPD
+wait $PID_VSOMEIPD || FAIL=$(($FAIL+1))
+
+echo ""
+
+# Check if both exited successfully
+if [ $FAIL -eq 0 ]; then
+ exit 0
+else
+ exit 1
+fi
diff --git a/test/suspend_resume_tests/suspend_resume_test_service.cpp b/test/suspend_resume_tests/suspend_resume_test_service.cpp
new file mode 100644
index 0000000..205a2ce
--- /dev/null
+++ b/test/suspend_resume_tests/suspend_resume_test_service.cpp
@@ -0,0 +1,213 @@
+// Copyright (C) 2021 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 <condition_variable>
+#include <mutex>
+#include <thread>
+#include <atomic>
+
+#include <gtest/gtest.h>
+
+#include <vsomeip/vsomeip.hpp>
+#include <vsomeip/internal/logger.hpp>
+
+#include "suspend_resume_test.hpp"
+
+pid_t daemon_pid__;
+
+class suspend_resume_test_service {
+public:
+ suspend_resume_test_service()
+ : name_("suspend_resume_test_service"),
+ app_(vsomeip::runtime::get()->create_application(name_)),
+ is_running_(true),
+ is_unblocked_(false),
+ runner_(std::bind(&suspend_resume_test_service::run, this)),
+ sr_runner_(std::bind(&suspend_resume_test_service::sr_run, this)) {
+ }
+
+ void run_test() {
+
+ register_state_handler();
+ register_message_handler();
+ register_subscription_handler();
+
+ start();
+
+ VSOMEIP_DEBUG << "Using daemon with pid=" << std::dec << daemon_pid__;
+
+ {
+ std::unique_lock<std::mutex> its_lock(mutex_);
+ auto r = cv_.wait_for(its_lock, std::chrono::seconds(30));
+ EXPECT_EQ(r, std::cv_status::no_timeout);
+ }
+
+ stop();
+ }
+
+private:
+ void start() {
+
+ app_->init();
+ cv_.notify_one();
+ }
+
+ void stop() {
+
+ is_running_ = false;
+ sr_cv_.notify_one();
+
+ app_->stop();
+
+ runner_.join();
+ sr_runner_.join();
+ }
+
+ void run() {
+
+ {
+ std::unique_lock<std::mutex> its_lock(mutex_);
+ cv_.wait(its_lock);
+ }
+
+ app_->start();
+ }
+
+ void sr_run() {
+
+ while (is_running_) {
+ std::unique_lock<std::mutex> its_lock(sr_mutex_);
+ sr_cv_.wait(its_lock);
+
+ if (is_running_) {
+ VSOMEIP_DEBUG << "send kill SIGUSR1 to PID: " << std::dec << daemon_pid__;
+ kill(daemon_pid__, SIGUSR1);
+ std::this_thread::sleep_for(std::chrono::seconds(5));
+ VSOMEIP_DEBUG << "send kill SIGUSR2 to PID: " << std::dec << daemon_pid__;
+ kill(daemon_pid__, SIGUSR2);
+ }
+ }
+ }
+
+ void register_state_handler() {
+
+ app_->register_state_handler(
+ std::bind(&suspend_resume_test_service::on_state, this, std::placeholders::_1));
+ }
+
+ void register_message_handler() {
+
+ app_->register_message_handler(TEST_SERVICE, TEST_INSTANCE, TEST_METHOD,
+ std::bind(&suspend_resume_test_service::on_message, this,
+ std::placeholders::_1));
+ }
+
+ void register_subscription_handler() {
+
+ app_->register_subscription_handler(TEST_SERVICE, TEST_INSTANCE, TEST_EVENTGROUP,
+ std::bind(&suspend_resume_test_service::on_subscribe, this,
+ std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4));
+ }
+
+ void offer_service() {
+ app_->offer_event(TEST_SERVICE, TEST_INSTANCE, TEST_EVENT, { TEST_EVENTGROUP },
+ vsomeip::event_type_e::ET_FIELD,
+ std::chrono::milliseconds::zero(), false, true, nullptr,
+ vsomeip::reliability_type_e::RT_UNRELIABLE);
+
+ vsomeip::byte_t its_data[] = { 0x1, 0x2, 0x3 };
+ auto its_payload = vsomeip::runtime::get()->create_payload();
+ its_payload->set_data(its_data, sizeof(its_data));
+ app_->notify(TEST_SERVICE, TEST_INSTANCE, TEST_EVENT, its_payload);
+
+ app_->offer_service(TEST_SERVICE, TEST_INSTANCE, TEST_MAJOR, TEST_MINOR);
+ }
+
+ // handler
+ void on_state(vsomeip::state_type_e _state) {
+ VSOMEIP_DEBUG << __func__ << ": state="
+ << (_state == vsomeip::state_type_e::ST_REGISTERED ?
+ "registered." : "NOT registered.");
+
+ if (_state == vsomeip::state_type_e::ST_REGISTERED) {
+ offer_service();
+ }
+ }
+
+ void on_message(const std::shared_ptr<vsomeip::message> &_message) {
+
+ VSOMEIP_DEBUG << __func__ << ": Received "
+ << std::hex << std::setw(4) << std::setfill('0')
+ << _message->get_service()
+ << std::hex << std::setw(4) << std::setfill('0')
+ << _message->get_instance()
+ << std::hex << std::setw(4) << std::setfill('0')
+ << _message->get_method();
+
+ if (_message->get_service() == TEST_SERVICE
+ && _message->get_instance() == TEST_INSTANCE
+ && _message->get_method() == TEST_METHOD) {
+
+ if (_message->get_payload()->get_length() == 1) {
+
+ vsomeip::byte_t its_control_byte(*_message->get_payload()->get_data());
+
+ switch (its_control_byte) {
+ case TEST_SUSPEND:
+ sr_cv_.notify_one();
+ break;
+ case TEST_STOP:
+ cv_.notify_one();
+ break;
+ default:
+ ;
+ }
+ }
+ }
+ }
+
+ bool on_subscribe(vsomeip::client_t _client,
+ vsomeip::uid_t _uid, vsomeip::gid_t _gid,
+ bool _is_subscribe) {
+
+ (void)_client;
+ (void)_uid;
+ (void)_gid;
+
+ VSOMEIP_DEBUG << __func__ << ": is_subscribe=" << std::boolalpha << _is_subscribe;
+ if (!_is_subscribe)
+ std::this_thread::sleep_for(std::chrono::milliseconds(2000));
+ return (true);
+ }
+
+private: // members
+ std::string name_;
+ std::shared_ptr<vsomeip::application> app_;
+ std::atomic<bool> is_running_;
+ bool is_unblocked_;
+ std::mutex mutex_;
+ std::condition_variable cv_;
+ std::mutex sr_mutex_;
+ std::condition_variable sr_cv_;
+ std::thread runner_;
+ std::thread sr_runner_;
+};
+
+TEST(suspend_resume_test, fast)
+{
+ suspend_resume_test_service its_service;
+ its_service.run_test();
+}
+
+#ifndef _WIN32
+int main(int argc, char** argv) {
+
+ ::testing::InitGoogleTest(&argc, argv);
+
+ daemon_pid__ = atoi(argv[1]);
+
+ return RUN_ALL_TESTS();
+}
+#endif // _WIN32
diff --git a/test/suspend_resume_tests/suspend_resume_test_slave_starter.sh b/test/suspend_resume_tests/suspend_resume_test_slave_starter.sh
new file mode 100755
index 0000000..9cbf85d
--- /dev/null
+++ b/test/suspend_resume_tests/suspend_resume_test_slave_starter.sh
@@ -0,0 +1,29 @@
+#!/bin/bash
+# Copyright (C) 2021 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
+
+# Start the client
+export VSOMEIP_APPLICATION_NAME=suspend_resume_test_client
+export VSOMEIP_CONFIGURATION=suspend_resume_test_client.json
+./suspend_resume_test_client &
+PID_CLIENT=$!
+
+# 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 \ No newline at end of file
diff --git a/tools/vsomeip_ctrl.cpp b/tools/vsomeip_ctrl.cpp
index 4b24deb..c703ed5 100644
--- a/tools/vsomeip_ctrl.cpp
+++ b/tools/vsomeip_ctrl.cpp
@@ -28,7 +28,6 @@ public:
user_message_(_user_message),
instance_(_instance),
app_(vsomeip::runtime::get()->create_application("vsomeip_ctrl")),
- wait_registered_(true),
wait_service_available_(true),
send_thread_(std::bind(&vsomeip_sender::send, this)),
service_id_(0x0),
@@ -321,7 +320,6 @@ private:
std::shared_ptr<vsomeip::application> app_;
std::mutex mutex_;
std::condition_variable condition_;
- bool wait_registered_;
bool wait_service_available_;
std::thread send_thread_;
vsomeip::service_t service_id_;
@@ -404,24 +402,23 @@ int main(int argc, char** argv) {
vsomeip::byte_t low(0x0);
std::cout << "Instance: " << instance_str << std::endl;
for (unsigned int i = 0; i < instance_str.length(); i += 2) {
- vsomeip::byte_t its_byte;
try {
std::uint64_t tmp = std::stoul(instance_str.substr(i, 2), 0, 16);
tmp = (tmp > (std::numeric_limits<std::uint8_t>::max)()) ?
(std::numeric_limits<std::uint8_t>::max)() : tmp;
- its_byte = static_cast<vsomeip::byte_t>(tmp);
- its_byte = static_cast<vsomeip::byte_t>(tmp);
+
+ vsomeip::byte_t its_byte = static_cast<vsomeip::byte_t>(tmp);
+ if (i == 0) {
+ high = its_byte;
+ } else {
+ low = its_byte;
+ }
} catch (std::invalid_argument &e) {
std::cerr << e.what() << ": Couldn't convert '"
<< instance_str.substr(i, 2) << "' to hex, exiting: "
<< std::endl;
exit(EXIT_FAILURE);
}
- if(i == 0) {
- high = its_byte;
- } else {
- low = its_byte;
- }
}
instance = VSOMEIP_BYTES_TO_WORD(high, low);
}