summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJuergen Gehring <juergen.gehring@bmw.de>2017-04-07 03:30:13 -0700
committerJuergen Gehring <juergen.gehring@bmw.de>2017-04-07 03:30:13 -0700
commit5315798ff81796217b55eb8c622f154bb0a1c487 (patch)
treea414da54a2ab36be5fbc2c95e551585c41cbc6f8
parentc35b82a9459b866ab22bc3cabe274c7b36bca290 (diff)
downloadvSomeIP-maintain/2.6.tar.gz
vSomeIP 2.6.22.6.2maintain/2.6
-rw-r--r--CHANGES8
-rw-r--r--CMakeLists.txt2
-rw-r--r--documentation/vsomeipUserGuide8
-rw-r--r--implementation/configuration/include/configuration.hpp1
-rw-r--r--implementation/configuration/include/configuration_impl.hpp3
-rw-r--r--implementation/configuration/include/internal.hpp.in20
-rw-r--r--implementation/configuration/src/configuration_impl.cpp21
-rw-r--r--implementation/endpoints/include/endpoint.hpp4
-rw-r--r--implementation/endpoints/include/endpoint_impl.hpp5
-rw-r--r--implementation/endpoints/include/local_client_endpoint_impl.hpp6
-rw-r--r--implementation/endpoints/include/tcp_server_endpoint_impl.hpp2
-rw-r--r--implementation/endpoints/include/virtual_server_endpoint_impl.hpp2
-rw-r--r--implementation/endpoints/src/endpoint_impl.cpp7
-rw-r--r--implementation/endpoints/src/local_client_endpoint_impl.cpp13
-rw-r--r--implementation/endpoints/src/tcp_client_endpoint_impl.cpp11
-rw-r--r--implementation/endpoints/src/tcp_server_endpoint_impl.cpp26
-rw-r--r--implementation/endpoints/src/virtual_server_endpoint_impl.cpp5
-rw-r--r--implementation/routing/include/routing_manager_base.hpp7
-rw-r--r--implementation/routing/include/routing_manager_host.hpp1
-rw-r--r--implementation/routing/include/routing_manager_impl.hpp9
-rw-r--r--implementation/routing/include/routing_manager_proxy.hpp33
-rw-r--r--implementation/routing/include/routing_manager_stub.hpp40
-rw-r--r--implementation/routing/include/routing_manager_stub_host.hpp5
-rw-r--r--implementation/routing/include/types.hpp6
-rw-r--r--implementation/routing/src/routing_manager_base.cpp37
-rw-r--r--implementation/routing/src/routing_manager_impl.cpp97
-rw-r--r--implementation/routing/src/routing_manager_proxy.cpp244
-rw-r--r--implementation/routing/src/routing_manager_stub.cpp470
-rw-r--r--implementation/runtime/src/application_impl.cpp2
-rw-r--r--implementation/service_discovery/include/service_discovery_host.hpp5
-rw-r--r--implementation/service_discovery/src/service_discovery_impl.cpp7
-rw-r--r--implementation/utility/include/utility.hpp2
-rw-r--r--implementation/utility/src/utility.cpp55
-rw-r--r--test/CMakeLists.txt81
-rw-r--r--test/restart_routing_tests/restart_routing_test_autoconfig.json24
-rw-r--r--test/restart_routing_tests/restart_routing_test_client.cpp158
-rw-r--r--test/restart_routing_tests/restart_routing_test_client.hpp50
-rw-r--r--test/restart_routing_tests/restart_routing_test_client.json48
-rwxr-xr-xtest/restart_routing_tests/restart_routing_test_client_start.sh9
-rw-r--r--test/restart_routing_tests/restart_routing_test_service.cpp133
-rw-r--r--test/restart_routing_tests/restart_routing_test_service.hpp44
-rw-r--r--test/restart_routing_tests/restart_routing_test_service.json44
-rwxr-xr-xtest/restart_routing_tests/restart_routing_test_service_start.sh9
-rwxr-xr-xtest/restart_routing_tests/restart_routing_test_starter.sh312
-rw-r--r--test/someip_test_globals.hpp2
45 files changed, 1706 insertions, 372 deletions
diff --git a/CHANGES b/CHANGES
index f8f5401..712308b 100644
--- a/CHANGES
+++ b/CHANGES
@@ -288,3 +288,11 @@ v2.6.0
v2.6.1
- Fixed clearing of subscribers on stop offer service
+
+v2.6.2
+- Service-Disovery performance improvements
+- Made Routing Manager restartable
+- Fixed file handle leak caused by remote ECU reboot
+- Activate TCP-Keep-Alive for TCP endpoints
+- Debouncing of request-service messages (routing info performance)
+- Fixed false session-id handling of identification request
diff --git a/CMakeLists.txt b/CMakeLists.txt
index f53cdf5..a7e67bb 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -8,7 +8,7 @@ project (vsomeip)
set (VSOMEIP_MAJOR_VERSION 2)
set (VSOMEIP_MINOR_VERSION 6)
-set (VSOMEIP_PATCH_VERSION 1)
+set (VSOMEIP_PATCH_VERSION 2)
set (VSOMEIP_VERSION ${VSOMEIP_MAJOR_VERSION}.${VSOMEIP_MINOR_VERSION}.${VSOMEIP_PATCH_VERSION})
set (PACKAGE_VERSION ${VSOMEIP_VERSION}) # Used in documentatin/doxygen.in
set (CMAKE_VERBOSE_MAKEFILE off)
diff --git a/documentation/vsomeipUserGuide b/documentation/vsomeipUserGuide
index 4bc644d..b2c7d1d 100644
--- a/documentation/vsomeipUserGuide
+++ b/documentation/vsomeipUserGuide
@@ -399,6 +399,14 @@ callbacks if max_dispatchers is configured greater than 0).
The number of internal threads to process messages and events within an application.
Valid values are 1-255. Default is 2.
+
+** 'request_debounce_time' (optional)
++
+Specifies a debounce-time interval in ms in which request-service messages are sent to
+the routing manager. If an application requests many services in short same time
+the load of sent messages to the routing manager and furthermore the replies from the
+routing manager (which contains the routing info for the requested service if available)
+can be heavily reduced. The default value if not specified is 10ms.
++
* `services` (array)
+
Contains the services of the service provider.
diff --git a/implementation/configuration/include/configuration.hpp b/implementation/configuration/include/configuration.hpp
index 88a978b..26ebf36 100644
--- a/implementation/configuration/include/configuration.hpp
+++ b/implementation/configuration/include/configuration.hpp
@@ -74,6 +74,7 @@ public:
virtual std::size_t get_max_dispatchers(const std::string &_name) const = 0;
virtual std::size_t get_max_dispatch_time(const std::string &_name) const = 0;
virtual std::size_t get_io_thread_count(const std::string &_name) const = 0;
+ virtual std::size_t get_request_debouncing(const std::string &_name) const = 0;
virtual std::uint32_t get_max_message_size_local() const = 0;
virtual std::uint32_t get_message_size_reliable(const std::string& _address,
diff --git a/implementation/configuration/include/configuration_impl.hpp b/implementation/configuration/include/configuration_impl.hpp
index 9693d72..9f7c3c3 100644
--- a/implementation/configuration/include/configuration_impl.hpp
+++ b/implementation/configuration/include/configuration_impl.hpp
@@ -80,6 +80,7 @@ public:
VSOMEIP_EXPORT std::size_t get_max_dispatchers(const std::string &_name) const;
VSOMEIP_EXPORT std::size_t get_max_dispatch_time(const std::string &_name) const;
VSOMEIP_EXPORT std::size_t get_io_thread_count(const std::string &_name) const;
+ VSOMEIP_EXPORT std::size_t get_request_debouncing(const std::string &_name) const;
VSOMEIP_EXPORT std::set<std::pair<service_t, instance_t> > get_remote_services() const;
@@ -227,7 +228,7 @@ protected:
std::string logfile_;
boost::log::trivial::severity_level loglevel_;
- std::map<std::string, std::tuple<client_t, std::size_t, std::size_t, size_t>> applications_;
+ std::map<std::string, std::tuple<client_t, std::size_t, std::size_t, std::size_t, std::size_t>> applications_;
std::set<client_t> client_identifiers_;
std::map<service_t,
diff --git a/implementation/configuration/include/internal.hpp.in b/implementation/configuration/include/internal.hpp.in
index 686ea8e..7d8a18c 100644
--- a/implementation/configuration/include/internal.hpp.in
+++ b/implementation/configuration/include/internal.hpp.in
@@ -8,6 +8,7 @@
#include <cstdint>
#include <limits>
+#include <vsomeip/primitive_types.hpp>
#define VSOMEIP_ENV_APPLICATION_NAME "VSOMEIP_APPLICATION_NAME"
#define VSOMEIP_ENV_CONFIGURATION "VSOMEIP_CONFIGURATION"
@@ -56,6 +57,8 @@
#define VSOMEIP_MAX_DESERIALIZER 5
+#define VSOMEIP_REQUEST_DEBOUNCE_TIME 10
+
#define VSOMEIP_COMMAND_HEADER_SIZE 7
#define VSOMEIP_COMMAND_TYPE_POS 0
@@ -89,6 +92,7 @@
#define VSOMEIP_REGISTER_EVENT 0x1B
#define VSOMEIP_UNREGISTER_EVENT 0x1C
#define VSOMEIP_ID_RESPONSE 0x1D
+#define VSOMEIP_ID_REQUEST 0x1E
#define VSOMEIP_OFFER_SERVICE_COMMAND_SIZE 16
#define VSOMEIP_REQUEST_SERVICE_COMMAND_SIZE 17
@@ -101,6 +105,7 @@
#define VSOMEIP_REGISTER_EVENT_COMMAND_SIZE 15
#define VSOMEIP_UNREGISTER_EVENT_COMMAND_SIZE 14
#define VSOMEIP_ID_RESPONSE_COMMAND_SIZE 12
+#define VSOMEIP_ID_REQUEST_COMMAND_SIZE 13
#ifndef _WIN32
#include <pthread.h>
@@ -126,10 +131,25 @@ typedef enum {
RIE_DEL_CLIENT = 0x3,
} routing_info_entry_e;
+struct service_data_t {
+ service_t service_;
+ instance_t instance_;
+ major_version_t major_;
+ minor_version_t minor_;
+ bool use_exclusive_proxy_; // only used for requests!
+
+ bool operator<(const service_data_t &_other) const {
+ return (service_ < _other.service_
+ || (service_ == _other.service_
+ && instance_ < _other.instance_));
+ }
+};
+
struct configuration_data_t {
#ifndef _WIN32
volatile char initialized_;
pthread_mutex_t mutex_;
+ pid_t pid_;
#endif
unsigned short client_base_;
diff --git a/implementation/configuration/src/configuration_impl.cpp b/implementation/configuration/src/configuration_impl.cpp
index d2c6283..7375bdb 100644
--- a/implementation/configuration/src/configuration_impl.cpp
+++ b/implementation/configuration/src/configuration_impl.cpp
@@ -441,6 +441,7 @@ void configuration_impl::load_application_data(
std::size_t its_max_dispatchers(VSOMEIP_MAX_DISPATCHERS);
std::size_t its_max_dispatch_time(VSOMEIP_MAX_DISPATCH_TIME);
std::size_t its_io_thread_count(VSOMEIP_IO_THREAD_COUNT);
+ std::size_t its_request_debounce_time(VSOMEIP_REQUEST_DEBOUNCE_TIME);
for (auto i = _tree.begin(); i != _tree.end(); ++i) {
std::string its_key(i->first);
std::string its_value(i->second.data());
@@ -470,6 +471,13 @@ void configuration_impl::load_application_data(
VSOMEIP_WARNING << "Max. number of threads per application is 255";
its_io_thread_count = 255;
}
+ } else if (its_key == "request_debounce_time") {
+ its_converter << std::dec << its_value;
+ its_converter >> its_request_debounce_time;
+ if (its_request_debounce_time > 10000) {
+ VSOMEIP_WARNING << "Max. request debounce time is 10.000ms";
+ its_request_debounce_time = 10000;
+ }
}
}
if (its_name != "") {
@@ -487,7 +495,8 @@ void configuration_impl::load_application_data(
}
applications_[its_name]
= std::make_tuple(its_id, its_max_dispatchers,
- its_max_dispatch_time, its_io_thread_count);
+ its_max_dispatch_time, its_io_thread_count,
+ its_request_debounce_time);
} else {
VSOMEIP_WARNING << "Multiple configurations for application "
<< its_name << ". Ignoring a configuration from "
@@ -1797,6 +1806,16 @@ bool configuration_impl::is_configured_client_id(client_t _id) const {
return (client_identifiers_.find(_id) != client_identifiers_.end());
}
+std::size_t configuration_impl::get_request_debouncing(const std::string &_name) const {
+ size_t debounce_time = VSOMEIP_REQUEST_DEBOUNCE_TIME;
+ auto found_application = applications_.find(_name);
+ if (found_application != applications_.end()) {
+ debounce_time = std::get<4>(found_application->second);
+ }
+
+ return debounce_time;
+}
+
std::size_t configuration_impl::get_io_thread_count(const std::string &_name) const {
std::size_t its_io_thread_count = VSOMEIP_IO_THREAD_COUNT;
diff --git a/implementation/endpoints/include/endpoint.hpp b/implementation/endpoints/include/endpoint.hpp
index 39b018e..e8752c0 100644
--- a/implementation/endpoints/include/endpoint.hpp
+++ b/implementation/endpoints/include/endpoint.hpp
@@ -16,6 +16,8 @@ class endpoint_definition;
class endpoint {
public:
+ typedef std::function<void()> error_handler_t;
+
virtual ~endpoint() {}
virtual void start() = 0;
@@ -46,6 +48,8 @@ public:
virtual uint32_t get_use_count() = 0;
virtual void restart() = 0;
+
+ virtual void register_error_handler(error_handler_t _error) = 0;
};
} // namespace vsomeip
diff --git a/implementation/endpoints/include/endpoint_impl.hpp b/implementation/endpoints/include/endpoint_impl.hpp
index 3c9b3da..6b8b274 100644
--- a/implementation/endpoints/include/endpoint_impl.hpp
+++ b/implementation/endpoints/include/endpoint_impl.hpp
@@ -51,6 +51,8 @@ public:
void decrement_use_count();
uint32_t get_use_count();
+ void register_error_handler(error_handler_t _error_handler);
+
public:
// required
virtual bool is_client() const = 0;
@@ -81,6 +83,9 @@ protected:
std::mutex local_mutex_;
endpoint_type local_;
+
+ error_handler_t error_handler_;
+ std::mutex error_handler_mutex_;
};
} // namespace vsomeip
diff --git a/implementation/endpoints/include/local_client_endpoint_impl.hpp b/implementation/endpoints/include/local_client_endpoint_impl.hpp
index 46d5c1d..7b71968 100644
--- a/implementation/endpoints/include/local_client_endpoint_impl.hpp
+++ b/implementation/endpoints/include/local_client_endpoint_impl.hpp
@@ -31,8 +31,6 @@ typedef client_endpoint_impl<
class local_client_endpoint_impl: public local_client_endpoint_base_impl {
public:
- typedef std::function<void()> error_handler_t;
-
local_client_endpoint_impl(std::shared_ptr<endpoint_host> _host,
endpoint_type _remote,
boost::asio::io_service &_io,
@@ -47,8 +45,6 @@ public:
bool get_remote_address(boost::asio::ip::address &_address) const;
unsigned short get_remote_port() const;
- void register_error_handler(error_handler_t _error_handler);
-
void restart();
private:
@@ -62,8 +58,6 @@ private:
std::size_t _bytes);
message_buffer_t recv_buffer_;
-
- error_handler_t error_handler_;
};
} // namespace vsomeip
diff --git a/implementation/endpoints/include/tcp_server_endpoint_impl.hpp b/implementation/endpoints/include/tcp_server_endpoint_impl.hpp
index c7b69f4..5875e71 100644
--- a/implementation/endpoints/include/tcp_server_endpoint_impl.hpp
+++ b/implementation/endpoints/include/tcp_server_endpoint_impl.hpp
@@ -34,6 +34,8 @@ public:
void start();
void stop();
+ void stop_all_connections(const boost::asio::ip::address &_address);
+
bool send_to(const std::shared_ptr<endpoint_definition> _target,
const byte_t *_data, uint32_t _size, bool _flush);
void send_queued(queue_iterator_type _queue_iterator);
diff --git a/implementation/endpoints/include/virtual_server_endpoint_impl.hpp b/implementation/endpoints/include/virtual_server_endpoint_impl.hpp
index 8237e30..5e8c49e 100644
--- a/implementation/endpoints/include/virtual_server_endpoint_impl.hpp
+++ b/implementation/endpoints/include/virtual_server_endpoint_impl.hpp
@@ -51,6 +51,8 @@ public:
void restart();
+ void register_error_handler(error_handler_t _handler);
+
private:
std::string address_;
uint16_t port_;
diff --git a/implementation/endpoints/src/endpoint_impl.cpp b/implementation/endpoints/src/endpoint_impl.cpp
index 1707502..1d16d05 100644
--- a/implementation/endpoints/src/endpoint_impl.cpp
+++ b/implementation/endpoints/src/endpoint_impl.cpp
@@ -134,6 +134,13 @@ uint32_t endpoint_impl<Protocol>::get_use_count() {
return use_count_;
}
+template<typename Protocol>
+void endpoint_impl<Protocol>::register_error_handler(error_handler_t _error_handler) {
+ std::lock_guard<std::mutex> its_lock(error_handler_mutex_);
+ this->error_handler_ = _error_handler;
+}
+
+
// Instantiate template
#ifndef _WIN32
template class endpoint_impl<boost::asio::local::stream_protocol>;
diff --git a/implementation/endpoints/src/local_client_endpoint_impl.cpp b/implementation/endpoints/src/local_client_endpoint_impl.cpp
index 6535ec6..4c79047 100644
--- a/implementation/endpoints/src/local_client_endpoint_impl.cpp
+++ b/implementation/endpoints/src/local_client_endpoint_impl.cpp
@@ -183,8 +183,13 @@ void local_client_endpoint_impl::receive_cbk(
// routing manager. For the routing manager proxies, the corresponding
// client endpoint (that connect to the same client) are removed
// after the proxy has received the routing info.
- if (error_handler_)
- error_handler_();
+ error_handler_t handler;
+ {
+ std::lock_guard<std::mutex> its_lock(error_handler_mutex_);
+ handler = error_handler_;
+ }
+ if (handler)
+ handler();
} else {
receive();
}
@@ -200,8 +205,4 @@ unsigned short local_client_endpoint_impl::get_remote_port() const {
return 0;
}
-void local_client_endpoint_impl::register_error_handler(error_handler_t _error_handler) {
- error_handler_ = _error_handler;
-}
-
} // namespace vsomeip
diff --git a/implementation/endpoints/src/tcp_client_endpoint_impl.cpp b/implementation/endpoints/src/tcp_client_endpoint_impl.cpp
index 916c78a..4afe3ef 100644
--- a/implementation/endpoints/src/tcp_client_endpoint_impl.cpp
+++ b/implementation/endpoints/src/tcp_client_endpoint_impl.cpp
@@ -67,6 +67,12 @@ void tcp_client_endpoint_impl::connect() {
<< "Nagle algorithm: " << its_error.message();
}
+ socket_.set_option(boost::asio::socket_base::keep_alive(true), its_error);
+ if (its_error) {
+ VSOMEIP_WARNING << "tcp_client_endpoint::connect: couldn't enable "
+ << "keep_alive: " << its_error.message();
+ }
+
// Enable SO_REUSEADDR to avoid bind problems with services going offline
// and coming online again and the user has specified only a small number
// of ports in the clients section for one service instance
@@ -351,8 +357,9 @@ void tcp_client_endpoint_impl::receive_cbk(
receive();
} else {
if (_error == boost::asio::error::connection_reset ||
- _error == boost::asio::error::eof) {
- VSOMEIP_TRACE << "tcp_client_endpoint: connection_reseted/EOF ~> close socket!";
+ _error == boost::asio::error::eof ||
+ _error == boost::asio::error::timed_out) {
+ VSOMEIP_WARNING << "tcp_client_endpoint receive_cbk error detected: " << _error.message();
shutdown_and_close_socket();
} else {
receive();
diff --git a/implementation/endpoints/src/tcp_server_endpoint_impl.cpp b/implementation/endpoints/src/tcp_server_endpoint_impl.cpp
index 39f2802..85766ef 100644
--- a/implementation/endpoints/src/tcp_server_endpoint_impl.cpp
+++ b/implementation/endpoints/src/tcp_server_endpoint_impl.cpp
@@ -85,6 +85,22 @@ void tcp_server_endpoint_impl::stop() {
}
}
+void tcp_server_endpoint_impl::stop_all_connections(const boost::asio::ip::address &_address) {
+ std::lock_guard<std::mutex> its_lock(connections_mutex_);
+ endpoint_type type;
+
+ for (const auto &c : connections_) {
+ if(c.first.address() == _address) {
+ VSOMEIP_INFO << "Stopping connections for " << _address.to_string()
+ << " : " << std::dec << c.first.port();
+ c.second->stop();
+ type = c.first;
+ }
+ }
+ connections_.erase(type);
+}
+
+
bool tcp_server_endpoint_impl::send_to(
const std::shared_ptr<endpoint_definition> _target,
const byte_t *_data,
@@ -162,6 +178,12 @@ void tcp_server_endpoint_impl::accept_cbk(connection::ptr _connection,
_connection->set_remote_info(remote);
// Nagle algorithm off
new_connection_socket.set_option(ip::tcp::no_delay(true), its_error);
+
+ new_connection_socket.set_option(boost::asio::socket_base::keep_alive(true), its_error);
+ if (its_error) {
+ VSOMEIP_WARNING << "tcp_server_endpoint::connect: couldn't enable "
+ << "keep_alive: " << its_error.message();
+ }
}
if (!its_error) {
{
@@ -485,7 +507,9 @@ void tcp_server_endpoint_impl::connection::receive_cbk(
}
}
if (_error == boost::asio::error::eof
- || _error == boost::asio::error::connection_reset) {
+ || _error == boost::asio::error::connection_reset
+ || _error == boost::asio::error::timed_out) {
+ VSOMEIP_WARNING << "tcp_server_endpoint receive_cbk error detected: " << _error.message();
{
std::lock_guard<std::mutex> its_lock(its_server->connections_mutex_);
stop();
diff --git a/implementation/endpoints/src/virtual_server_endpoint_impl.cpp b/implementation/endpoints/src/virtual_server_endpoint_impl.cpp
index 4ea9ed2..6f20929 100644
--- a/implementation/endpoints/src/virtual_server_endpoint_impl.cpp
+++ b/implementation/endpoints/src/virtual_server_endpoint_impl.cpp
@@ -113,4 +113,9 @@ void virtual_server_endpoint_impl::restart() {
}
+void virtual_server_endpoint_impl::register_error_handler(
+ error_handler_t _handler) {
+ (void)_handler;
+}
+
} // namespace vsomeip
diff --git a/implementation/routing/include/routing_manager_base.hpp b/implementation/routing/include/routing_manager_base.hpp
index 625ed6a..e0ad57e 100644
--- a/implementation/routing/include/routing_manager_base.hpp
+++ b/implementation/routing/include/routing_manager_base.hpp
@@ -110,6 +110,7 @@ public:
endpoint *_receiver,
const boost::asio::ip::address &_remote_address,
std::uint16_t _remote_port) = 0;
+
#ifndef _WIN32
virtual bool check_credentials(client_t _client, uid_t _uid, gid_t _gid);
#endif
@@ -119,6 +120,9 @@ public:
virtual std::shared_ptr<event> find_event(service_t _service, instance_t _instance,
event_t _event) const;
+ virtual void register_client_error_handler(client_t _client,
+ const std::shared_ptr<endpoint> &_endpoint) = 0;
+
protected:
std::shared_ptr<serviceinfo> find_service(service_t _service, instance_t _instance) const;
std::shared_ptr<serviceinfo> create_service_info(service_t _service,
@@ -182,6 +186,9 @@ protected:
instance_t _instance,
eventgroup_t _eventgroup, event_t _event);
+ void send_identify_request(service_t _service, instance_t _instance,
+ major_version_t _major, bool _reliable);
+
private:
std::shared_ptr<endpoint> create_local_unlocked(client_t _client);
std::shared_ptr<endpoint> find_local_unlocked(client_t _client);
diff --git a/implementation/routing/include/routing_manager_host.hpp b/implementation/routing/include/routing_manager_host.hpp
index bbea181..4b0edad 100644
--- a/implementation/routing/include/routing_manager_host.hpp
+++ b/implementation/routing/include/routing_manager_host.hpp
@@ -36,6 +36,7 @@ public:
client_t _client, bool _subscribed) = 0;
virtual void on_subscription_error(service_t _service, instance_t _instance,
eventgroup_t _eventgroup, uint16_t _error) = 0;
+ virtual void send(std::shared_ptr<message> _message, bool _flush) = 0;
};
} // namespace vsomeip
diff --git a/implementation/routing/include/routing_manager_impl.hpp b/implementation/routing/include/routing_manager_impl.hpp
index 2992c9e..a6d7f0d 100644
--- a/implementation/routing/include/routing_manager_impl.hpp
+++ b/implementation/routing/include/routing_manager_impl.hpp
@@ -171,7 +171,7 @@ public:
std::shared_ptr<endpoint> create_service_discovery_endpoint(const std::string &_address,
uint16_t _port, bool _reliable);
void init_routing_info();
- std::chrono::milliseconds add_routing_info(service_t _service, instance_t _instance,
+ void add_routing_info(service_t _service, instance_t _instance,
major_version_t _major, minor_version_t _minor, ttl_t _ttl,
const boost::asio::ip::address &_reliable_address,
uint16_t _reliable_port,
@@ -181,6 +181,8 @@ public:
bool _has_reliable, bool _has_unreliable);
std::chrono::milliseconds update_routing_info(std::chrono::milliseconds _elapsed);
+ void on_reboot(const boost::asio::ip::address &_address);
+
void on_subscribe(service_t _service, instance_t _instance,
eventgroup_t _eventgroup,
std::shared_ptr<endpoint_definition> _subscriber,
@@ -204,8 +206,9 @@ public:
bool has_identified(client_t _client, service_t _service,
instance_t _instance, bool _reliable);
- void on_clientendpoint_error(client_t _client);
- void confirm_pending_offers(client_t _client);
+ void register_client_error_handler(client_t _client,
+ const std::shared_ptr<endpoint> &_endpoint);
+ void handle_client_error(client_t _client);
void set_routing_state(routing_state_e _routing_state);
diff --git a/implementation/routing/include/routing_manager_proxy.hpp b/implementation/routing/include/routing_manager_proxy.hpp
index e725913..0bc25f7 100644
--- a/implementation/routing/include/routing_manager_proxy.hpp
+++ b/implementation/routing/include/routing_manager_proxy.hpp
@@ -95,17 +95,20 @@ public:
void on_identify_response(client_t _client, service_t _service, instance_t _instance,
bool _reliable);
+ void register_client_error_handler(client_t _client,
+ const std::shared_ptr<endpoint> &_endpoint);
+ void handle_client_error(client_t _client);
+
private:
void register_application();
void deregister_application();
+ void reconnect(const std::unordered_set<client_t> &_clients);
+
void send_pong() const;
void send_offer_service(client_t _client, service_t _service,
instance_t _instance, major_version_t _major,
minor_version_t _minor);
- void send_request_service(client_t _client, service_t _service,
- instance_t _instance, major_version_t _major,
- minor_version_t _minor, bool _use_exclusive_proxy);
void send_release_service(client_t _client, service_t _service,
instance_t _instance);
void send_register_event(client_t _client, service_t _service,
@@ -163,6 +166,10 @@ private:
event_t _event,
client_t _client);
+ void request_debounce_timeout_cbk(boost::system::error_code const &_error);
+
+ void send_request_services(std::set<service_data_t>& _requests);
+
private:
enum class inner_state_type_e : std::uint8_t {
ST_REGISTERED = 0x0,
@@ -180,21 +187,9 @@ private:
std::mutex known_clients_mutex_;
std::unordered_set<client_t> known_clients_;
- struct service_data_t {
- service_t service_;
- instance_t instance_;
- major_version_t major_;
- minor_version_t minor_;
- bool use_exclusive_proxy_; // only used for requests!
-
- bool operator<(const service_data_t &_other) const {
- return (service_ < _other.service_
- || (service_ == _other.service_
- && instance_ < _other.instance_));
- }
- };
std::set<service_data_t> pending_offers_;
- std::set<service_data_t> pending_requests_;
+ std::set<service_data_t> requests_;
+ std::set<service_data_t> requests_to_debounce_;
struct event_data_t {
service_t service_;
@@ -230,6 +225,10 @@ private:
boost::asio::steady_timer register_application_timer_;
std::shared_ptr<logger> logger_;
+
+ std::mutex request_timer_mutex_;
+ boost::asio::steady_timer request_debounce_timer_;
+ bool request_debounce_timer_running_;
};
} // namespace vsomeip
diff --git a/implementation/routing/include/routing_manager_stub.hpp b/implementation/routing/include/routing_manager_stub.hpp
index 819352f..13911dc 100644
--- a/implementation/routing/include/routing_manager_stub.hpp
+++ b/implementation/routing/include/routing_manager_stub.hpp
@@ -20,6 +20,7 @@
#include "../../endpoints/include/endpoint_host.hpp"
#include "../../configuration/include/internal.hpp"
+#include "types.hpp"
namespace vsomeip {
@@ -80,14 +81,19 @@ public:
void create_local_receiver();
bool send_ping(client_t _client);
bool is_registered(client_t _client) const;
- void deregister_erroneous_client(client_t _client);
client_t get_client() const;
- void on_request_service(client_t _client, service_t _service,
- instance_t _instance, major_version_t _major,
- minor_version_t _minor);
+ void handle_requests(const client_t _client, std::set<service_data_t>& _requests);
+
+ void send_identify_request_command(std::shared_ptr<vsomeip::endpoint> _target,
+ service_t _service, instance_t _instance, major_version_t _major,
+ bool _reliable);
+
#ifndef _WIN32
virtual bool check_credentials(client_t _client, uid_t _uid, gid_t _gid);
#endif
+
+ void update_registration(client_t _client, registration_type_e _type);
+
private:
void broadcast(const std::vector<byte_t> &_command) const;
@@ -96,12 +102,6 @@ private:
void broadcast_routing_stop();
- void send_routing_info_delta(client_t _target, routing_info_entry_e _entry,
- client_t _client, service_t _service = ANY_SERVICE,
- instance_t _instance = ANY_INSTANCE,
- major_version_t _major = ANY_MAJOR,
- minor_version_t _minor = ANY_MINOR);
-
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,
@@ -122,6 +122,15 @@ private:
};
bool is_already_connected(client_t _source, client_t _sink);
+ void create_client_routing_info(const client_t _target);
+ void insert_client_routing_info(client_t _target, routing_info_entry_e _entry,
+ client_t _client, service_t _service = ANY_SERVICE,
+ instance_t _instance = ANY_INSTANCE,
+ major_version_t _major = ANY_MAJOR,
+ minor_version_t _minor = ANY_MINOR);
+ void send_client_routing_info(const client_t _target);
+
+ void on_client_id_timer_expired(boost::system::error_code const &_error);
private:
routing_manager_stub_host *host_;
@@ -129,6 +138,10 @@ private:
std::mutex watchdog_timer_mutex_;
boost::asio::steady_timer watchdog_timer_;
+ boost::asio::steady_timer client_id_timer_;
+ std::set<client_t> used_client_ids_;
+ std::mutex used_client_ids_mutex_;
+
std::string endpoint_path_;
std::string local_receiver_path_;
std::shared_ptr<endpoint> endpoint_;
@@ -147,11 +160,6 @@ private:
std::mutex client_registration_mutex_;
std::condition_variable client_registration_condition_;
- enum class registration_type_e : std::uint8_t {
- REGISTER = 0x1,
- DEREGISTER = 0x2,
- DEREGISTER_ERROR_CASE = 0x3
- };
std::map<client_t, std::vector<registration_type_e>> pending_client_registrations_;
const std::uint32_t max_local_message_size_;
static const std::vector<byte_t> its_ping_;
@@ -162,6 +170,8 @@ private:
std::map<client_t, std::map<service_t, std::map<instance_t, std::pair<major_version_t, minor_version_t> > > > service_requests_;
std::map<client_t, std::set<client_t>> connection_matrix_;
+
+ std::map<client_t, std::vector<byte_t>> client_routing_info_;
};
} // namespace vsomeip
diff --git a/implementation/routing/include/routing_manager_stub_host.hpp b/implementation/routing/include/routing_manager_stub_host.hpp
index 1606439..344d594 100644
--- a/implementation/routing/include/routing_manager_stub_host.hpp
+++ b/implementation/routing/include/routing_manager_stub_host.hpp
@@ -79,8 +79,9 @@ public:
bool _reliable) = 0;
virtual void on_pong(client_t _client) = 0;
- virtual void on_clientendpoint_error(client_t _client) = 0;
- virtual void confirm_pending_offers(client_t _client) = 0;
+
+ virtual void handle_client_error(client_t _client) = 0;
+
virtual void set_routing_state(routing_state_e _routing_state) = 0;
};
diff --git a/implementation/routing/include/types.hpp b/implementation/routing/include/types.hpp
index 9b803a5..720e937 100644
--- a/implementation/routing/include/types.hpp
+++ b/implementation/routing/include/types.hpp
@@ -27,6 +27,12 @@ typedef std::map<service_t,
std::shared_ptr<
eventgroupinfo> > > > eventgroups_t;
+enum class registration_type_e : std::uint8_t {
+ REGISTER = 0x1,
+ DEREGISTER = 0x2,
+ DEREGISTER_ON_ERROR = 0x3
+};
+
}
// namespace vsomeip
diff --git a/implementation/routing/src/routing_manager_base.cpp b/implementation/routing/src/routing_manager_base.cpp
index 8f10057..04e4adb 100644
--- a/implementation/routing/src/routing_manager_base.cpp
+++ b/implementation/routing/src/routing_manager_base.cpp
@@ -13,7 +13,6 @@
#include "../../logging/include/logger.hpp"
#include "../../endpoints/include/local_client_endpoint_impl.hpp"
#include "../../endpoints/include/local_server_endpoint_impl.hpp"
-#include "../include/routing_manager_impl.hpp"
namespace vsomeip {
@@ -624,22 +623,16 @@ std::shared_ptr<endpoint> routing_manager_base::create_local_unlocked(client_t _
#endif
, io_, configuration_->get_max_message_size_local());
+ // Messages sent to the VSOMEIP_ROUTING_CLIENT are meant to be routed to
+ // external devices. Therefore, its local endpoint must not be found by
+ // a call to find_local. Thus it must not be inserted to the list of local
+ // clients.
if (_client != VSOMEIP_ROUTING_CLIENT) {
- // VSOMEIP_ROUTING_CLIENT must not be added here.
- // The routing master should not get an end-point when calling find_local
- // with VSOMEIP_ROUTING_CLIENT as parameter
- // as it indicates remote communication!
- local_endpoints_[_client] = std::static_pointer_cast<endpoint>(its_endpoint);
-
- routing_manager_impl *its_manager = dynamic_cast<routing_manager_impl*>(this);
- if (its_manager != nullptr) {
- its_endpoint->register_error_handler(
- std::bind(&routing_manager_impl::on_clientendpoint_error,
- its_manager, _client));
- }
+ local_endpoints_[_client] = its_endpoint;
}
+ register_client_error_handler(_client, its_endpoint);
- return (its_endpoint);
+ return its_endpoint;
}
std::shared_ptr<endpoint> routing_manager_base::create_local(client_t _client) {
@@ -682,6 +675,7 @@ void routing_manager_base::remove_local(client_t _client) {
std::shared_ptr<endpoint> its_endpoint(find_local(_client));
if (its_endpoint) {
+ its_endpoint->register_error_handler(nullptr);
its_endpoint->stop();
VSOMEIP_INFO << "Client [" << std::hex << get_client() << "] is closing connection to ["
<< std::hex << _client << "]";
@@ -1033,4 +1027,19 @@ routing_manager_base::get_subscriptions(const client_t _client) {
return result;
}
+void routing_manager_base::send_identify_request(service_t _service,
+ instance_t _instance, major_version_t _major, bool _reliable) {
+ auto message = runtime::get()->create_message(_reliable);
+ message->set_service(_service);
+ message->set_instance(_instance);
+ message->set_client(get_client());
+ message->set_method(ANY_METHOD - 1);
+ message->set_interface_version(_major);
+ message->set_message_type(message_type_e::MT_REQUEST);
+
+ // Initiate a request/response to the remote service
+ // Use host for sending to ensure correct session id is set
+ host_->send(message, true);
+}
+
} // namespace vsomeip
diff --git a/implementation/routing/src/routing_manager_impl.cpp b/implementation/routing/src/routing_manager_impl.cpp
index 145ff35..bfc232e 100644
--- a/implementation/routing/src/routing_manager_impl.cpp
+++ b/implementation/routing/src/routing_manager_impl.cpp
@@ -300,9 +300,12 @@ void routing_manager_impl::request_service(client_t _client, service_t _service,
if (_client == get_client()) {
stub_->create_local_receiver();
- }
- stub_->on_request_service(_client, _service, _instance, _major, _minor);
+ service_data_t request = { _service, _instance, _major, _minor, _use_exclusive_proxy };
+ std::set<service_data_t> requests;
+ requests.insert(request);
+ stub_->handle_requests(_client, requests);
+ }
}
void routing_manager_impl::release_service(client_t _client, service_t _service,
@@ -1775,7 +1778,7 @@ bool routing_manager_impl::is_field(service_t _service, instance_t _instance,
return false;
}
-std::chrono::milliseconds routing_manager_impl::add_routing_info(
+void routing_manager_impl::add_routing_info(
service_t _service, instance_t _instance,
major_version_t _major, minor_version_t _minor, ttl_t _ttl,
const boost::asio::ip::address &_reliable_address,
@@ -1783,37 +1786,6 @@ std::chrono::milliseconds routing_manager_impl::add_routing_info(
const boost::asio::ip::address &_unreliable_address,
uint16_t _unreliable_port) {
- std::chrono::seconds default_ttl(DEFAULT_TTL);
- std::chrono::milliseconds its_smallest_ttl =
- std::chrono::duration_cast<std::chrono::milliseconds>(default_ttl);
- std::chrono::milliseconds its_ttl(std::chrono::duration_cast<std::chrono::milliseconds>(
- std::chrono::seconds(_ttl)));
-
- bool offer_exists(false);
- for (auto &s : get_services()) {
- for (auto &i : s.second) {
- if (i.second->is_local()) {
- continue; //ignore local services
- }
- std::chrono::milliseconds its_found_ttl(i.second->get_precise_ttl());
- if ( its_found_ttl < its_smallest_ttl ) {
- its_smallest_ttl = its_found_ttl;
- if( its_ttl < its_smallest_ttl ) {
- its_smallest_ttl = its_ttl;
- }
- }
- offer_exists = true;
- }
- }
- //if no remote service is in the list yet
- if( !offer_exists ) {
- if( its_ttl < its_smallest_ttl ) {
- // set smallest TTL to TTL of first incoming remote offer
- // this allows expiration of service if no further offer message is received which would trigger update_routing info
- its_smallest_ttl = its_ttl;
- }
- }
-
// Create/Update service info
std::shared_ptr<serviceinfo> its_info(find_service(_service, _instance));
if (!its_info) {
@@ -1845,7 +1817,7 @@ std::chrono::milliseconds routing_manager_impl::add_routing_info(
<< std::hex << std::setfill('0') << std::setw(4) << _instance << "."
<< std::dec << static_cast<std::uint32_t>(its_info->get_major())
<< "." << its_info->get_minor() << "]";
- return its_smallest_ttl;
+ return;
} else {
its_info->set_ttl(_ttl);
}
@@ -2007,8 +1979,6 @@ std::chrono::milliseconds routing_manager_impl::add_routing_info(
stub_->on_offer_service(VSOMEIP_ROUTING_CLIENT, _service, _instance, _major, _minor);
}
}
-
- return its_smallest_ttl;
}
void routing_manager_impl::del_routing_info(service_t _service, instance_t _instance,
@@ -2847,22 +2817,14 @@ bool routing_manager_impl::send_identify_message(client_t _client,
std::lock_guard<std::mutex> its_lock(identified_clients_mutex_);
identifying_clients_[_service][_instance][_reliable].insert(_client);
}
- auto message = runtime::get()->create_message(_reliable);
- message->set_service(_service);
- message->set_instance(_instance);
- message->set_client(_client);
- message->set_method(ANY_METHOD - 1);
- message->set_interface_version(_major);
- message->set_message_type(message_type_e::MT_REQUEST);
- {
- std::lock_guard<std::mutex> its_lock(serialize_mutex_);
- if (serializer_->serialize(message.get())) {
- its_endpoint->send(serializer_->get_data(), serializer_->get_size());
- serializer_->reset();
- } else {
- return false;
- }
+
+ if (_client == get_client()) {
+ send_identify_request(_service, _instance, _major, _reliable);
+ } else {
+ stub_->send_identify_request_command(find_local(_client),
+ _service, _instance, _major, _reliable);
}
+
return true;
}
@@ -3251,16 +3213,16 @@ void routing_manager_impl::on_pong(client_t _client) {
}
}
-void routing_manager_impl::on_clientendpoint_error(client_t _client) {
- if (stub_->is_registered(_client)) {
- VSOMEIP_WARNING << "Application/Client "
- << std::hex << std::setw(4) << std::setfill('0')
- << _client << " will be deregistered because of an client endpoint error.";
- stub_->deregister_erroneous_client(_client);
- }
+void routing_manager_impl::register_client_error_handler(client_t _client,
+ const std::shared_ptr<endpoint> &_endpoint) {
+ _endpoint->register_error_handler(
+ std::bind(&routing_manager_impl::handle_client_error, this, _client));
}
-void routing_manager_impl::confirm_pending_offers(client_t _client) {
+void routing_manager_impl::handle_client_error(client_t _client) {
+ if (stub_)
+ stub_->update_registration(_client, registration_type_e::DEREGISTER_ON_ERROR);
+
std::forward_list<std::tuple<client_t, service_t, instance_t, major_version_t,
minor_version_t>> its_offers;
{
@@ -3651,4 +3613,19 @@ bool routing_manager_impl::create_placeholder_event_and_subscribe(
return is_inserted;
}
+void routing_manager_impl::on_reboot(const boost::asio::ip::address &_address){
+ std::lock_guard<std::recursive_mutex> its_lock(endpoint_mutex_);
+ for (auto its_port : server_endpoints_) {
+ for (auto its_endpoint : its_port.second) {
+ if (its_endpoint.first == true) {
+ std::shared_ptr<tcp_server_endpoint_impl> endpoint = std::dynamic_pointer_cast<tcp_server_endpoint_impl>(its_endpoint.second);
+ if (endpoint) {
+ endpoint->stop_all_connections(_address);
+ }
+ }
+ }
+ }
+}
+
+
} // namespace vsomeip
diff --git a/implementation/routing/src/routing_manager_proxy.cpp b/implementation/routing/src/routing_manager_proxy.cpp
index 79e85f2..00359f9 100644
--- a/implementation/routing/src/routing_manager_proxy.cpp
+++ b/implementation/routing/src/routing_manager_proxy.cpp
@@ -43,7 +43,9 @@ routing_manager_proxy::routing_manager_proxy(routing_manager_host *_host) :
sender_(0),
receiver_(0),
register_application_timer_(io_),
- logger_(logger::get())
+ logger_(logger::get()),
+ request_debounce_timer_ (io_),
+ request_debounce_timer_running_(false)
{
}
@@ -111,6 +113,11 @@ void routing_manager_proxy::stop() {
is_started_ = false;
its_lock.unlock();
+ {
+ std::lock_guard<std::mutex> its_lock(request_timer_mutex_);
+ request_debounce_timer_.cancel();
+ }
+
if (receiver_) {
receiver_->stop();
}
@@ -251,12 +258,28 @@ void routing_manager_proxy::request_service(client_t _client,
_minor, _use_exclusive_proxy);
{
std::lock_guard<std::mutex> its_lock(state_mutex_);
- if (state_ == inner_state_type_e::ST_REGISTERED) {
- send_request_service(_client, _service, _instance, _major, _minor,
- _use_exclusive_proxy);
- }
+ size_t request_debouncing_time = configuration_->get_request_debouncing(host_->get_name());
service_data_t request = { _service, _instance, _major, _minor, _use_exclusive_proxy };
- pending_requests_.insert(request);
+ if (!request_debouncing_time) {
+ if (state_ == inner_state_type_e::ST_REGISTERED) {
+ std::set<service_data_t> requests;
+ requests.insert(request);
+ send_request_services(requests);
+ }
+ requests_.insert(request);
+ } else {
+ requests_to_debounce_.insert(request);
+ std::lock_guard<std::mutex> its_lock(request_timer_mutex_);
+ if (!request_debounce_timer_running_) {
+ request_debounce_timer_running_ = true;
+ request_debounce_timer_.expires_from_now(std::chrono::milliseconds(request_debouncing_time));
+ request_debounce_timer_.async_wait(
+ std::bind(
+ &routing_manager_proxy::request_debounce_timeout_cbk,
+ std::dynamic_pointer_cast<routing_manager_proxy>(shared_from_this()),
+ std::placeholders::_1));
+ }
+ }
}
}
@@ -266,18 +289,33 @@ void routing_manager_proxy::release_service(client_t _client,
{
std::lock_guard<std::mutex> its_lock(state_mutex_);
remove_pending_subscription(_service, _instance, 0xFFFF, ANY_EVENT);
- if (state_ == inner_state_type_e::ST_REGISTERED) {
- send_release_service(_client, _service, _instance);
- }
- auto it = pending_requests_.begin();
- while (it != pending_requests_.end()) {
+
+ bool pending(false);
+ auto it = requests_to_debounce_.begin();
+ while (it != requests_to_debounce_.end()) {
if (it->service_ == _service
&& it->instance_ == _instance) {
- break;
+ pending = true;
}
it++;
}
- if (it != pending_requests_.end()) pending_requests_.erase(it);
+ if (it != requests_to_debounce_.end()) requests_to_debounce_.erase(it);
+
+ if (!pending && state_ == inner_state_type_e::ST_REGISTERED) {
+ send_release_service(_client, _service, _instance);
+ }
+
+ {
+ auto it = requests_.begin();
+ while (it != requests_.end()) {
+ if (it->service_ == _service
+ && it->instance_ == _instance) {
+ break;
+ }
+ it++;
+ }
+ if (it != requests_.end()) requests_.erase(it);
+ }
}
}
@@ -754,6 +792,7 @@ void routing_manager_proxy::on_message(const byte_t *_data, length_t _size,
uint8_t is_remote_subscriber;
client_t routing_host_id = configuration_->get_id(configuration_->get_routing_host());
client_t its_subscriber;
+ bool its_reliable;
if (_size > VSOMEIP_COMMAND_SIZE_POS_MAX) {
its_command = _data[VSOMEIP_COMMAND_TYPE_POS];
@@ -1006,6 +1045,24 @@ void routing_manager_proxy::on_message(const byte_t *_data, length_t _size,
<< std::hex << std::setw(4) << std::setfill('0') << its_event << "]";
break;
+ case VSOMEIP_ID_REQUEST:
+ if (_size < VSOMEIP_ID_REQUEST_COMMAND_SIZE) {
+ VSOMEIP_WARNING << "Received a VSOMEIP_ID_REQUEST 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_major, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 4],
+ sizeof(its_major));
+ std::memcpy(&its_reliable, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 5],
+ sizeof(its_reliable));
+
+ send_identify_request(its_service, its_instance, its_major, its_reliable);
+
+ break;
+
default:
break;
}
@@ -1034,33 +1091,8 @@ void routing_manager_proxy::on_routing_info(const byte_t *_data,
}
}
}
- VSOMEIP_INFO << std::hex << "Application/Client " << get_client()
- << " is deregistered.";
-
- // inform host about its own registration state changes
- host_->on_state(static_cast<state_type_e>(inner_state_type_e::ST_DEREGISTERED));
-
- {
- std::lock_guard<std::mutex> its_lock(state_mutex_);
- state_ = inner_state_type_e::ST_DEREGISTERED;
- }
-
- // Notify stop() call about clean deregistration
- state_condition_.notify_one();
-
- // Remove all local connections/endpoints
- for (const auto client : clients_to_delete) {
- if (client != VSOMEIP_ROUTING_CLIENT) {
- remove_local(client);
- }
- }
- VSOMEIP_INFO << std::hex << "Application/Client " << get_client()
- <<": Reconnecting to routing manager.";
- std::lock_guard<std::mutex> its_lock(sender_mutex_);
- if (sender_) {
- sender_->restart();
- }
+ reconnect(clients_to_delete);
// Abort due to routing manager has stopped
return;
@@ -1242,6 +1274,33 @@ void routing_manager_proxy::on_routing_info(const byte_t *_data,
}
}
+void routing_manager_proxy::reconnect(const std::unordered_set<client_t> &_clients) {
+ // inform host about its own registration state changes
+ host_->on_state(static_cast<state_type_e>(inner_state_type_e::ST_DEREGISTERED));
+
+ {
+ std::lock_guard<std::mutex> its_lock(state_mutex_);
+ state_ = inner_state_type_e::ST_DEREGISTERED;
+ }
+
+ // Notify stop() call about clean deregistration
+ state_condition_.notify_one();
+
+ // Remove all local connections/endpoints
+ for (const auto its_client : _clients) {
+ if (its_client != VSOMEIP_ROUTING_CLIENT) {
+ remove_local(its_client);
+ }
+ }
+
+ VSOMEIP_INFO << std::hex << "Application/Client " << get_client()
+ <<": Reconnecting to routing manager.";
+ std::lock_guard<std::mutex> its_lock(sender_mutex_);
+ if (sender_) {
+ sender_->restart();
+ }
+}
+
void routing_manager_proxy::register_application() {
byte_t its_command[] = {
VSOMEIP_REGISTER_APPLICATION, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
@@ -1265,7 +1324,8 @@ void routing_manager_proxy::register_application() {
register_application_timer_.async_wait(
std::bind(
&routing_manager_proxy::register_application_timeout_cbk,
- this, std::placeholders::_1));
+ std::dynamic_pointer_cast<routing_manager_proxy>(shared_from_this()),
+ std::placeholders::_1));
}
}
}
@@ -1303,37 +1363,43 @@ void routing_manager_proxy::send_pong() const {
}
}
-void routing_manager_proxy::send_request_service(client_t _client, service_t _service,
- instance_t _instance, major_version_t _major,
- minor_version_t _minor, bool _use_exclusive_proxy) {
- (void)_client;
-
- byte_t its_command[VSOMEIP_REQUEST_SERVICE_COMMAND_SIZE];
- uint32_t its_size = VSOMEIP_REQUEST_SERVICE_COMMAND_SIZE
- - VSOMEIP_COMMAND_HEADER_SIZE;
+void routing_manager_proxy::send_request_services(std::set<service_data_t>& _requests) {
+ if (!_requests.size()) {
+ return;
+ }
+ uint32_t its_size = (VSOMEIP_REQUEST_SERVICE_COMMAND_SIZE - VSOMEIP_COMMAND_HEADER_SIZE)
+ * (uint32_t)_requests.size();
+ std::vector<byte_t> its_command(its_size + VSOMEIP_COMMAND_HEADER_SIZE);
its_command[VSOMEIP_COMMAND_TYPE_POS] = VSOMEIP_REQUEST_SERVICE;
std::memcpy(&its_command[VSOMEIP_COMMAND_CLIENT_POS], &client_,
sizeof(client_));
std::memcpy(&its_command[VSOMEIP_COMMAND_SIZE_POS_MIN], &its_size,
sizeof(its_size));
- std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS], &_service,
- sizeof(_service));
- std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 2], &_instance,
- sizeof(_instance));
- its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 4] = _major;
- std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 5], &_minor,
- sizeof(_minor));
- std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 9], &_use_exclusive_proxy,
- sizeof(_use_exclusive_proxy));
+
+ uint32_t entry_size = (sizeof(service_t) + sizeof(instance_t) + sizeof(major_version_t)
+ + sizeof(minor_version_t) + sizeof(bool));
+
+ int i = 0;
+ for (auto its_service : _requests) {
+ std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + (i * entry_size)], &its_service.service_,
+ sizeof(its_service.service_));
+ std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 2 + (i * entry_size)], &its_service.instance_,
+ sizeof(its_service.instance_));
+ its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 4 + (i * entry_size)] = its_service.major_;
+ std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 5 + (i * entry_size)], &its_service.minor_,
+ sizeof(its_service.minor_));
+ std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 9 + (i * entry_size)], &its_service.use_exclusive_proxy_,
+ sizeof(its_service.use_exclusive_proxy_));
+ ++i;
+ }
{
std::lock_guard<std::mutex> its_lock(sender_mutex_);
if (sender_) {
- sender_->send(its_command, sizeof(its_command));
+ sender_->send(&its_command[0], its_size + VSOMEIP_COMMAND_HEADER_SIZE);
}
}
-
}
void routing_manager_proxy::send_release_service(client_t _client, service_t _service,
@@ -1504,10 +1570,7 @@ void routing_manager_proxy::send_pending_commands() {
per.event_, per.eventgroups_,
per.is_field_, per.is_provided_);
- for (auto &po : pending_requests_) {
- send_request_service(client_, po.service_, po.instance_,
- po.major_, po.minor_, po.use_exclusive_proxy_);
- }
+ send_request_services(requests_);
}
void routing_manager_proxy::init_receiver() {
@@ -1681,4 +1744,59 @@ bool routing_manager_proxy::create_placeholder_event_and_subscribe(
}
return is_inserted;
}
+
+void routing_manager_proxy::request_debounce_timeout_cbk(
+ boost::system::error_code const &_error) {
+ std::lock_guard<std::mutex> its_lock(state_mutex_);
+ if (!_error) {
+ if (requests_to_debounce_.size()) {
+ if (state_ == inner_state_type_e::ST_REGISTERED) {
+ send_request_services(requests_to_debounce_);
+ requests_.insert(requests_to_debounce_.begin(),
+ requests_to_debounce_.end());
+ requests_to_debounce_.clear();
+ } else {
+ {
+ std::lock_guard<std::mutex> its_lock(request_timer_mutex_);
+ request_debounce_timer_running_ = true;
+ request_debounce_timer_.expires_from_now(std::chrono::milliseconds(configuration_->get_request_debouncing(host_->get_name())));
+ request_debounce_timer_.async_wait(
+ std::bind(
+ &routing_manager_proxy::request_debounce_timeout_cbk,
+ std::dynamic_pointer_cast<routing_manager_proxy>(shared_from_this()),
+ std::placeholders::_1));
+ return;
+ }
+ }
+ }
+ }
+ {
+ std::lock_guard<std::mutex> its_lock(request_timer_mutex_);
+ request_debounce_timer_running_ = false;
+ }
+}
+
+void routing_manager_proxy::register_client_error_handler(client_t _client,
+ const std::shared_ptr<endpoint> &_endpoint) {
+ _endpoint->register_error_handler(
+ std::bind(&routing_manager_proxy::handle_client_error, this, _client));
+}
+
+void routing_manager_proxy::handle_client_error(client_t _client) {
+ if (_client != VSOMEIP_ROUTING_CLIENT) {
+ VSOMEIP_INFO << "Client 0x" << std::hex << get_client()
+ << " handles a client error(" << std::hex << _client << ")";
+ remove_local(_client);
+ } else {
+ bool should_reconnect(true);
+ {
+ std::unique_lock<std::mutex> its_lock(state_mutex_);
+ should_reconnect = is_started_;
+ }
+ if (should_reconnect) {
+ reconnect(known_clients_);
+ }
+ }
+}
+
} // namespace vsomeip
diff --git a/implementation/routing/src/routing_manager_stub.cpp b/implementation/routing/src/routing_manager_stub.cpp
index 4146f59..526d6ce 100644
--- a/implementation/routing/src/routing_manager_stub.cpp
+++ b/implementation/routing/src/routing_manager_stub.cpp
@@ -46,6 +46,7 @@ routing_manager_stub::routing_manager_stub(
host_(_host),
io_(_host->get_io()),
watchdog_timer_(_host->get_io()),
+ client_id_timer_(_host->get_io()),
endpoint_(nullptr),
local_receiver_(nullptr),
configuration_(_configuration),
@@ -65,6 +66,20 @@ void routing_manager_stub::init() {
}
void routing_manager_stub::start() {
+ {
+ std::lock_guard<std::mutex> its_lock(used_client_ids_mutex_);
+ used_client_ids_ = utility::get_used_client_ids();
+ // Wait VSOMEIP_MAX_CONNECT_TIMEOUT * 2 and expect after that time
+ // that all client_ids are used have to be connected to the routing.
+ // Otherwise they can be marked as "erroneous client".
+ client_id_timer_.expires_from_now(std::chrono::milliseconds(VSOMEIP_MAX_CONNECT_TIMEOUT * 2));
+ client_id_timer_.async_wait(
+ std::bind(
+ &routing_manager_stub::on_client_id_timer_expired,
+ std::dynamic_pointer_cast<routing_manager_stub>(shared_from_this()),
+ std::placeholders::_1));
+ }
+
if(!endpoint_) {
// application has been stopped and started again
init_routing_endpoint();
@@ -109,6 +124,11 @@ void routing_manager_stub::stop() {
watchdog_timer_.cancel();
}
+ {
+ std::lock_guard<std::mutex> its_lock(used_client_ids_mutex_);
+ client_id_timer_.cancel();
+ }
+
if( !is_socket_activated_) {
endpoint_->stop();
endpoint_ = nullptr;
@@ -207,7 +227,6 @@ void routing_manager_stub::on_message(const byte_t *_data, length_t _size,
const byte_t *its_data;
uint32_t its_size;
bool its_reliable(false);
- bool use_exclusive_proxy(false);
subscription_type_e its_subscription_type;
bool is_remote_subscriber(false);
client_t its_client_from_header;
@@ -234,25 +253,11 @@ void routing_manager_stub::on_message(const byte_t *_data, length_t _size,
if (its_size <= _size - VSOMEIP_COMMAND_HEADER_SIZE) {
switch (its_command) {
case VSOMEIP_REGISTER_APPLICATION:
- {
- std::lock_guard<std::mutex> its_lock(client_registration_mutex_);
- VSOMEIP_INFO << "Application/Client "
- << std::hex << std::setw(4) << std::setfill('0')
- << its_client << " is registering.";
- pending_client_registrations_[its_client].push_back(registration_type_e::REGISTER);
- client_registration_condition_.notify_one();
- }
+ update_registration(its_client, registration_type_e::REGISTER);
break;
case VSOMEIP_DEREGISTER_APPLICATION:
- {
- std::lock_guard<std::mutex> its_lock(client_registration_mutex_);
- VSOMEIP_INFO << "Application/Client "
- << std::hex << std::setw(4) << std::setfill('0')
- << its_client << " is deregistering.";
- pending_client_registrations_[its_client].push_back(registration_type_e::DEREGISTER);
- client_registration_condition_.notify_one();
- }
+ update_registration(its_client, registration_type_e::DEREGISTER);
break;
case VSOMEIP_PONG:
@@ -468,31 +473,44 @@ void routing_manager_stub::on_message(const byte_t *_data, length_t _size,
break;
}
case VSOMEIP_REQUEST_SERVICE:
- if (_size != VSOMEIP_REQUEST_SERVICE_COMMAND_SIZE) {
- VSOMEIP_WARNING << "Received a REQUEST_SERVICE command with wrong size ~> skip!";
+ {
+ uint32_t entry_size = (sizeof(service_t) + sizeof(instance_t) + sizeof(major_version_t)
+ + sizeof(minor_version_t) + sizeof(bool));
+ uint32_t request_count(its_size / entry_size);
+ std::set<service_data_t> requests;
+ for (uint32_t i = 0; i < request_count; ++i) {
+ service_t its_service;
+ instance_t its_instance;
+ major_version_t its_major;
+ minor_version_t its_minor;
+ bool use_exclusive_proxy;
+ std::memcpy(&its_service, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + (i * entry_size)],
+ sizeof(its_service));
+ std::memcpy(&its_instance,
+ &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 2 + (i * entry_size)],
+ sizeof(its_instance));
+ std::memcpy(&its_major, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 4 + (i * entry_size)],
+ sizeof(its_major));
+ std::memcpy(&its_minor, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 5 + (i * entry_size)],
+ sizeof(its_minor));
+ std::memcpy(&use_exclusive_proxy, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 9 + (i * entry_size)],
+ sizeof(use_exclusive_proxy));
+ if (configuration_->is_client_allowed(its_client, its_service, its_instance)) {
+ host_->request_service(its_client, its_service, its_instance,
+ its_major, its_minor, use_exclusive_proxy);
+ service_data_t request = { its_service, its_instance,
+ its_major, its_minor, use_exclusive_proxy };
+ requests.insert(request);
+ } else {
+ VSOMEIP_WARNING << "Security: Client " << std::hex
+ << its_client << " requests service/instance "
+ << its_service << "/" << its_instance
+ << " which violates the security policy ~> Skip request!";
+ }
+ }
+ handle_requests(its_client, requests);
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_major, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 4],
- sizeof(its_major));
- std::memcpy(&its_minor, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 5],
- sizeof(its_minor));
- std::memcpy(&use_exclusive_proxy, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 9],
- sizeof(use_exclusive_proxy));
- if (configuration_->is_client_allowed(its_client, its_service, its_instance)) {
- host_->request_service(its_client, its_service, its_instance,
- its_major, its_minor, use_exclusive_proxy);
- } else {
- VSOMEIP_WARNING << "Security: Client " << std::hex
- << its_client << " requests service/instance "
- << its_service << "/" << its_instance
- << " which violates the security policy ~> Skip request!";
- }
- break;
case VSOMEIP_RELEASE_SERVICE:
if (_size != VSOMEIP_RELEASE_SERVICE_COMMAND_SIZE) {
@@ -594,7 +612,7 @@ void routing_manager_stub::on_message(const byte_t *_data, length_t _size,
&_data[VSOMEIP_COMMAND_PAYLOAD_POS + 4],
sizeof(its_reliable));
host_->on_identify_response(its_client, its_service, its_instance, its_reliable);
- VSOMEIP_TRACE << "ID RESPONSE("
+ VSOMEIP_INFO << "ID RESPONSE("
<< 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
@@ -673,13 +691,15 @@ void routing_manager_stub::client_registration_func(void) {
// the client acknowledged its registered state!
// Don't inform client if we deregister because of an client
// endpoint error to avoid writing in an already closed socket
- if (b != registration_type_e::DEREGISTER_ERROR_CASE) {
+ if (b != registration_type_e::DEREGISTER_ON_ERROR) {
std::lock_guard<std::mutex> its_guard(routing_info_mutex_);
- send_routing_info_delta(r.first,
+ create_client_routing_info(r.first);
+ insert_client_routing_info(r.first,
b == registration_type_e::REGISTER ?
routing_info_entry_e::RIE_ADD_CLIENT :
routing_info_entry_e::RIE_DEL_CLIENT,
r.first);
+ send_client_routing_info(r.first);
}
if (b != registration_type_e::REGISTER) {
{
@@ -689,8 +709,10 @@ void routing_manager_stub::client_registration_func(void) {
for (auto its_client : its_connection->second) {
if (its_client != r.first &&
its_client != VSOMEIP_ROUTING_CLIENT) {
- send_routing_info_delta(its_client,
+ create_client_routing_info(its_client);
+ insert_client_routing_info(its_client,
routing_info_entry_e::RIE_DEL_CLIENT, r.first);
+ send_client_routing_info(its_client);
}
}
connection_matrix_.erase(r.first);
@@ -701,10 +723,9 @@ void routing_manager_stub::client_registration_func(void) {
service_requests_.erase(r.first);
}
host_->remove_local(r.first);
- }
- if (b == registration_type_e::DEREGISTER_ERROR_CASE) {
- utility::release_client_id(r.first);
- host_->confirm_pending_offers(r.first);
+ if (b == registration_type_e::DEREGISTER_ON_ERROR) {
+ utility::release_client_id(r.first);
+ }
}
}
}
@@ -837,85 +858,33 @@ void routing_manager_stub::on_stop_offer_service(client_t _client,
}
}
-void routing_manager_stub::send_routing_info_delta(client_t _target,
- routing_info_entry_e _entry,
- client_t _client, service_t _service, instance_t _instance,
- major_version_t _major, minor_version_t _minor) {
- std::shared_ptr<endpoint> its_endpoint = host_->find_local(_target);
- if (its_endpoint) {
- connection_matrix_[_target].insert(_client);
-
- std::vector<byte_t> its_command;
-
- // Routing command
- its_command.push_back(VSOMEIP_ROUTING_INFO);
-
- // Sender client
- client_t client = get_client();
- for (uint32_t i = 0; i < sizeof(client_t); ++i) {
- its_command.push_back(
- reinterpret_cast<const byte_t*>(&client)[i]);
- }
-
- // Overall size placeholder
- byte_t size_placeholder = 0x0;
- for (uint32_t i = 0; i < sizeof(uint32_t); ++i) {
- its_command.push_back(size_placeholder);
- }
-
- // Routing Info State Change
- for (uint32_t i = 0; i < sizeof(routing_info_entry_e); ++i) {
- its_command.push_back(
- reinterpret_cast<const byte_t*>(&_entry)[i]);
- }
+void routing_manager_stub::create_client_routing_info(const client_t _target) {
+ std::vector<byte_t> its_command;
+ its_command.push_back(VSOMEIP_ROUTING_INFO);
- std::size_t its_size_pos = its_command.size();
- std::size_t its_entry_size = its_command.size();
+ // Sender client
+ client_t client = get_client();
+ for (uint32_t i = 0; i < sizeof(client_t); ++i) {
+ its_command.push_back(
+ reinterpret_cast<const byte_t*>(&client)[i]);
+ }
- // Client size placeholder
- byte_t placeholder = 0x0;
- for (uint32_t i = 0; i < sizeof(uint32_t); ++i) {
- its_command.push_back(placeholder);
- }
- // Client
- for (uint32_t i = 0; i < sizeof(client_t); ++i) {
- its_command.push_back(
- reinterpret_cast<const byte_t*>(&_client)[i]);
- }
+ // Overall size placeholder
+ byte_t size_placeholder = 0x0;
+ for (uint32_t i = 0; i < sizeof(uint32_t); ++i) {
+ its_command.push_back(size_placeholder);
+ }
- if (_entry == routing_info_entry_e::RIE_ADD_SERVICE_INSTANCE ||
- _entry == routing_info_entry_e::RIE_DEL_SERVICE_INSTANCE) {
- //Service
- uint32_t its_service_entry_size = uint32_t(sizeof(service_t)
- + sizeof(instance_t) + sizeof(major_version_t) + sizeof(minor_version_t));
- for (uint32_t i = 0; i < sizeof(its_service_entry_size); ++i) {
- its_command.push_back(
- reinterpret_cast<const byte_t*>(&its_service_entry_size)[i]);
- }
- for (uint32_t i = 0; i < sizeof(service_t); ++i) {
- its_command.push_back(
- reinterpret_cast<const byte_t*>(&_service)[i]);
- }
- // Instance
- for (uint32_t i = 0; i < sizeof(instance_t); ++i) {
- its_command.push_back(
- reinterpret_cast<const byte_t*>(&_instance)[i]);
- }
- // Major version
- for (uint32_t i = 0; i < sizeof(major_version_t); ++i) {
- its_command.push_back(
- reinterpret_cast<const byte_t*>(&_major)[i]);
- }
- // Minor version
- for (uint32_t i = 0; i < sizeof(minor_version_t); ++i) {
- its_command.push_back(
- reinterpret_cast<const byte_t*>(&_minor)[i]);
- }
- }
+ client_routing_info_[_target] = its_command;
+}
- // File client size
- its_entry_size = its_command.size() - its_entry_size - uint32_t(sizeof(uint32_t));
- std::memcpy(&its_command[its_size_pos], &its_entry_size, sizeof(uint32_t));
+void routing_manager_stub::send_client_routing_info(const client_t _target) {
+ if (client_routing_info_.find(_target) == client_routing_info_.end()) {
+ return;
+ }
+ std::shared_ptr<endpoint> its_endpoint = host_->find_local(_target);
+ if (its_endpoint) {
+ auto its_command = client_routing_info_[_target];
// File overall size
std::size_t its_size = its_command.size() - VSOMEIP_COMMAND_PAYLOAD_POS;
@@ -937,9 +906,83 @@ void routing_manager_stub::send_routing_info_delta(client_t _target,
} else {
VSOMEIP_ERROR << "Routing info exceeds maximum message size: Can't send!";
}
+
+ client_routing_info_.erase(_target);
}
}
+void routing_manager_stub::insert_client_routing_info(client_t _target,
+ routing_info_entry_e _entry,
+ client_t _client, service_t _service,
+ instance_t _instance,
+ major_version_t _major,
+ minor_version_t _minor) {
+
+ if (client_routing_info_.find(_target) == client_routing_info_.end()) {
+ return;
+ }
+
+ connection_matrix_[_target].insert(_client);
+
+ auto its_command = client_routing_info_[_target];
+
+ // Routing Info State Change
+ for (uint32_t i = 0; i < sizeof(routing_info_entry_e); ++i) {
+ its_command.push_back(
+ reinterpret_cast<const byte_t*>(&_entry)[i]);
+ }
+
+ std::size_t its_size_pos = its_command.size();
+ std::size_t its_entry_size = its_command.size();
+
+ // Client size placeholder
+ byte_t placeholder = 0x0;
+ for (uint32_t i = 0; i < sizeof(uint32_t); ++i) {
+ its_command.push_back(placeholder);
+ }
+ // Client
+ for (uint32_t i = 0; i < sizeof(client_t); ++i) {
+ its_command.push_back(
+ reinterpret_cast<const byte_t*>(&_client)[i]);
+ }
+
+ if (_entry == routing_info_entry_e::RIE_ADD_SERVICE_INSTANCE ||
+ _entry == routing_info_entry_e::RIE_DEL_SERVICE_INSTANCE) {
+ //Service
+ uint32_t its_service_entry_size = uint32_t(sizeof(service_t)
+ + sizeof(instance_t) + sizeof(major_version_t) + sizeof(minor_version_t));
+ for (uint32_t i = 0; i < sizeof(its_service_entry_size); ++i) {
+ its_command.push_back(
+ reinterpret_cast<const byte_t*>(&its_service_entry_size)[i]);
+ }
+ for (uint32_t i = 0; i < sizeof(service_t); ++i) {
+ its_command.push_back(
+ reinterpret_cast<const byte_t*>(&_service)[i]);
+ }
+ // Instance
+ for (uint32_t i = 0; i < sizeof(instance_t); ++i) {
+ its_command.push_back(
+ reinterpret_cast<const byte_t*>(&_instance)[i]);
+ }
+ // Major version
+ for (uint32_t i = 0; i < sizeof(major_version_t); ++i) {
+ its_command.push_back(
+ reinterpret_cast<const byte_t*>(&_major)[i]);
+ }
+ // Minor version
+ for (uint32_t i = 0; i < sizeof(minor_version_t); ++i) {
+ its_command.push_back(
+ reinterpret_cast<const byte_t*>(&_minor)[i]);
+ }
+ }
+
+ // File client size
+ its_entry_size = its_command.size() - its_entry_size - uint32_t(sizeof(uint32_t));
+ std::memcpy(&its_command[its_size_pos], &its_entry_size, sizeof(uint32_t));
+
+ client_routing_info_[_target] = its_command;
+}
+
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) {
@@ -958,14 +1001,18 @@ void routing_manager_stub::inform_requesters(client_t _hoster, service_t _servic
if (_hoster != VSOMEIP_ROUTING_CLIENT &&
_hoster != host_->get_client()) {
if (!is_already_connected(_hoster, its_client.first)) {
- send_routing_info_delta(_hoster,
+ create_client_routing_info(_hoster);
+ insert_client_routing_info(_hoster,
routing_info_entry_e::RIE_ADD_CLIENT,
its_client.first);
+ send_client_routing_info(_hoster);
}
}
}
- send_routing_info_delta(its_client.first, _entry, _hoster,
+ create_client_routing_info(its_client.first);
+ insert_client_routing_info(its_client.first, _entry, _hoster,
_service, _instance, _major, _minor);
+ send_client_routing_info(its_client.first);
}
}
}
@@ -1223,7 +1270,7 @@ void routing_manager_stub::check_watchdog() {
}
}
for (auto i : lost) {
- deregister_erroneous_client(i);
+ host_->handle_client_error(i);
}
start_watchdog();
};
@@ -1373,10 +1420,10 @@ void routing_manager_stub::on_ping_timer_expired(
}
for (const client_t client : timed_out_clients) {
- // client did not respond to ping. Report client_endpoint_error
- // in order to accept pending offers trying to replace the offers of
- // the now not responding client
- host_->on_clientendpoint_error(client);
+ // Client did not respond to ping. Report client_error in order to
+ // accept pending offers trying to replace the offers of the client
+ // that seems to be gone.
+ host_->handle_client_error(client);
}
if (pinged_clients_remaining) {
boost::system::error_code ec;
@@ -1435,72 +1482,98 @@ bool routing_manager_stub::is_registered(client_t _client) const {
return (routing_info_.find(_client) != routing_info_.end());
}
-void routing_manager_stub::deregister_erroneous_client(client_t _client) {
- std::lock_guard<std::mutex> its_lock(client_registration_mutex_);
+void routing_manager_stub::update_registration(client_t _client,
+ registration_type_e _type) {
+
VSOMEIP_INFO << "Application/Client "
- << std::hex << std::setw(4) << std::setfill('0')
- << _client << " is deregistering.";
- pending_client_registrations_[_client].push_back(registration_type_e::DEREGISTER_ERROR_CASE);
+ << std::hex << std::setw(4) << std::setfill('0') << _client
+ << " is "
+ << (_type == registration_type_e::REGISTER ?
+ "registering." : "deregistering.");
+
+ std::lock_guard<std::mutex> its_lock(client_registration_mutex_);
+ pending_client_registrations_[_client].push_back(_type);
client_registration_condition_.notify_one();
+
+ if (_type != registration_type_e::REGISTER) {
+ std::lock_guard<std::mutex> its_lock(used_client_ids_mutex_);
+ used_client_ids_.erase(_client);
+ }
}
client_t routing_manager_stub::get_client() const {
return host_->get_client();
}
-void routing_manager_stub::on_request_service(client_t _client, service_t _service,
- instance_t _instance, major_version_t _major,
- minor_version_t _minor) {
-
+void routing_manager_stub::handle_requests(const client_t _client, std::set<service_data_t>& _requests) {
+ if (!_requests.size()) {
+ return;
+ }
std::lock_guard<std::mutex> its_guard(routing_info_mutex_);
- service_requests_[_client][_service][_instance] = std::make_pair(_major, _minor);
-
- for (auto found_client : routing_info_) {
- auto found_service = found_client.second.second.find(_service);
- if (found_service != found_client.second.second.end()) {
- if (_instance == ANY_INSTANCE) {
- if (found_client.first != VSOMEIP_ROUTING_CLIENT &&
- found_client.first != host_->get_client()) {
- if (!is_already_connected(found_client.first, _client)) {
- send_routing_info_delta(found_client.first,
- routing_info_entry_e::RIE_ADD_CLIENT, _client);
- }
- }
- if (_client != VSOMEIP_ROUTING_CLIENT &&
- _client != host_->get_client()) {
- for (auto instance : found_service->second) {
- send_routing_info_delta(_client,
- routing_info_entry_e::RIE_ADD_SERVICE_INSTANCE,
- found_client.first, _service, instance.first,
- instance.second.first, instance.second.second);
- }
- }
-
- break;
- } else {
- auto found_instance = found_service->second.find(_instance);
- if (found_instance != found_service->second.end()) {
+ create_client_routing_info(_client);
+ for (auto request : _requests) {
+ service_requests_[_client][request.service_][request.instance_]
+ = std::make_pair(request.major_, request.minor_);
+ for (auto found_client : routing_info_) {
+ auto found_service = found_client.second.second.find(request.service_);
+ if (found_service != found_client.second.second.end()) {
+ if (request.instance_ == ANY_INSTANCE) {
if (found_client.first != VSOMEIP_ROUTING_CLIENT &&
found_client.first != host_->get_client()) {
if (!is_already_connected(found_client.first, _client)) {
- send_routing_info_delta(found_client.first,
+ if (_client == found_client.first) {
+ insert_client_routing_info(found_client.first,
routing_info_entry_e::RIE_ADD_CLIENT, _client);
+ } else {
+ create_client_routing_info(found_client.first);
+ insert_client_routing_info(found_client.first,
+ routing_info_entry_e::RIE_ADD_CLIENT, _client);
+ send_client_routing_info(found_client.first);
+ }
}
}
if (_client != VSOMEIP_ROUTING_CLIENT &&
_client != host_->get_client()) {
- send_routing_info_delta(_client,
- routing_info_entry_e::RIE_ADD_SERVICE_INSTANCE,
- found_client.first, _service, _instance,
- found_instance->second.first,
- found_instance->second.second);
+ for (auto instance : found_service->second) {
+ insert_client_routing_info(_client,
+ routing_info_entry_e::RIE_ADD_SERVICE_INSTANCE,
+ found_client.first, request.service_, instance.first,
+ instance.second.first, instance.second.second);
+ }
}
-
break;
+ } else {
+ auto found_instance = found_service->second.find(request.instance_);
+ if (found_instance != found_service->second.end()) {
+ if (found_client.first != VSOMEIP_ROUTING_CLIENT &&
+ found_client.first != host_->get_client()) {
+ if (!is_already_connected(found_client.first, _client)) {
+ if (_client == found_client.first) {
+ insert_client_routing_info(found_client.first,
+ routing_info_entry_e::RIE_ADD_CLIENT, _client);
+ } else {
+ create_client_routing_info(found_client.first);
+ insert_client_routing_info(found_client.first,
+ routing_info_entry_e::RIE_ADD_CLIENT, _client);
+ send_client_routing_info(found_client.first);
+ }
+ }
+ }
+ if (_client != VSOMEIP_ROUTING_CLIENT &&
+ _client != host_->get_client()) {
+ insert_client_routing_info(_client,
+ routing_info_entry_e::RIE_ADD_SERVICE_INSTANCE,
+ found_client.first, request.service_, request.instance_,
+ found_instance->second.first,
+ found_instance->second.second);
+ }
+ break;
+ }
}
}
}
}
+ send_client_routing_info(_client);
}
#ifndef _WIN32
@@ -1509,4 +1582,55 @@ bool routing_manager_stub::check_credentials(client_t _client, uid_t _uid, gid_t
}
#endif
+void routing_manager_stub::send_identify_request_command(std::shared_ptr<vsomeip::endpoint> _target,
+ service_t _service, instance_t _instance, major_version_t _major, bool _reliable) {
+ if (_target) {
+ byte_t its_command[VSOMEIP_ID_REQUEST_COMMAND_SIZE];
+ uint32_t its_size = VSOMEIP_ID_REQUEST_COMMAND_SIZE
+ - VSOMEIP_COMMAND_HEADER_SIZE;
+ its_command[VSOMEIP_COMMAND_TYPE_POS] = VSOMEIP_ID_REQUEST;
+ client_t client = get_client();
+ 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], &_major,
+ sizeof(_major));
+ std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 5], &_reliable,
+ sizeof(_reliable));
+
+ _target->send(its_command, sizeof(its_command));
+ }
+}
+
+void routing_manager_stub::on_client_id_timer_expired(boost::system::error_code const &_error) {
+ std::set<client_t> used_client_ids;
+ {
+ std::lock_guard<std::mutex> its_lock(used_client_ids_mutex_);
+ used_client_ids = used_client_ids_;
+ used_client_ids_.clear();
+ }
+
+ std::set<client_t> erroneous_clients;
+ if (!_error) {
+ std::lock_guard<std::mutex> its_lock(routing_info_mutex_);
+ for (auto client : used_client_ids) {
+ if (client != VSOMEIP_ROUTING_CLIENT && client != get_client()) {
+ if (routing_info_.find(client) == routing_info_.end()) {
+ erroneous_clients.insert(client);
+ }
+ }
+ }
+ }
+ for (auto client : erroneous_clients) {
+ VSOMEIP_WARNING << "Routinger Manager 0x" << std::hex << get_client()
+ << " : Release died Client 0x" << std::hex << client;
+ host_->handle_client_error(client);
+ }
+}
+
} // namespace vsomeip
diff --git a/implementation/runtime/src/application_impl.cpp b/implementation/runtime/src/application_impl.cpp
index d4d4ed7..3ae0d61 100644
--- a/implementation/runtime/src/application_impl.cpp
+++ b/implementation/runtime/src/application_impl.cpp
@@ -973,9 +973,7 @@ void application_impl::on_state(state_type_e _state) {
void application_impl::on_availability(service_t _service, instance_t _instance,
bool _is_available, major_version_t _major, minor_version_t _minor) {
-
std::vector<availability_handler_t> its_handlers;
-
{
std::lock_guard<std::mutex> availability_lock(availability_mutex_);
if (_is_available == is_available_unlocked(_service, _instance, _major, _minor)) {
diff --git a/implementation/service_discovery/include/service_discovery_host.hpp b/implementation/service_discovery/include/service_discovery_host.hpp
index 710e4e7..0e1de9e 100644
--- a/implementation/service_discovery/include/service_discovery_host.hpp
+++ b/implementation/service_discovery/include/service_discovery_host.hpp
@@ -44,7 +44,7 @@ public:
virtual bool send_to(const std::shared_ptr<endpoint_definition> &_target,
const byte_t *_data, uint32_t _size, uint16_t _sd_port) = 0;
- virtual std::chrono::milliseconds add_routing_info(service_t _service, instance_t _instance,
+ virtual void add_routing_info(service_t _service, instance_t _instance,
major_version_t _major, minor_version_t _minor, ttl_t _ttl,
const boost::asio::ip::address &_reliable_address,
uint16_t _reliable_port,
@@ -81,6 +81,9 @@ public:
virtual void expire_subscriptions(const boost::asio::ip::address &_address) = 0;
virtual void expire_services(const boost::asio::ip::address &_address) = 0;
+ virtual void on_reboot(const boost::asio::ip::address &_address) = 0;
+
+
virtual bool on_subscribe_accepted(service_t _service, instance_t _instance,
eventgroup_t _eventgroup, std::shared_ptr<endpoint_definition> _target,
const std::chrono::steady_clock::time_point &_expiration) = 0;
diff --git a/implementation/service_discovery/src/service_discovery_impl.cpp b/implementation/service_discovery/src/service_discovery_impl.cpp
index 9fc955d..7318eda 100644
--- a/implementation/service_discovery/src/service_discovery_impl.cpp
+++ b/implementation/service_discovery/src/service_discovery_impl.cpp
@@ -1039,6 +1039,7 @@ void service_discovery_impl::on_message(const byte_t *_data, length_t _length,
its_message->get_reboot_flag(), its_message->get_session())) {
host_->expire_subscriptions(_sender);
host_->expire_services(_sender);
+ host_->on_reboot(_sender);
}
std::chrono::milliseconds expired = stop_ttl_timer();
@@ -1214,10 +1215,14 @@ void service_discovery_impl::process_offerservice_serviceentry(
its_request->set_sent_counter(std::uint8_t(repetitions_max_ + 1));
}
- smallest_ttl_ = host_->add_routing_info(_service, _instance,
+ host_->add_routing_info(_service, _instance,
_major, _minor, _ttl,
_reliable_address, _reliable_port,
_unreliable_address, _unreliable_port);
+ const std::chrono::milliseconds its_precise_ttl(_ttl * 1000);
+ if (its_precise_ttl < smallest_ttl_) {
+ smallest_ttl_ = its_precise_ttl;
+ }
std::lock_guard<std::mutex> its_lock(subscribed_mutex_);
auto found_service = subscribed_.find(_service);
diff --git a/implementation/utility/include/utility.hpp b/implementation/utility/include/utility.hpp
index a638860..e48be1a 100644
--- a/implementation/utility/include/utility.hpp
+++ b/implementation/utility/include/utility.hpp
@@ -8,6 +8,7 @@
#include <memory>
#include <vector>
+#include <set>
#include <vsomeip/enumeration_types.hpp>
#include <vsomeip/message.hpp>
@@ -88,6 +89,7 @@ public:
static client_t request_client_id(const std::shared_ptr<configuration> &_config,
const std::string &_name, client_t _client);
static void release_client_id(client_t _client);
+ static std::set<client_t> get_used_client_ids();
static inline bool is_valid_message_type(message_type_e _type) {
return (_type == message_type_e::MT_REQUEST
diff --git a/implementation/utility/src/utility.cpp b/implementation/utility/src/utility.cpp
index 8fc48db..f4f4449 100644
--- a/implementation/utility/src/utility.cpp
+++ b/implementation/utility/src/utility.cpp
@@ -7,6 +7,7 @@
#include <iostream>
#else
#include <dlfcn.h>
+ #include <signal.h>
#include <sys/mman.h>
#include <thread>
#include <sstream>
@@ -306,8 +307,6 @@ bool utility::auto_configuration_init(const std::shared_ptr<configuration> &_con
the_configuration_data__->routing_manager_host_ = 0x0000;
std::string its_name = _config->get_routing_host();
- if (its_name == "")
- the_configuration_data__->routing_manager_host_ = the_configuration_data__->client_base_;
its_configuration_refs__++;
@@ -340,7 +339,6 @@ bool utility::auto_configuration_init(const std::shared_ptr<configuration> &_con
VSOMEIP_ERROR << "utility::auto_configuration_init: "
"ftruncate failed: " << std::strerror(errno);
} else {
-
void *its_segment = mmap(0, sizeof(configuration_data_t),
PROT_READ | PROT_WRITE, MAP_SHARED,
its_descriptor, 0);
@@ -460,6 +458,43 @@ bool utility::is_used_client_id(client_t _client) {
return false;
}
+std::set<client_t> utility::get_used_client_ids() {
+ std::set<client_t> clients;
+
+ std::unique_lock<CriticalSection> its_lock(its_local_configuration_mutex__);
+
+ if (the_configuration_data__ != nullptr) {
+#ifdef _WIN32
+ DWORD waitResult = WaitForSingleObject(configuration_data_mutex, INFINITE);
+ assert(waitResult == WAIT_OBJECT_0);
+ (void)waitResult;
+#else
+ if (EOWNERDEAD == pthread_mutex_lock(&the_configuration_data__->mutex_)) {
+ VSOMEIP_WARNING << "utility::request_client_id EOWNERDEAD";
+ check_client_id_consistency();
+ if (0 != pthread_mutex_consistent(&the_configuration_data__->mutex_)) {
+ VSOMEIP_ERROR << "pthread_mutex_consistent() failed ";
+ }
+ }
+#endif
+ for (int i = 0;
+ i < the_configuration_data__->max_used_client_ids_index_;
+ i++) {
+ clients.insert(the_configuration_data__->used_client_ids_[i]);
+ }
+
+#ifdef _WIN32
+ BOOL releaseResult = ReleaseMutex(configuration_data_mutex);
+ assert(releaseResult);
+ (void)releaseResult;
+#else
+ pthread_mutex_unlock(&the_configuration_data__->mutex_);
+#endif
+ }
+
+ return clients;
+}
+
client_t utility::request_client_id(const std::shared_ptr<configuration> &_config, const std::string &_name, client_t _client) {
std::unique_lock<CriticalSection> its_lock(its_local_configuration_mutex__);
@@ -476,7 +511,18 @@ client_t utility::request_client_id(const std::shared_ptr<configuration> &_confi
VSOMEIP_ERROR << "pthread_mutex_consistent() failed ";
}
}
+
+ pid_t pid = getpid();
+ if (the_configuration_data__->pid_ != 0) {
+ if (pid != the_configuration_data__->pid_) {
+ if (kill(the_configuration_data__->pid_, 0) == -1) {
+ VSOMEIP_WARNING << "Routing Manager seems to be inactive. Taking over...";
+ the_configuration_data__->routing_manager_host_ = 0x0000;
+ }
+ }
+ }
#endif
+
const std::string its_name = _config->get_routing_host();
bool set_client_as_manager_host(false);
if (its_name != "" && its_name == _name) {
@@ -572,6 +618,9 @@ client_t utility::request_client_id(const std::shared_ptr<configuration> &_confi
if (set_client_as_manager_host) {
the_configuration_data__->routing_manager_host_ = _client;
+#ifndef _WIN32
+ the_configuration_data__->pid_ = pid;
+#endif
}
the_configuration_data__->used_client_ids_[
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 7f841af..41f253a 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -514,6 +514,80 @@ else()
)
endif()
##############################################################################
+# restart_routing-test
+##############################################################################
+
+if(NOT ${TESTS_BAT})
+ set(TEST_RESTART_ROUTING_NAME restart_routing_test)
+
+ set(TEST_RESTART_ROUTING_SERVICE restart_routing_test_service)
+ add_executable(${TEST_RESTART_ROUTING_SERVICE} restart_routing_tests/${TEST_RESTART_ROUTING_SERVICE}.cpp)
+ target_link_libraries(${TEST_RESTART_ROUTING_SERVICE}
+ vsomeip
+ ${Boost_LIBRARIES}
+ ${DL_LIBRARY}
+ ${TEST_LINK_LIBRARIES}
+ )
+
+ # Copy config file for service into $BUILDDIR/test
+ set(TEST_RESTART_ROUTING_SERVICE_CONFIG_FILE ${TEST_RESTART_ROUTING_SERVICE}.json)
+ copy_to_builddir(
+ ${PROJECT_SOURCE_DIR}/test/restart_routing_tests/${TEST_RESTART_ROUTING_SERVICE_CONFIG_FILE}
+ ${PROJECT_BINARY_DIR}/test/${TEST_RESTART_ROUTING_SERVICE_CONFIG_FILE}
+ ${TEST_RESTART_ROUTING_SERVICE}
+ )
+
+ # Copy bashscript to start service into $BUILDDIR/test
+ set(TEST_RESTART_ROUTING_SERVICE_START_SCRIPT ${TEST_RESTART_ROUTING_SERVICE}_start.sh)
+ copy_to_builddir(
+ ${PROJECT_SOURCE_DIR}/test/restart_routing_tests/${TEST_RESTART_ROUTING_SERVICE_START_SCRIPT}
+ ${PROJECT_BINARY_DIR}/test/${TEST_RESTART_ROUTING_SERVICE_START_SCRIPT}
+ ${TEST_RESTART_ROUTING_SERVICE}
+ )
+
+ set(TEST_RESTART_ROUTING_CLIENT restart_routing_test_client)
+ add_executable(${TEST_RESTART_ROUTING_CLIENT}
+ restart_routing_tests/${TEST_RESTART_ROUTING_CLIENT}.cpp
+ )
+ target_link_libraries(${TEST_RESTART_ROUTING_CLIENT}
+ vsomeip
+ ${Boost_LIBRARIES}
+ ${DL_LIBRARY}
+ ${TEST_LINK_LIBRARIES}
+ )
+
+ # Copy config file for client into $BUILDDIR/test
+ set(TEST_RESTART_ROUTING_CLIENT_CONFIG_FILE ${TEST_RESTART_ROUTING_CLIENT}.json)
+ copy_to_builddir(
+ ${PROJECT_SOURCE_DIR}/test/restart_routing_tests/${TEST_RESTART_ROUTING_CLIENT_CONFIG_FILE}
+ ${PROJECT_BINARY_DIR}/test/${TEST_RESTART_ROUTING_CLIENT_CONFIG_FILE}
+ ${TEST_RESTART_ROUTING_CLIENT}
+ )
+
+ # Copy bashscript to start client into $BUILDDIR/test
+ set(TEST_RESTART_ROUTING_CLIENT_START_SCRIPT ${TEST_RESTART_ROUTING_CLIENT}_start.sh)
+ copy_to_builddir(
+ ${PROJECT_SOURCE_DIR}/test/restart_routing_tests/${TEST_RESTART_ROUTING_CLIENT_START_SCRIPT}
+ ${PROJECT_BINARY_DIR}/test/${TEST_RESTART_ROUTING_CLIENT_START_SCRIPT}
+ ${TEST_RESTART_ROUTING_CLIENT}
+ )
+
+ # Copy bashscript to start client and server $BUILDDIR/test
+ set(TEST_RESTART_ROUTING_STARTER restart_routing_test_starter.sh)
+ copy_to_builddir(${PROJECT_SOURCE_DIR}/test/restart_routing_tests/${TEST_RESTART_ROUTING_STARTER}
+ ${PROJECT_BINARY_DIR}/test/${TEST_RESTART_ROUTING_STARTER}
+ ${TEST_RESTART_ROUTING_CLIENT}
+ )
+
+ # Copy config file for autoconfig into $BUILDDIR/test
+ set(TEST_RESTART_ROUTING_AUTO_CONFIG_FILE ${TEST_RESTART_ROUTING_NAME}_autoconfig.json)
+ copy_to_builddir(
+ ${PROJECT_SOURCE_DIR}/test/restart_routing_tests/${TEST_RESTART_ROUTING_AUTO_CONFIG_FILE}
+ ${PROJECT_BINARY_DIR}/test/${TEST_RESTART_ROUTING_AUTO_CONFIG_FILE}
+ ${TEST_RESTART_ROUTING_CLIENT}
+ )
+endif()
+##############################################################################
# payload-test
##############################################################################
@@ -1712,6 +1786,8 @@ 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_RESTART_ROUTING_SERVICE})
+ add_dependencies(build_tests ${TEST_RESTART_ROUTING_CLIENT})
else()
add_dependencies(build_tests ${TEST_LOCAL_ROUTING_SERVICE})
add_dependencies(build_tests ${TEST_LOCAL_ROUTING_CLIENT})
@@ -2071,6 +2147,11 @@ if(NOT ${TESTS_BAT})
add_test(NAME ${TEST_OFFER_NAME}_external
COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_OFFER_EXTERNAL_MASTER_STARTER})
set_tests_properties(${TEST_OFFER_NAME}_local PROPERTIES TIMEOUT 360)
+
+ # Restart-Routing tests
+ add_test(NAME ${TEST_RESTART_ROUTING_NAME}
+ COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_RESTART_ROUTING_STARTER}
+ )
else()
# Routing tests
add_test(NAME ${TEST_LOCAL_ROUTING_NAME}
diff --git a/test/restart_routing_tests/restart_routing_test_autoconfig.json b/test/restart_routing_tests/restart_routing_test_autoconfig.json
new file mode 100644
index 0000000..f50dba7
--- /dev/null
+++ b/test/restart_routing_tests/restart_routing_test_autoconfig.json
@@ -0,0 +1,24 @@
+{
+ "unicast" : "127.0.0.1",
+ "netmask" : "255.255.255.0",
+ "logging" :
+ {
+ "level" : "warning",
+ "console" : "true",
+ "file" :
+ {
+ "enable" : "true",
+ "path" : "/var/log/vsomeip.log"
+ },
+
+ "dlt" : "true"
+ },
+
+ "service-discovery" :
+ {
+ "enable" : "false",
+ "multicast" : "224.0.0.1",
+ "port" : "30491",
+ "protocol" : "udp"
+ }
+}
diff --git a/test/restart_routing_tests/restart_routing_test_client.cpp b/test/restart_routing_tests/restart_routing_test_client.cpp
new file mode 100644
index 0000000..a8c0acc
--- /dev/null
+++ b/test/restart_routing_tests/restart_routing_test_client.cpp
@@ -0,0 +1,158 @@
+// 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/.
+
+#include "restart_routing_test_client.hpp"
+
+routing_restart_test_client::routing_restart_test_client()
+ : app_(vsomeip::runtime::get()->create_application()),
+ is_available_(false),
+ sender_(std::bind(&routing_restart_test_client::run, this)),
+ received_responses_(0) {
+
+}
+
+bool routing_restart_test_client::init() {
+ if (!app_->init()) {
+ ADD_FAILURE() << "Couldn't initialize application";
+ return false;
+ }
+
+ app_->register_state_handler(
+ std::bind(&routing_restart_test_client::on_state, this,
+ std::placeholders::_1));
+
+ app_->register_message_handler(vsomeip::ANY_SERVICE,
+ vsomeip_test::TEST_SERVICE_INSTANCE_ID, vsomeip::ANY_METHOD,
+ std::bind(&routing_restart_test_client::on_message, this,
+ std::placeholders::_1));
+
+ app_->register_availability_handler(vsomeip_test::TEST_SERVICE_SERVICE_ID,
+ vsomeip_test::TEST_SERVICE_INSTANCE_ID,
+ std::bind(&routing_restart_test_client::on_availability, this,
+ std::placeholders::_1, std::placeholders::_2,
+ std::placeholders::_3));
+ return true;
+}
+
+void routing_restart_test_client::start() {
+ VSOMEIP_INFO << "Starting...";
+
+ app_->start();
+}
+
+void routing_restart_test_client::stop() {
+ VSOMEIP_INFO << "Stopping...";
+
+ shutdown_service();
+
+ std::this_thread::sleep_for(std::chrono::milliseconds(100));
+
+ app_->clear_all_handler();
+ app_->stop();
+}
+
+void routing_restart_test_client::on_state(vsomeip::state_type_e _state) {
+ if(_state == vsomeip::state_type_e::ST_REGISTERED) {
+ app_->request_service(vsomeip_test::TEST_SERVICE_SERVICE_ID,
+ vsomeip_test::TEST_SERVICE_INSTANCE_ID, false);
+ }
+}
+
+void routing_restart_test_client::on_availability(vsomeip::service_t _service,
+ vsomeip::instance_t _instance, bool _is_available) {
+
+ VSOMEIP_INFO << std::hex << "Client 0x" << app_->get_client()
+ << " : Service [" << std::setw(4) << std::setfill('0') << std::hex
+ << _service << "." << _instance << "] is "
+ << (_is_available ? "available." : "NOT available.");
+
+ if(vsomeip_test::TEST_SERVICE_SERVICE_ID == _service
+ && vsomeip_test::TEST_SERVICE_INSTANCE_ID == _instance) {
+ std::unique_lock<std::mutex> its_lock(mutex_);
+ if(is_available_ && !_is_available) {
+ is_available_ = false;
+ }
+ else if(_is_available && !is_available_) {
+ is_available_ = true;
+ condition_.notify_one();
+ }
+ }
+}
+
+void routing_restart_test_client::on_message(const std::shared_ptr<vsomeip::message> &_response) {
+ VSOMEIP_INFO << "Received a response from Service ["
+ << std::setw(4) << std::setfill('0') << std::hex << _response->get_service()
+ << "."
+ << std::setw(4) << std::setfill('0') << std::hex << _response->get_instance()
+ << "] to Client/Session ["
+ << std::setw(4) << std::setfill('0') << std::hex << _response->get_client()
+ << "/"
+ << std::setw(4) << std::setfill('0') << std::hex << _response->get_session()
+ << "]";
+
+ if (_response->get_service() == vsomeip_test::TEST_SERVICE_SERVICE_ID &&
+ _response->get_instance() == vsomeip_test::TEST_SERVICE_INSTANCE_ID) {
+ received_responses_++;
+ if (received_responses_ == vsomeip_test::NUMBER_OF_MESSAGES_TO_SEND_ROUTING_RESTART_TESTS) {
+ VSOMEIP_WARNING << std::hex << app_->get_client()
+ << ": Received all messages ~> going down!";
+ }
+ }
+}
+
+void routing_restart_test_client::run() {
+ for (uint32_t i = 0; i < vsomeip_test::NUMBER_OF_MESSAGES_TO_SEND_ROUTING_RESTART_TESTS; ++i) {
+ {
+ std::unique_lock<std::mutex> its_lock(mutex_);
+ while (!is_available_)
+ {
+ condition_.wait(its_lock);
+ }
+ }
+
+ auto request = vsomeip::runtime::get()->create_request(false);
+ request->set_service(vsomeip_test::TEST_SERVICE_SERVICE_ID);
+ request->set_instance(vsomeip_test::TEST_SERVICE_INSTANCE_ID);
+ request->set_method(vsomeip_test::TEST_SERVICE_METHOD_ID);
+ app_->send(request, true);
+
+ std::this_thread::sleep_for(std::chrono::milliseconds(250));
+ }
+
+ std::this_thread::sleep_for(std::chrono::milliseconds(250));
+ EXPECT_EQ(vsomeip_test::NUMBER_OF_MESSAGES_TO_SEND_ROUTING_RESTART_TESTS,
+ received_responses_);
+
+ stop();
+}
+
+void routing_restart_test_client::join_sender_thread()
+{
+ if (sender_.joinable()) {
+ sender_.join();
+ }
+}
+
+void routing_restart_test_client::shutdown_service() {
+ auto request = vsomeip::runtime::get()->create_request(false);
+ request->set_service(vsomeip_test::TEST_SERVICE_SERVICE_ID);
+ request->set_instance(vsomeip_test::TEST_SERVICE_INSTANCE_ID);
+ request->set_method(vsomeip_test::TEST_SERVICE_METHOD_ID_SHUTDOWN);
+ app_->send(request,true);
+}
+
+TEST(someip_restart_routing_test, request_response_over_restart)
+{
+ routing_restart_test_client test_client;
+ if (test_client.init()) {
+ test_client.start();
+ test_client.join_sender_thread();
+ }
+}
+
+int main(int argc, char** argv) {
+ ::testing::InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
+}
diff --git a/test/restart_routing_tests/restart_routing_test_client.hpp b/test/restart_routing_tests/restart_routing_test_client.hpp
new file mode 100644
index 0000000..fdc56d4
--- /dev/null
+++ b/test/restart_routing_tests/restart_routing_test_client.hpp
@@ -0,0 +1,50 @@
+
+// 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/.
+
+#ifndef RESTART_ROUTING_TEST_CLIENT_HPP
+#define RESTART_ROUTING_TEST_CLIENT_HPP
+
+#include <gtest/gtest.h>
+
+#include <vsomeip/vsomeip.hpp>
+
+#include "../someip_test_globals.hpp"
+
+#include <thread>
+#include <mutex>
+#include <condition_variable>
+#include <atomic>
+
+class routing_restart_test_client {
+public:
+ routing_restart_test_client();
+ bool init();
+ void start();
+ void stop();
+
+ void on_state(vsomeip::state_type_e _state);
+ void on_availability(vsomeip::service_t _service,
+ vsomeip::instance_t _instance, bool _is_available);
+ void on_message(const std::shared_ptr<vsomeip::message> &_response);
+
+ void run();
+ void join_sender_thread();
+
+private:
+ void shutdown_service();
+
+ std::shared_ptr<vsomeip::application> app_;
+
+ std::mutex mutex_;
+ std::condition_variable condition_;
+ bool is_available_;
+
+ std::thread sender_;
+
+ std::atomic<std::uint32_t> received_responses_;
+};
+
+#endif // RESTART_ROUTING_TEST_CLIENT_HPP
diff --git a/test/restart_routing_tests/restart_routing_test_client.json b/test/restart_routing_tests/restart_routing_test_client.json
new file mode 100644
index 0000000..0d901d8
--- /dev/null
+++ b/test/restart_routing_tests/restart_routing_test_client.json
@@ -0,0 +1,48 @@
+{
+ "unicast" : "127.0.0.1",
+ "netmask" : "255.255.255.0",
+ "logging" :
+ {
+ "level" : "warning",
+ "console" : "true",
+ "file" :
+ {
+ "enable" : "true",
+ "path" : "/var/log/vsomeip.log"
+ },
+
+ "dlt" : "true"
+ },
+
+ "applications" :
+ [
+ {
+ "name" : "restart_routing_test_client1",
+ "id" : "0x1343"
+ },
+ {
+ "name" : "restart_routing_test_client2",
+ "id" : "0x1344"
+ },
+ {
+ "name" : "restart_routing_test_client3",
+ "id" : "0x1345"
+ },
+ {
+ "name" : "restart_routing_test_client4",
+ "id" : "0x1346"
+ }
+ ],
+ "services" :
+ [
+ ],
+
+ "routing" : "vsomeipd",
+ "service-discovery" :
+ {
+ "enable" : "false",
+ "multicast" : "224.0.0.1",
+ "port" : "30491",
+ "protocol" : "udp"
+ }
+}
diff --git a/test/restart_routing_tests/restart_routing_test_client_start.sh b/test/restart_routing_tests/restart_routing_test_client_start.sh
new file mode 100755
index 0000000..de944b9
--- /dev/null
+++ b/test/restart_routing_tests/restart_routing_test_client_start.sh
@@ -0,0 +1,9 @@
+#!/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/.
+
+export VSOMEIP_APPLICATION_NAME=restart_routing_test_client
+export VSOMEIP_CONFIGURATION=restart_routing_test_client.json
+./restart_routing_test_client
diff --git a/test/restart_routing_tests/restart_routing_test_service.cpp b/test/restart_routing_tests/restart_routing_test_service.cpp
new file mode 100644
index 0000000..cf4bba1
--- /dev/null
+++ b/test/restart_routing_tests/restart_routing_test_service.cpp
@@ -0,0 +1,133 @@
+// 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/.
+
+#include "restart_routing_test_service.hpp"
+
+routing_restart_test_service::routing_restart_test_service() :
+ app_(vsomeip::runtime::get()->create_application()),
+ is_registered_(false),
+ blocked_(false),
+ number_of_received_messages_(0),
+ offer_thread_(std::bind(&routing_restart_test_service::run, this)) {
+}
+
+bool routing_restart_test_service::init() {
+ std::lock_guard<std::mutex> its_lock(mutex_);
+
+ if (!app_->init()) {
+ ADD_FAILURE() << "Couldn't initialize application";
+ return false;
+ }
+ app_->register_message_handler(vsomeip_test::TEST_SERVICE_SERVICE_ID,
+ vsomeip_test::TEST_SERVICE_INSTANCE_ID, vsomeip_test::TEST_SERVICE_METHOD_ID,
+ std::bind(&routing_restart_test_service::on_message, this,
+ std::placeholders::_1));
+
+ app_->register_message_handler(vsomeip_test::TEST_SERVICE_SERVICE_ID,
+ vsomeip_test::TEST_SERVICE_INSTANCE_ID,
+ vsomeip_test::TEST_SERVICE_METHOD_ID_SHUTDOWN,
+ std::bind(&routing_restart_test_service::on_message_shutdown, this,
+ std::placeholders::_1));
+
+ app_->register_state_handler(
+ std::bind(&routing_restart_test_service::on_state, this,
+ std::placeholders::_1));
+ return true;
+}
+
+void routing_restart_test_service::start() {
+ VSOMEIP_INFO << "Starting...";
+ app_->start();
+}
+
+void routing_restart_test_service::stop() {
+ VSOMEIP_INFO << "Stopping...";
+ app_->clear_all_handler();
+ app_->stop();
+}
+
+void routing_restart_test_service::join_offer_thread() {
+ if (offer_thread_.joinable()) {
+ offer_thread_.join();
+ }
+}
+
+void routing_restart_test_service::offer() {
+ app_->offer_service(vsomeip_test::TEST_SERVICE_SERVICE_ID, vsomeip_test::TEST_SERVICE_INSTANCE_ID);
+}
+
+void routing_restart_test_service::stop_offer() {
+ app_->stop_offer_service(vsomeip_test::TEST_SERVICE_SERVICE_ID, vsomeip_test::TEST_SERVICE_INSTANCE_ID);
+}
+
+void routing_restart_test_service::on_state(vsomeip::state_type_e _state) {
+ VSOMEIP_INFO << "Application " << app_->get_name() << " is "
+ << (_state == vsomeip::state_type_e::ST_REGISTERED ? "registered." :
+ "deregistered.");
+
+ if(_state == vsomeip::state_type_e::ST_REGISTERED) {
+ if(!is_registered_) {
+ is_registered_ = true;
+ std::lock_guard<std::mutex> its_lock(mutex_);
+ blocked_ = true;
+ // "start" the run method thread
+ condition_.notify_one();
+ }
+ }
+ else {
+ is_registered_ = false;
+ }
+}
+
+void routing_restart_test_service::on_message(const std::shared_ptr<vsomeip::message>& _request) {
+ ASSERT_EQ(vsomeip_test::TEST_SERVICE_SERVICE_ID, _request->get_service());
+ ASSERT_EQ(vsomeip_test::TEST_SERVICE_METHOD_ID, _request->get_method());
+
+ VSOMEIP_INFO << "Received a message with Client/Session [" << std::setw(4)
+ << std::setfill('0') << std::hex << _request->get_client() << "/"
+ << std::setw(4) << std::setfill('0') << std::hex
+ << _request->get_session() << "]";
+
+ // send response
+ std::shared_ptr<vsomeip::message> its_response =
+ vsomeip::runtime::get()->create_response(_request);
+
+ app_->send(its_response, true);
+
+ number_of_received_messages_++;
+ if(number_of_received_messages_ == vsomeip_test::NUMBER_OF_MESSAGES_TO_SEND_ROUTING_RESTART_TESTS) {
+ VSOMEIP_INFO << "Received all messages!";
+ }
+}
+
+void routing_restart_test_service::on_message_shutdown(
+ const std::shared_ptr<vsomeip::message>& _request) {
+ (void)_request;
+ VSOMEIP_INFO << "Shutdown method was called, going down now.";
+ stop();
+}
+
+void routing_restart_test_service::run() {
+ std::unique_lock<std::mutex> its_lock(mutex_);
+ while (!blocked_)
+ condition_.wait(its_lock);
+
+ offer();
+}
+
+TEST(someip_restart_routing_test, send_response_for_every_request) {
+ routing_restart_test_service test_service;
+ if (test_service.init()) {
+ test_service.start();
+ test_service.join_offer_thread();
+ }
+}
+
+#ifndef _WIN32
+int main(int argc, char** argv) {
+ ::testing::InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
+}
+#endif
diff --git a/test/restart_routing_tests/restart_routing_test_service.hpp b/test/restart_routing_tests/restart_routing_test_service.hpp
new file mode 100644
index 0000000..3abfe17
--- /dev/null
+++ b/test/restart_routing_tests/restart_routing_test_service.hpp
@@ -0,0 +1,44 @@
+// 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/.
+
+#ifndef RESTART_ROUTING_TEST_SERVICE_HPP
+#define RESTART_ROUTING_TEST_SERVICE_HPP
+
+#include <gtest/gtest.h>
+
+#include <vsomeip/vsomeip.hpp>
+
+#include "../someip_test_globals.hpp"
+
+#include <thread>
+#include <mutex>
+#include <condition_variable>
+
+class routing_restart_test_service {
+public:
+ routing_restart_test_service();
+ bool init();
+ void start();
+ void stop();
+ void offer();
+ void stop_offer();
+ void join_offer_thread();
+ void on_state(vsomeip::state_type_e _state);
+ void on_message(const std::shared_ptr<vsomeip::message> &_request);
+ void on_message_shutdown(const std::shared_ptr<vsomeip::message> &_request);
+ void run();
+
+private:
+ std::shared_ptr<vsomeip::application> app_;
+ bool is_registered_;
+
+ std::mutex mutex_;
+ std::condition_variable condition_;
+ bool blocked_;
+ std::uint32_t number_of_received_messages_;
+ std::thread offer_thread_;
+};
+
+#endif // RESTART_ROUTING_TEST_SERVICE_HPP
diff --git a/test/restart_routing_tests/restart_routing_test_service.json b/test/restart_routing_tests/restart_routing_test_service.json
new file mode 100644
index 0000000..8ff90cb
--- /dev/null
+++ b/test/restart_routing_tests/restart_routing_test_service.json
@@ -0,0 +1,44 @@
+{
+ "unicast" : "127.0.0.1",
+ "logging" :
+ {
+ "level" : "warning",
+ "console" : "true",
+ "file" :
+ {
+ "enable" : "false",
+ "path" : "/tmp/vsomeip.log"
+ },
+
+ "dlt" : "false"
+ },
+
+ "applications" :
+ [
+ {
+ "name" : "vsomeipd",
+ "id" : "0x0815"
+ },
+ {
+ "name" : "restart_routing_test_service",
+ "id" : "0x1277"
+ }
+ ],
+
+ "services" :
+ [
+ {
+ "service" : "0x1234",
+ "instance" : "0x5678"
+ }
+ ],
+
+ "routing" : "vsomeipd",
+ "service-discovery" :
+ {
+ "enable" : "false",
+ "multicast" : "224.0.0.1",
+ "port" : "30490",
+ "protocol" : "udp"
+ }
+}
diff --git a/test/restart_routing_tests/restart_routing_test_service_start.sh b/test/restart_routing_tests/restart_routing_test_service_start.sh
new file mode 100755
index 0000000..b82be7c
--- /dev/null
+++ b/test/restart_routing_tests/restart_routing_test_service_start.sh
@@ -0,0 +1,9 @@
+#!/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/.
+
+export VSOMEIP_APPLICATION_NAME=restart_routing_test_service
+export VSOMEIP_CONFIGURATION=restart_routing_test_service.json
+./restart_routing_test_service
diff --git a/test/restart_routing_tests/restart_routing_test_starter.sh b/test/restart_routing_tests/restart_routing_test_starter.sh
new file mode 100755
index 0000000..0778e98
--- /dev/null
+++ b/test/restart_routing_tests/restart_routing_test_starter.sh
@@ -0,0 +1,312 @@
+#!/bin/bash
+# Copyright (C) 2015-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+# Purpose: This script is needed to start the client and service with
+# one command. This is necessary as ctest - which is used to run the
+# tests - isn't able to start two binaries for one testcase. Therefore
+# the testcase simply executes this script. This script then runs client
+# and service and checks that both exit sucessfully.
+
+FAIL=0
+
+# NOW WITHOUT JSON
+echo "----------------------------------------------"
+echo "----------------------------------------------"
+echo " Run test with auto configuration "
+echo "----------------------------------------------"
+echo "----------------------------------------------"
+
+export VSOMEIP_CONFIGURATION=restart_routing_test_autoconfig.json
+
+../daemon/./vsomeipd &
+DAEMON_PID=$!
+
+sleep 2
+
+# Start the service
+export VSOMEIP_APPLICATION_NAME=restart_routing_test_service
+./restart_routing_test_service &
+SERIVCE_PID=$!
+
+# Start the client1
+export VSOMEIP_APPLICATION_NAME=restart_routing_test_client1
+./restart_routing_test_client &
+CLIENT1_PID=$!
+
+# Start the client2
+export VSOMEIP_APPLICATION_NAME=restart_routing_test_client2
+./restart_routing_test_client &
+CLIENT2_PID=$!
+
+# Start the client3
+export VSOMEIP_APPLICATION_NAME=restart_routing_test_client3
+./restart_routing_test_client &
+CLIENT3_PID=$!
+
+# Start the client4
+export VSOMEIP_APPLICATION_NAME=restart_routing_test_client4
+./restart_routing_test_client &
+CLIENT4_PID=$!
+
+sleep 2
+echo "----------------------------------------------"
+echo " let vsomeipd crash (kill -9) "
+echo "----------------------------------------------"
+kill -9 $DAEMON_PID
+echo "----------------------------------------------"
+echo " restart vsomeipd "
+echo "----------------------------------------------"
+sleep 2
+
+../daemon/./vsomeipd &
+DAEMON_PID=$!
+
+wait $SERIVCE_PID || ((FAIL+=1))
+wait $CLIENT1_PID || ((FAIL+=1))
+wait $CLIENT2_PID || ((FAIL+=1))
+wait $CLIENT3_PID || ((FAIL+=1))
+wait $CLIENT4_PID || ((FAIL+=1))
+
+kill $DAEMON_PID
+wait $DAEMON_PID
+
+# Check if client and server both exited sucessfully and the service didnt't
+# have any open tcp/udp sockets
+if [ $FAIL -eq 0 ]
+then
+ echo "Test Succeeded"
+else
+ exit 1
+fi
+
+# NOW WITHOUT VSOMEIPD
+echo "----------------------------------------------"
+echo "----------------------------------------------"
+echo " Run test with auto configuration no deamon "
+echo "----------------------------------------------"
+echo "----------------------------------------------"
+
+sleep 2
+
+# Start the service
+export VSOMEIP_APPLICATION_NAME=restart_routing_test_service
+./restart_routing_test_service &
+SERIVCE_PID=$!
+
+# Start the client1
+export VSOMEIP_APPLICATION_NAME=restart_routing_test_client1
+./restart_routing_test_client &
+CLIENT1_PID=$!
+
+# Start the client2
+export VSOMEIP_APPLICATION_NAME=restart_routing_test_client2
+./restart_routing_test_client &
+CLIENT2_PID=$!
+
+# Start the client3
+export VSOMEIP_APPLICATION_NAME=restart_routing_test_client3
+./restart_routing_test_client &
+CLIENT3_PID=$!
+
+# Start the client4
+export VSOMEIP_APPLICATION_NAME=restart_routing_test_client4
+./restart_routing_test_client &
+CLIENT4_PID=$!
+
+sleep 2
+echo "----------------------------------------------"
+echo " let service (routing) crash (kill -9) "
+echo "----------------------------------------------"
+kill -9 $SERIVCE_PID
+echo "----------------------------------------------"
+echo " restart service (routing) "
+echo "----------------------------------------------"
+sleep 2
+
+# Start the service
+export VSOMEIP_APPLICATION_NAME=restart_routing_test_service
+./restart_routing_test_service &
+SERIVCE_PID=$!
+
+wait $SERIVCE_PID || ((FAIL+=1))
+wait $CLIENT1_PID || ((FAIL+=1))
+wait $CLIENT2_PID || ((FAIL+=1))
+wait $CLIENT3_PID || ((FAIL+=1))
+wait $CLIENT4_PID || ((FAIL+=1))
+
+# Check if client and server both exited sucessfully and the service didnt't
+# have any open tcp/udp sockets
+if [ $FAIL -eq 0 ]
+then
+ echo "Test Succeeded"
+else
+ exit 1
+fi
+
+
+echo "----------------------------------------------"
+echo "----------------------------------------------"
+echo " Run test with json configuration "
+echo "----------------------------------------------"
+echo "----------------------------------------------"
+
+sleep 2
+
+export VSOMEIP_CONFIGURATION=restart_routing_test_service.json
+../daemon/./vsomeipd &
+DAEMON_PID=$!
+
+# Start the service
+export VSOMEIP_APPLICATION_NAME=restart_routing_test_service
+export VSOMEIP_CONFIGURATION=restart_routing_test_service.json
+./restart_routing_test_service &
+SERIVCE_PID=$!
+
+# Start the client1
+export VSOMEIP_APPLICATION_NAME=restart_routing_test_client1
+export VSOMEIP_CONFIGURATION=restart_routing_test_client.json
+./restart_routing_test_client &
+CLIENT1_PID=$!
+
+# Start the client2
+export VSOMEIP_APPLICATION_NAME=restart_routing_test_client2
+export VSOMEIP_CONFIGURATION=restart_routing_test_client.json
+./restart_routing_test_client &
+CLIENT2_PID=$!
+
+# Start the client3
+export VSOMEIP_APPLICATION_NAME=restart_routing_test_client3
+export VSOMEIP_CONFIGURATION=restart_routing_test_client.json
+./restart_routing_test_client &
+CLIENT3_PID=$!
+
+# Start the client4
+export VSOMEIP_APPLICATION_NAME=restart_routing_test_client4
+export VSOMEIP_CONFIGURATION=restart_routing_test_client.json
+./restart_routing_test_client &
+CLIENT4_PID=$!
+
+sleep 2
+echo "----------------------------------------------"
+echo " let vsomeipd crash (kill -9) "
+echo "----------------------------------------------"
+kill -9 $DAEMON_PID
+echo "----------------------------------------------"
+echo " restart vsomeipd "
+echo "----------------------------------------------"
+sleep 2
+
+export VSOMEIP_CONFIGURATION=restart_routing_test_service.json
+../daemon/./vsomeipd &
+DAEMON_PID=$!
+
+wait $SERIVCE_PID || ((FAIL+=1))
+wait $CLIENT1_PID || ((FAIL+=1))
+wait $CLIENT2_PID || ((FAIL+=1))
+wait $CLIENT3_PID || ((FAIL+=1))
+wait $CLIENT4_PID || ((FAIL+=1))
+
+kill $DAEMON_PID
+wait $DAEMON_PID
+
+# Check if client and server both exited sucessfully and the service didnt't
+# have any open tcp/udp sockets
+if [ $FAIL -eq 0 ]
+then
+ echo "Test Succeeded"
+else
+ exit 1
+fi
+
+echo "----------------------------------------------"
+echo "----------------------------------------------"
+echo "Run test with json configuration + kill service"
+echo "----------------------------------------------"
+echo "----------------------------------------------"
+
+sleep 2
+
+export VSOMEIP_CONFIGURATION=restart_routing_test_service.json
+../daemon/./vsomeipd &
+DAEMON_PID=$!
+
+# Start the service
+export VSOMEIP_APPLICATION_NAME=restart_routing_test_service
+export VSOMEIP_CONFIGURATION=restart_routing_test_service.json
+./restart_routing_test_service &
+SERIVCE_PID=$!
+
+# Start the client1
+export VSOMEIP_APPLICATION_NAME=restart_routing_test_client1
+export VSOMEIP_CONFIGURATION=restart_routing_test_client.json
+./restart_routing_test_client &
+CLIENT1_PID=$!
+
+# Start the client2
+export VSOMEIP_APPLICATION_NAME=restart_routing_test_client2
+export VSOMEIP_CONFIGURATION=restart_routing_test_client.json
+./restart_routing_test_client &
+CLIENT2_PID=$!
+
+# Start the client3
+export VSOMEIP_APPLICATION_NAME=restart_routing_test_client3
+export VSOMEIP_CONFIGURATION=restart_routing_test_client.json
+./restart_routing_test_client &
+CLIENT3_PID=$!
+
+# Start the client4
+export VSOMEIP_APPLICATION_NAME=restart_routing_test_client4
+export VSOMEIP_CONFIGURATION=restart_routing_test_client.json
+./restart_routing_test_client &
+CLIENT4_PID=$!
+
+sleep 2
+echo "----------------------------------------------"
+echo " let vsomeipd crash (kill -9) "
+echo "----------------------------------------------"
+kill -9 $DAEMON_PID
+sleep 1
+echo "----------------------------------------------"
+echo " let service crash (kill -9) "
+echo "----------------------------------------------"
+kill -9 $SERIVCE_PID
+echo "----------------------------------------------"
+echo " restart vsomeipd "
+echo "----------------------------------------------"
+sleep 2
+
+export VSOMEIP_CONFIGURATION=restart_routing_test_service.json
+../daemon/./vsomeipd &
+DAEMON_PID=$!
+
+echo "----------------------------------------------"
+echo " restart service "
+echo "----------------------------------------------"
+sleep 1
+
+# Start the service again
+export VSOMEIP_APPLICATION_NAME=restart_routing_test_service
+export VSOMEIP_CONFIGURATION=restart_routing_test_service.json
+./restart_routing_test_service &
+SERIVCE_PID=$!
+
+wait $SERIVCE_PID || ((FAIL+=1))
+wait $CLIENT1_PID || ((FAIL+=1))
+wait $CLIENT2_PID || ((FAIL+=1))
+wait $CLIENT3_PID || ((FAIL+=1))
+wait $CLIENT4_PID || ((FAIL+=1))
+
+kill $DAEMON_PID
+wait $DAEMON_PID
+
+# Check if client and server both exited sucessfully and the service didnt't
+# have any open tcp/udp sockets
+if [ $FAIL -eq 0 ]
+then
+ exit 0
+else
+ exit 1
+fi
diff --git a/test/someip_test_globals.hpp b/test/someip_test_globals.hpp
index 08397a7..5a5f916 100644
--- a/test/someip_test_globals.hpp
+++ b/test/someip_test_globals.hpp
@@ -35,6 +35,8 @@ constexpr vsomeip::byte_t PAYLOAD_TEST_DATA = 0xDD;
constexpr std::uint32_t MAX_PAYLOADSIZE = 1024*128;
// TR_SOMEIP_00061
constexpr std::uint32_t MAX_PAYLOADSIZE_UDP = 1400;
+
+constexpr std::uint32_t NUMBER_OF_MESSAGES_TO_SEND_ROUTING_RESTART_TESTS = 32;
}
#endif /* SOMEIP_TEST_GLOBALS_HPP_ */