summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJuergen Gehring <juergen.gehring@bmw.de>2018-01-25 00:40:06 -0800
committerJuergen Gehring <juergen.gehring@bmw.de>2018-01-25 00:40:06 -0800
commitca8af4e6da0eb1f5c268ace102c0ac6aa5545b5c (patch)
tree33646dd65a9578148ac5ac6111ada0272bc153d0
parent005f77c5d4711ece8ad5e5e789c78f90c41d928b (diff)
downloadvSomeIP-ca8af4e6da0eb1f5c268ace102c0ac6aa5545b5c.tar.gz
vsomeip 2.10.42.10.4
-rw-r--r--CHANGES9
-rw-r--r--CMakeLists.txt2
-rw-r--r--documentation/vsomeipUserGuide41
-rw-r--r--implementation/configuration/src/configuration_impl.cpp4
-rw-r--r--implementation/endpoints/include/tcp_client_endpoint_impl.hpp10
-rw-r--r--implementation/endpoints/include/tcp_server_endpoint_impl.hpp19
-rw-r--r--implementation/endpoints/src/tcp_client_endpoint_impl.cpp98
-rw-r--r--implementation/endpoints/src/tcp_server_endpoint_impl.cpp104
-rw-r--r--implementation/routing/include/routing_manager_proxy.hpp7
-rw-r--r--implementation/routing/include/routing_manager_stub.hpp1
-rw-r--r--implementation/routing/src/routing_manager_base.cpp6
-rw-r--r--implementation/routing/src/routing_manager_impl.cpp6
-rw-r--r--implementation/routing/src/routing_manager_proxy.cpp70
-rw-r--r--implementation/routing/src/routing_manager_stub.cpp12
-rw-r--r--implementation/runtime/include/application_impl.hpp5
-rw-r--r--implementation/runtime/src/application_impl.cpp209
-rw-r--r--implementation/service_discovery/src/service_discovery_impl.cpp1
-rw-r--r--test/application_tests/application_test.cpp124
18 files changed, 582 insertions, 146 deletions
diff --git a/CHANGES b/CHANGES
index 385bac1..1fa9a5f 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,6 +1,15 @@
Changes
=======
+v2.10.4
+- Extended diagnosis plugin to handle requests for
+ "disableRxAndEnableTx" and "disableRxAndTx".
+- Catch unhandled user code exceptions thrown from called handlers.
+- Don't send SubscribeEventGroupNACK for pending subscriptions on next
+ offer to reduce the amount of StopSubscribe/Subscribe messages.
+- Added possibility to apply filter for client side logging
+ using VSOMEIP_CLIENTSIDELOGGING environment variable.
+
v2.10.3
- Interpret all incoming TTLs five times longer in service discovery
to prevent inadvertent expiration of remote offers during high load
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 5d958b4..d1df178 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -8,7 +8,7 @@ project (vsomeip)
set (VSOMEIP_MAJOR_VERSION 2)
set (VSOMEIP_MINOR_VERSION 10)
-set (VSOMEIP_PATCH_VERSION 3)
+set (VSOMEIP_PATCH_VERSION 4)
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 882890d..0c222b9 100644
--- a/documentation/vsomeipUserGuide
+++ b/documentation/vsomeipUserGuide
@@ -231,11 +231,14 @@ On startup the following environment variables are read out:
applications, all other configuration files are only read by the application that is
responsible for connections to external devices. If this configuration variable is not set,
the default mandatory files vsomeip_std.json, vsomeip_app.json and vsomeip_plc.json are used.
-* `VSOMEIP_CLIENTSIDELOGGING`: Set this variable to an empty string or an arbitrary
- value to enable logging of received messages to DLT in all applications
- acting as routing manager proxies. For example add the following line to the
- application's systemd service file:
+* `VSOMEIP_CLIENTSIDELOGGING`: Set this variable to an empty string to enable logging of
+ any received messages to DLT in all applications acting as routing manager proxies. For
+ example add the following line to the application's systemd service file:
`Environment=VSOMEIP_CLIENTSIDELOGGING=""`
+ To enable service-specific logs, provide a space- or colon-separated list of ServiceIDs (using
+ 4-digit hexadecimal notation, optionally followed by dot-separted InstanceID). For example:
+ `Environment=VSOMEIP_CLIENTSIDELOGGING="b003.0001 f013.000a 1001 1002"`
+ `Environment=VSOMEIP_CLIENTSIDELOGGING="b003.0001:f013.000a:1001:1002"`
NOTE: If the file/folder that is configured by `VSOMEIP_CONFIGURATION` does _not_ exist,
the default configuration locations will be used.
@@ -907,9 +910,37 @@ Specifies a service for the _offers_.
+
Specifies a instance for the _offers_
-In the config/ folder are some vSomeIP configuration files to run the vSomeIP examples with activated security checks.
+In the `config/` folder are some vSomeIP configuration files to run the vSomeIP
+examples with activated security checks.
+Additionally there's a security test in the `test/` subfolder which can be used
+for further reference. +
They give a basic overview how to use the security related configuration tags described in this chapter to run a simple request/response or subscribe/notify example locally or over remote.
+Audit Mode
+~~~~~~~~~~
+vSomeIP's security implementation can be put in a so called 'Audit Mode' where
+all security violations will be logged but allowed. This mode can be used to
+build a security configuration.
+
+To activate the 'Audit Mode' the 'security' object has to be included in the
+json file but the 'check_credentials' switch has to be set to false. For
+example:
+
+[source, json]
+----
+ [...]
+ "services" :
+ [
+ [...]
+ ],
+ "security" :
+ {
+ "check_credentials" : "false"
+ },
+ "routing" : "service-sample",
+ [...]
+----
+
Autoconfiguration
-----------------
vsomeip supports the automatic configuration of client identifiers and the routing.
diff --git a/implementation/configuration/src/configuration_impl.cpp b/implementation/configuration/src/configuration_impl.cpp
index 243f93e..43e3c67 100644
--- a/implementation/configuration/src/configuration_impl.cpp
+++ b/implementation/configuration/src/configuration_impl.cpp
@@ -351,10 +351,6 @@ bool configuration_impl::load_data(const std::vector<element> &_elements,
}
}
- for (auto its_service : services_) {
- VSOMEIP_INFO << "service: " << its_service.first;
- }
-
return is_logging_loaded_ && has_routing && has_applications;
}
diff --git a/implementation/endpoints/include/tcp_client_endpoint_impl.hpp b/implementation/endpoints/include/tcp_client_endpoint_impl.hpp
index 7ba35aa..801c98c 100644
--- a/implementation/endpoints/include/tcp_client_endpoint_impl.hpp
+++ b/implementation/endpoints/include/tcp_client_endpoint_impl.hpp
@@ -25,7 +25,8 @@ public:
endpoint_type _remote,
boost::asio::io_service &_io,
std::uint32_t _max_message_size,
- std::uint32_t buffer_shrink_threshold);
+ std::uint32_t buffer_shrink_threshold,
+ std::chrono::milliseconds _send_timeout);
virtual ~tcp_client_endpoint_impl();
void start();
@@ -52,6 +53,11 @@ private:
const std::string get_address_port_local() const;
void handle_recv_buffer_exception(const std::exception &_e);
void set_local_port();
+ std::size_t write_completion_condition(
+ const boost::system::error_code& _error,
+ std::size_t _bytes_transferred, std::size_t _bytes_to_send,
+ service_t _service, method_t _method, client_t _client, session_t _session,
+ std::chrono::steady_clock::time_point _start);
const std::uint32_t recv_buffer_size_initial_;
@@ -64,6 +70,8 @@ private:
const boost::asio::ip::address remote_address_;
const std::uint16_t remote_port_;
std::chrono::steady_clock::time_point last_cookie_sent_;
+ const std::chrono::milliseconds send_timeout_;
+ const std::chrono::milliseconds send_timeout_warning_;
};
} // namespace vsomeip
diff --git a/implementation/endpoints/include/tcp_server_endpoint_impl.hpp b/implementation/endpoints/include/tcp_server_endpoint_impl.hpp
index 3d639d9..ab6fdb9 100644
--- a/implementation/endpoints/include/tcp_server_endpoint_impl.hpp
+++ b/implementation/endpoints/include/tcp_server_endpoint_impl.hpp
@@ -30,7 +30,8 @@ public:
endpoint_type _local,
boost::asio::io_service &_io,
std::uint32_t _max_message_size,
- std::uint32_t _buffer_shrink_threshold);
+ std::uint32_t _buffer_shrink_threshold,
+ std::chrono::milliseconds _send_timeout);
virtual ~tcp_server_endpoint_impl();
void start();
@@ -64,7 +65,8 @@ private:
std::uint32_t _max_message_size,
std::uint32_t _buffer_shrink_threshold,
bool _magic_cookies_enabled,
- boost::asio::io_service & _io_service);
+ boost::asio::io_service & _io_service,
+ std::chrono::milliseconds _send_timeout);
socket_type & get_socket();
std::unique_lock<std::mutex> get_socket_lock();
@@ -84,7 +86,8 @@ private:
std::uint32_t _recv_buffer_size_initial,
std::uint32_t _buffer_shrink_threshold,
bool _magic_cookies_enabled,
- boost::asio::io_service & _io_service);
+ boost::asio::io_service & _io_service,
+ std::chrono::milliseconds _send_timeout);
void send_magic_cookie(message_buffer_ptr_t &_buffer);
bool is_magic_cookie(size_t _offset) const;
void receive_cbk(boost::system::error_code const &_error,
@@ -92,7 +95,12 @@ private:
void calculate_shrink_count();
const std::string get_address_port_local() const;
void handle_recv_buffer_exception(const std::exception &_e);
-
+ std::size_t write_completion_condition(
+ const boost::system::error_code& _error,
+ std::size_t _bytes_transferred, std::size_t _bytes_to_send,
+ service_t _service, method_t _method, client_t _client, session_t _session,
+ std::chrono::steady_clock::time_point _start);
+ void stop_and_remove_connection();
std::mutex socket_mutex_;
tcp_server_endpoint_impl::socket_type socket_;
@@ -112,6 +120,8 @@ private:
std::uint16_t remote_port_;
std::atomic<bool> magic_cookies_enabled_;
std::chrono::steady_clock::time_point last_cookie_sent_;
+ const std::chrono::milliseconds send_timeout_;
+ const std::chrono::milliseconds send_timeout_warning_;
};
std::mutex acceptor_mutex_;
@@ -121,6 +131,7 @@ private:
connections_t connections_;
const std::uint32_t buffer_shrink_threshold_;
const std::uint16_t local_port_;
+ const std::chrono::milliseconds send_timeout_;
private:
void remove_connection(connection *_connection);
diff --git a/implementation/endpoints/src/tcp_client_endpoint_impl.cpp b/implementation/endpoints/src/tcp_client_endpoint_impl.cpp
index 6a5df88..2646f01 100644
--- a/implementation/endpoints/src/tcp_client_endpoint_impl.cpp
+++ b/implementation/endpoints/src/tcp_client_endpoint_impl.cpp
@@ -14,8 +14,10 @@
#include "../include/tcp_client_endpoint_impl.hpp"
#include "../../logging/include/logger.hpp"
#include "../../utility/include/utility.hpp"
+#include "../../utility/include/byteorder.hpp"
#include "../../configuration/include/internal.hpp"
+
namespace ip = boost::asio::ip;
namespace vsomeip {
@@ -26,7 +28,8 @@ tcp_client_endpoint_impl::tcp_client_endpoint_impl(
endpoint_type _remote,
boost::asio::io_service &_io,
std::uint32_t _max_message_size,
- std::uint32_t _buffer_shrink_threshold)
+ std::uint32_t _buffer_shrink_threshold,
+ std::chrono::milliseconds _send_timeout)
: tcp_client_endpoint_base_impl(_host, _local, _remote, _io, _max_message_size),
recv_buffer_size_initial_(VSOMEIP_SOMEIP_HEADER_SIZE),
recv_buffer_(recv_buffer_size_initial_, 0),
@@ -36,7 +39,9 @@ tcp_client_endpoint_impl::tcp_client_endpoint_impl(
buffer_shrink_threshold_(_buffer_shrink_threshold),
remote_address_(_remote.address()),
remote_port_(_remote.port()),
- last_cookie_sent_(std::chrono::steady_clock::now() - std::chrono::seconds(11)) {
+ last_cookie_sent_(std::chrono::steady_clock::now() - std::chrono::seconds(11)),
+ send_timeout_(_send_timeout),
+ send_timeout_warning_(_send_timeout / 2) {
is_supporting_magic_cookies_ = true;
}
@@ -67,6 +72,27 @@ void tcp_client_endpoint_impl::restart() {
}
{
std::lock_guard<std::mutex> its_lock(mutex_);
+ for (const auto&m : queue_) {
+ const service_t its_service = VSOMEIP_BYTES_TO_WORD(
+ (*m)[VSOMEIP_SERVICE_POS_MIN],
+ (*m)[VSOMEIP_SERVICE_POS_MAX]);
+ const method_t its_method = VSOMEIP_BYTES_TO_WORD(
+ (*m)[VSOMEIP_METHOD_POS_MIN],
+ (*m)[VSOMEIP_METHOD_POS_MAX]);
+ const client_t its_client = VSOMEIP_BYTES_TO_WORD(
+ (*m)[VSOMEIP_CLIENT_POS_MIN],
+ (*m)[VSOMEIP_CLIENT_POS_MAX]);
+ const session_t its_session = VSOMEIP_BYTES_TO_WORD(
+ (*m)[VSOMEIP_SESSION_POS_MIN],
+ (*m)[VSOMEIP_SESSION_POS_MAX]);
+ VSOMEIP_WARNING << "tce::restart: dropping message: "
+ << "remote:" << get_address_port_remote() << " ("
+ << std::hex << std::setw(4) << std::setfill('0') << its_client <<"): ["
+ << std::hex << std::setw(4) << std::setfill('0') << its_service << "."
+ << std::hex << std::setw(4) << std::setfill('0') << its_method << "."
+ << std::hex << std::setw(4) << std::setfill('0') << its_session << "]"
+ << " size: " << std::dec << m->size();
+ }
queue_.clear();
}
start_connect_timer();
@@ -174,6 +200,18 @@ void tcp_client_endpoint_impl::send_queued() {
} else {
return;
}
+ const service_t its_service = VSOMEIP_BYTES_TO_WORD(
+ (*its_buffer)[VSOMEIP_SERVICE_POS_MIN],
+ (*its_buffer)[VSOMEIP_SERVICE_POS_MAX]);
+ const method_t its_method = VSOMEIP_BYTES_TO_WORD(
+ (*its_buffer)[VSOMEIP_METHOD_POS_MIN],
+ (*its_buffer)[VSOMEIP_METHOD_POS_MAX]);
+ const client_t its_client = VSOMEIP_BYTES_TO_WORD(
+ (*its_buffer)[VSOMEIP_CLIENT_POS_MIN],
+ (*its_buffer)[VSOMEIP_CLIENT_POS_MAX]);
+ const session_t its_session = VSOMEIP_BYTES_TO_WORD(
+ (*its_buffer)[VSOMEIP_SESSION_POS_MIN],
+ (*its_buffer)[VSOMEIP_SESSION_POS_MAX]);
if (has_enabled_magic_cookies_) {
const std::chrono::steady_clock::time_point now =
@@ -200,6 +238,13 @@ void tcp_client_endpoint_impl::send_queued() {
boost::asio::async_write(
*socket_,
boost::asio::buffer(*its_buffer),
+ std::bind(&tcp_client_endpoint_impl::write_completion_condition,
+ std::static_pointer_cast<tcp_client_endpoint_impl>(shared_from_this()),
+ std::placeholders::_1,
+ std::placeholders::_2,
+ its_buffer->size(),
+ its_service, its_method, its_client, its_session,
+ std::chrono::steady_clock::now()),
std::bind(
&tcp_client_endpoint_base_impl::send_cbk,
shared_from_this(),
@@ -233,6 +278,55 @@ void tcp_client_endpoint_impl::set_local_port() {
}
}
+std::size_t tcp_client_endpoint_impl::write_completion_condition(
+ const boost::system::error_code& _error, std::size_t _bytes_transferred,
+ std::size_t _bytes_to_send, service_t _service, method_t _method,
+ client_t _client, session_t _session,
+ std::chrono::steady_clock::time_point _start) {
+
+ if (_error) {
+ VSOMEIP_ERROR << "tce::write_completion_condition: "
+ << _error.message() << "(" << std::dec << _error.value()
+ << ") bytes transferred: " << std::dec << _bytes_transferred
+ << " bytes to sent: " << std::dec << _bytes_to_send << " "
+ << "remote:" << get_address_port_remote() << " ("
+ << std::hex << std::setw(4) << std::setfill('0') << _client <<"): ["
+ << std::hex << std::setw(4) << std::setfill('0') << _service << "."
+ << std::hex << std::setw(4) << std::setfill('0') << _method << "."
+ << std::hex << std::setw(4) << std::setfill('0') << _session << "]";
+ return 0;
+ }
+
+ std::chrono::steady_clock::time_point now = std::chrono::steady_clock::now();
+ std::chrono::milliseconds passed = std::chrono::duration_cast<std::chrono::milliseconds>(now - _start);
+ if (passed > send_timeout_warning_) {
+ if (passed > send_timeout_) {
+ VSOMEIP_ERROR << "tce::write_completion_condition: "
+ << _error.message() << "(" << std::dec << _error.value()
+ << ") took longer than " << std::dec << send_timeout_.count()
+ << "ms bytes transferred: " << std::dec << _bytes_transferred
+ << " bytes to sent: " << std::dec << _bytes_to_send << " "
+ << "remote:" << get_address_port_remote() << " ("
+ << std::hex << std::setw(4) << std::setfill('0') << _client <<"): ["
+ << std::hex << std::setw(4) << std::setfill('0') << _service << "."
+ << std::hex << std::setw(4) << std::setfill('0') << _method << "."
+ << std::hex << std::setw(4) << std::setfill('0') << _session << "]";
+ } else {
+ VSOMEIP_WARNING << "tce::write_completion_condition: "
+ << _error.message() << "(" << std::dec << _error.value()
+ << ") took longer than " << std::dec << send_timeout_warning_.count()
+ << "ms bytes transferred: " << std::dec << _bytes_transferred
+ << " bytes to sent: " << std::dec << _bytes_to_send << " "
+ << "remote:" << get_address_port_remote() << " ("
+ << std::hex << std::setw(4) << std::setfill('0') << _client <<"): ["
+ << std::hex << std::setw(4) << std::setfill('0') << _service << "."
+ << std::hex << std::setw(4) << std::setfill('0') << _method << "."
+ << std::hex << std::setw(4) << std::setfill('0') << _session << "]";
+ }
+ }
+ return _bytes_to_send - _bytes_transferred;
+}
+
std::uint16_t tcp_client_endpoint_impl::get_remote_port() const {
return remote_port_;
}
diff --git a/implementation/endpoints/src/tcp_server_endpoint_impl.cpp b/implementation/endpoints/src/tcp_server_endpoint_impl.cpp
index 2392f58..37e3554 100644
--- a/implementation/endpoints/src/tcp_server_endpoint_impl.cpp
+++ b/implementation/endpoints/src/tcp_server_endpoint_impl.cpp
@@ -14,6 +14,7 @@
#include "../include/tcp_server_endpoint_impl.hpp"
#include "../../logging/include/logger.hpp"
#include "../../utility/include/utility.hpp"
+#include "../../utility/include/byteorder.hpp"
#include "../../configuration/include/internal.hpp"
namespace ip = boost::asio::ip;
@@ -23,11 +24,13 @@ namespace vsomeip {
tcp_server_endpoint_impl::tcp_server_endpoint_impl(
std::shared_ptr<endpoint_host> _host, endpoint_type _local,
boost::asio::io_service &_io, std::uint32_t _max_message_size,
- std::uint32_t _buffer_shrink_threshold)
+ std::uint32_t _buffer_shrink_threshold,
+ std::chrono::milliseconds _send_timeout)
: tcp_server_endpoint_base_impl(_host, _local, _io, _max_message_size),
acceptor_(_io),
buffer_shrink_threshold_(_buffer_shrink_threshold),
- local_port_(_local.port()) {
+ local_port_(_local.port()),
+ send_timeout_(_send_timeout) {
is_supporting_magic_cookies_ = true;
boost::system::error_code ec;
@@ -55,7 +58,7 @@ void tcp_server_endpoint_impl::start() {
std::dynamic_pointer_cast<tcp_server_endpoint_impl>(
shared_from_this()), max_message_size_,
buffer_shrink_threshold_, has_enabled_magic_cookies_,
- service_);
+ service_, send_timeout_);
{
std::unique_lock<std::mutex> its_socket_lock(new_connection->get_socket_lock());
@@ -203,7 +206,8 @@ tcp_server_endpoint_impl::connection::connection(
std::uint32_t _initial_recv_buffer_size,
std::uint32_t _buffer_shrink_threshold,
bool _magic_cookies_enabled,
- boost::asio::io_service &_io_service) :
+ boost::asio::io_service &_io_service,
+ std::chrono::milliseconds _send_timeout) :
socket_(_io_service),
server_(_server),
max_message_size_(_max_message_size),
@@ -215,7 +219,9 @@ tcp_server_endpoint_impl::connection::connection(
buffer_shrink_threshold_(_buffer_shrink_threshold),
remote_port_(0),
magic_cookies_enabled_(_magic_cookies_enabled),
- last_cookie_sent_(std::chrono::steady_clock::now() - std::chrono::seconds(11)) {
+ last_cookie_sent_(std::chrono::steady_clock::now() - std::chrono::seconds(11)),
+ send_timeout_(_send_timeout),
+ send_timeout_warning_(_send_timeout / 2) {
}
tcp_server_endpoint_impl::connection::ptr
@@ -224,14 +230,15 @@ tcp_server_endpoint_impl::connection::create(
std::uint32_t _max_message_size,
std::uint32_t _buffer_shrink_threshold,
bool _magic_cookies_enabled,
- boost::asio::io_service & _io_service) {
+ boost::asio::io_service & _io_service,
+ std::chrono::milliseconds _send_timeout) {
const std::uint32_t its_initial_receveive_buffer_size =
VSOMEIP_SOMEIP_HEADER_SIZE + 8 + MAGIC_COOKIE_SIZE + 8
+ VSOMEIP_MAX_TCP_MESSAGE_SIZE;
return ptr(new connection(_server, _max_message_size,
its_initial_receveive_buffer_size,
_buffer_shrink_threshold, _magic_cookies_enabled,
- _io_service));
+ _io_service, _send_timeout));
}
tcp_server_endpoint_impl::socket_type &
@@ -304,6 +311,18 @@ void tcp_server_endpoint_impl::connection::send_queued(
return;
}
message_buffer_ptr_t its_buffer = _queue_iterator->second.front();
+ const service_t its_service = VSOMEIP_BYTES_TO_WORD(
+ (*its_buffer)[VSOMEIP_SERVICE_POS_MIN],
+ (*its_buffer)[VSOMEIP_SERVICE_POS_MAX]);
+ const method_t its_method = VSOMEIP_BYTES_TO_WORD(
+ (*its_buffer)[VSOMEIP_METHOD_POS_MIN],
+ (*its_buffer)[VSOMEIP_METHOD_POS_MAX]);
+ const client_t its_client = VSOMEIP_BYTES_TO_WORD(
+ (*its_buffer)[VSOMEIP_CLIENT_POS_MIN],
+ (*its_buffer)[VSOMEIP_CLIENT_POS_MAX]);
+ const session_t its_session = VSOMEIP_BYTES_TO_WORD(
+ (*its_buffer)[VSOMEIP_SESSION_POS_MIN],
+ (*its_buffer)[VSOMEIP_SESSION_POS_MAX]);
if (magic_cookies_enabled_) {
const std::chrono::steady_clock::time_point now =
std::chrono::steady_clock::now();
@@ -317,6 +336,13 @@ void tcp_server_endpoint_impl::connection::send_queued(
{
std::lock_guard<std::mutex> its_lock(socket_mutex_);
boost::asio::async_write(socket_, boost::asio::buffer(*its_buffer),
+ std::bind(&tcp_server_endpoint_impl::connection::write_completion_condition,
+ shared_from_this(),
+ std::placeholders::_1,
+ std::placeholders::_2,
+ its_buffer->size(),
+ its_service, its_method, its_client, its_session,
+ std::chrono::steady_clock::now()),
std::bind(&tcp_server_endpoint_base_impl::send_cbk,
its_server,
_queue_iterator,
@@ -630,6 +656,70 @@ tcp_server_endpoint_impl::connection::get_recv_buffer_capacity() const {
return recv_buffer_.capacity();
}
+std::size_t
+tcp_server_endpoint_impl::connection::write_completion_condition(
+ const boost::system::error_code& _error,
+ std::size_t _bytes_transferred, std::size_t _bytes_to_send,
+ service_t _service, method_t _method, client_t _client, session_t _session,
+ std::chrono::steady_clock::time_point _start) {
+ if (_error) {
+ VSOMEIP_ERROR << "tse::write_completion_condition: "
+ << _error.message() << "(" << std::dec << _error.value()
+ << ") bytes transferred: " << std::dec << _bytes_transferred
+ << " bytes to sent: " << std::dec << _bytes_to_send << " "
+ << "remote:" << get_address_port_remote() << " ("
+ << std::hex << std::setw(4) << std::setfill('0') << _client <<"): ["
+ << std::hex << std::setw(4) << std::setfill('0') << _service << "."
+ << std::hex << std::setw(4) << std::setfill('0') << _method << "."
+ << std::hex << std::setw(4) << std::setfill('0') << _session << "]";
+ stop_and_remove_connection();
+ return 0;
+ }
+
+ std::chrono::steady_clock::time_point now = std::chrono::steady_clock::now();
+ std::chrono::milliseconds passed = std::chrono::duration_cast<std::chrono::milliseconds>(now - _start);
+ if (passed > send_timeout_warning_) {
+ if (passed > send_timeout_) {
+ VSOMEIP_ERROR << "tse::write_completion_condition: "
+ << _error.message() << "(" << std::dec << _error.value()
+ << ") took longer than " << std::dec << send_timeout_.count()
+ << "ms bytes transferred: " << std::dec << _bytes_transferred
+ << " bytes to sent: " << std::dec << _bytes_to_send
+ << " remote:" << get_address_port_remote() << " ("
+ << std::hex << std::setw(4) << std::setfill('0') << _client <<"): ["
+ << std::hex << std::setw(4) << std::setfill('0') << _service << "."
+ << std::hex << std::setw(4) << std::setfill('0') << _method << "."
+ << std::hex << std::setw(4) << std::setfill('0') << _session << "]";
+ } else {
+ VSOMEIP_WARNING << "tse::write_completion_condition: "
+ << _error.message() << "(" << std::dec << _error.value()
+ << ") took longer than " << std::dec << send_timeout_warning_.count()
+ << "ms bytes transferred: " << std::dec << _bytes_transferred
+ << " bytes to sent: " << std::dec << _bytes_to_send
+ << " remote:" << get_address_port_remote() << " ("
+ << std::hex << std::setw(4) << std::setfill('0') << _client <<"): ["
+ << std::hex << std::setw(4) << std::setfill('0') << _service << "."
+ << std::hex << std::setw(4) << std::setfill('0') << _method << "."
+ << std::hex << std::setw(4) << std::setfill('0') << _session << "]";
+ }
+ }
+ return _bytes_to_send - _bytes_transferred;
+}
+
+void tcp_server_endpoint_impl::connection::stop_and_remove_connection() {
+ std::shared_ptr<tcp_server_endpoint_impl> its_server(server_.lock());
+ if (!its_server) {
+ VSOMEIP_ERROR << "tse::connection::stop_and_remove_connection "
+ " couldn't lock server_";
+ return;
+ }
+ {
+ std::lock_guard<std::mutex> its_lock(its_server->connections_mutex_);
+ stop();
+ }
+ its_server->remove_connection(this);
+}
+
// Dummies
void tcp_server_endpoint_impl::receive() {
// intentionally left empty
diff --git a/implementation/routing/include/routing_manager_proxy.hpp b/implementation/routing/include/routing_manager_proxy.hpp
index dcf6152..806024b 100644
--- a/implementation/routing/include/routing_manager_proxy.hpp
+++ b/implementation/routing/include/routing_manager_proxy.hpp
@@ -29,7 +29,8 @@ class logger;
class routing_manager_proxy: public routing_manager_base {
public:
- routing_manager_proxy(routing_manager_host *_host, bool _client_side_logging);
+ routing_manager_proxy(routing_manager_host *_host, bool _client_side_logging,
+ const std::set<std::tuple<service_t, instance_t> > & _client_side_logging_filter);
virtual ~routing_manager_proxy();
void init();
@@ -217,13 +218,14 @@ private:
std::set<event_data_t> pending_event_registrations_;
std::map<client_t, std::set<subscription_data_t>> pending_incoming_subscripitons_;
- std::mutex incoming_subscripitons_mutex_;
+ std::mutex incoming_subscriptions_mutex_;
std::mutex state_mutex_;
std::condition_variable state_condition_;
std::map<service_t,
std::map<instance_t, std::map<eventgroup_t, uint32_t > > > remote_subscriber_count_;
+ std::mutex remote_subscriber_count_mutex_;
mutable std::mutex sender_mutex_;
@@ -236,6 +238,7 @@ private:
bool request_debounce_timer_running_;
const bool client_side_logging_;
+ const std::set<std::tuple<service_t, instance_t> > client_side_logging_filter_;
};
} // namespace vsomeip
diff --git a/implementation/routing/include/routing_manager_stub.hpp b/implementation/routing/include/routing_manager_stub.hpp
index ec5dd4e..f825b0b 100644
--- a/implementation/routing/include/routing_manager_stub.hpp
+++ b/implementation/routing/include/routing_manager_stub.hpp
@@ -154,6 +154,7 @@ private:
std::string local_receiver_path_;
std::shared_ptr<endpoint> endpoint_;
std::shared_ptr<endpoint> local_receiver_;
+ std::mutex local_receiver_mutex_;
std::map<client_t,
std::pair<uint8_t, std::map<service_t, std::map<instance_t, std::pair<major_version_t, minor_version_t>> > > > routing_info_;
diff --git a/implementation/routing/src/routing_manager_base.cpp b/implementation/routing/src/routing_manager_base.cpp
index 9036e5a..1d0c795 100644
--- a/implementation/routing/src/routing_manager_base.cpp
+++ b/implementation/routing/src/routing_manager_base.cpp
@@ -1001,10 +1001,8 @@ std::shared_ptr<deserializer> routing_manager_base::get_deserializer() {
}
void routing_manager_base::put_deserializer(std::shared_ptr<deserializer> _deserializer) {
- {
- std::lock_guard<std::mutex> its_lock(deserializer_mutex_);
- deserializers_.push(_deserializer);
- }
+ std::lock_guard<std::mutex> its_lock(deserializer_mutex_);
+ deserializers_.push(_deserializer);
deserializer_condition_.notify_one();
}
diff --git a/implementation/routing/src/routing_manager_impl.cpp b/implementation/routing/src/routing_manager_impl.cpp
index 34398ad..88aaca3 100644
--- a/implementation/routing/src/routing_manager_impl.cpp
+++ b/implementation/routing/src/routing_manager_impl.cpp
@@ -1726,7 +1726,8 @@ std::shared_ptr<endpoint> routing_manager_impl::create_client_endpoint(
io_,
configuration_->get_max_message_size_reliable(
_address.to_string(), _remote_port),
- configuration_->get_buffer_shrink_threshold());
+ configuration_->get_buffer_shrink_threshold(),
+ std::chrono::milliseconds(configuration_->get_sd_ttl() * 666));
if (configuration_->has_enabled_magic_cookies(_address.to_string(),
_remote_port)) {
@@ -1763,7 +1764,8 @@ std::shared_ptr<endpoint> routing_manager_impl::create_server_endpoint(
boost::asio::ip::tcp::endpoint(its_unicast, _port), io_,
configuration_->get_max_message_size_reliable(
its_unicast.to_string(), _port),
- configuration_->get_buffer_shrink_threshold());
+ configuration_->get_buffer_shrink_threshold(),
+ std::chrono::milliseconds(configuration_->get_sd_ttl() * 666));
if (configuration_->has_enabled_magic_cookies(
its_unicast.to_string(), _port) ||
configuration_->has_enabled_magic_cookies(
diff --git a/implementation/routing/src/routing_manager_proxy.cpp b/implementation/routing/src/routing_manager_proxy.cpp
index 4224b57..a62ee96 100644
--- a/implementation/routing/src/routing_manager_proxy.cpp
+++ b/implementation/routing/src/routing_manager_proxy.cpp
@@ -36,7 +36,8 @@
namespace vsomeip {
routing_manager_proxy::routing_manager_proxy(routing_manager_host *_host,
- bool _client_side_logging) :
+ bool _client_side_logging,
+ const std::set<std::tuple<service_t, instance_t> > & _client_side_logging_filter) :
routing_manager_base(_host),
is_connected_(false),
is_started_(false),
@@ -47,7 +48,8 @@ routing_manager_proxy::routing_manager_proxy(routing_manager_host *_host,
logger_(logger::get()),
request_debounce_timer_ (io_),
request_debounce_timer_running_(false),
- client_side_logging_(_client_side_logging)
+ client_side_logging_(_client_side_logging),
+ client_side_logging_filter_(_client_side_logging_filter)
{
}
@@ -625,24 +627,28 @@ bool routing_manager_proxy::send(client_t _client, const byte_t *_data,
service_t its_service = VSOMEIP_BYTES_TO_WORD(
_data[VSOMEIP_SERVICE_POS_MIN],
_data[VSOMEIP_SERVICE_POS_MAX]);
- method_t its_method = VSOMEIP_BYTES_TO_WORD(
- _data[VSOMEIP_METHOD_POS_MIN],
- _data[VSOMEIP_METHOD_POS_MAX]);
- session_t its_session = VSOMEIP_BYTES_TO_WORD(
- _data[VSOMEIP_SESSION_POS_MIN],
- _data[VSOMEIP_SESSION_POS_MAX]);
- client_t its_client = VSOMEIP_BYTES_TO_WORD(
- _data[VSOMEIP_CLIENT_POS_MIN],
- _data[VSOMEIP_CLIENT_POS_MAX]);
- VSOMEIP_INFO << "routing_manager_proxy::send: ("
- << std::hex << std::setw(4) << std::setfill('0') << client_ <<"): ["
- << std::hex << std::setw(4) << std::setfill('0') << its_service << "."
- << std::hex << std::setw(4) << std::setfill('0') << _instance << "."
- << std::hex << std::setw(4) << std::setfill('0') << its_method << ":"
- << std::hex << std::setw(4) << std::setfill('0') << its_session << ":"
- << std::hex << std::setw(4) << std::setfill('0') << its_client << "] "
- << "type=" << std::hex << static_cast<std::uint32_t>(_data[VSOMEIP_MESSAGE_TYPE_POS])
- << " thread=" << std::hex << std::this_thread::get_id();
+ if (client_side_logging_filter_.empty()
+ || (1 == client_side_logging_filter_.count(std::make_tuple(its_service, ANY_INSTANCE)))
+ || (1 == client_side_logging_filter_.count(std::make_tuple(its_service, _instance)))) {
+ method_t its_method = VSOMEIP_BYTES_TO_WORD(
+ _data[VSOMEIP_METHOD_POS_MIN],
+ _data[VSOMEIP_METHOD_POS_MAX]);
+ session_t its_session = VSOMEIP_BYTES_TO_WORD(
+ _data[VSOMEIP_SESSION_POS_MIN],
+ _data[VSOMEIP_SESSION_POS_MAX]);
+ client_t its_client = VSOMEIP_BYTES_TO_WORD(
+ _data[VSOMEIP_CLIENT_POS_MIN],
+ _data[VSOMEIP_CLIENT_POS_MAX]);
+ VSOMEIP_INFO << "routing_manager_proxy::send: ("
+ << std::hex << std::setw(4) << std::setfill('0') << client_ <<"): ["
+ << std::hex << std::setw(4) << std::setfill('0') << its_service << "."
+ << std::hex << std::setw(4) << std::setfill('0') << _instance << "."
+ << std::hex << std::setw(4) << std::setfill('0') << its_method << ":"
+ << std::hex << std::setw(4) << std::setfill('0') << its_session << ":"
+ << std::hex << std::setw(4) << std::setfill('0') << its_client << "] "
+ << "type=" << std::hex << static_cast<std::uint32_t>(_data[VSOMEIP_MESSAGE_TYPE_POS])
+ << " thread=" << std::hex << std::this_thread::get_id();
+ }
} else {
VSOMEIP_ERROR << "routing_manager_proxy::send: ("
<< std::hex << std::setw(4) << std::setfill('0') << client_
@@ -924,7 +930,10 @@ void routing_manager_proxy::on_message(const byte_t *_data, length_t _size,
}
}
#ifdef USE_DLT
- if (client_side_logging_) {
+ if (client_side_logging_
+ && (client_side_logging_filter_.empty()
+ || (1 == client_side_logging_filter_.count(std::make_tuple(its_message->get_service(), ANY_INSTANCE)))
+ || (1 == client_side_logging_filter_.count(std::make_tuple(its_message->get_service(), its_message->get_instance()))))) {
tc::trace_header its_header;
if (its_header.prepare(nullptr, false, its_instance))
tc_->trace(its_header.data_, VSOMEIP_TRACE_HEADER_SIZE,
@@ -974,7 +983,7 @@ void routing_manager_proxy::on_message(const byte_t *_data, length_t _size,
std::memcpy(&its_subscription_id, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 10],
sizeof(its_subscription_id));
{
- std::unique_lock<std::mutex> its_lock(incoming_subscripitons_mutex_);
+ std::unique_lock<std::mutex> its_lock(incoming_subscriptions_mutex_);
if (its_subscription_id != DEFAULT_SUBSCRIPTION) {
its_lock.unlock();
// Remote subscriber: Notify routing manager initially + count subscribes
@@ -1216,10 +1225,9 @@ void routing_manager_proxy::on_routing_info(const byte_t *_data,
send_registered_ack();
send_pending_commands();
state_ = inner_state_type_e::ST_REGISTERED;
+ // Notify stop() call about clean deregistration
+ state_condition_.notify_one();
}
-
- // Notify stop() call about clean deregistration
- state_condition_.notify_one();
}
} else if (routing_info_entry == routing_info_entry_e::RIE_DEL_CLIENT) {
{
@@ -1236,10 +1244,9 @@ void routing_manager_proxy::on_routing_info(const byte_t *_data,
{
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();
}
-
- // Notify stop() call about clean deregistration
- state_condition_.notify_one();
} else if (its_client != VSOMEIP_ROUTING_CLIENT) {
remove_local(its_client);
}
@@ -1327,7 +1334,7 @@ void routing_manager_proxy::on_routing_info(const byte_t *_data,
major_version_t major_;
event_t event_;
};
- std::lock_guard<std::mutex> its_lock(incoming_subscripitons_mutex_);
+ std::lock_guard<std::mutex> its_lock(incoming_subscriptions_mutex_);
std::forward_list<struct subscription_info> subscription_actions;
if (pending_incoming_subscripitons_.size()) {
{
@@ -1429,10 +1436,10 @@ void routing_manager_proxy::reconnect(const std::unordered_set<client_t> &_clien
{
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();
}
- // Notify stop() call about clean deregistration
- state_condition_.notify_one();
// Remove all local connections/endpoints
for (const auto its_client : _clients) {
@@ -1830,6 +1837,7 @@ void routing_manager_proxy::notify_remote_initially(service_t _service, instance
uint32_t routing_manager_proxy::get_remote_subscriber_count(service_t _service,
instance_t _instance, eventgroup_t _eventgroup, bool _increment) {
+ std::lock_guard<std::mutex> its_lock(remote_subscriber_count_mutex_);
uint32_t count (0);
bool found(false);
auto found_service = remote_subscriber_count_.find(_service);
diff --git a/implementation/routing/src/routing_manager_stub.cpp b/implementation/routing/src/routing_manager_stub.cpp
index 08a91c7..504458e 100644
--- a/implementation/routing/src/routing_manager_stub.cpp
+++ b/implementation/routing/src/routing_manager_stub.cpp
@@ -1287,6 +1287,8 @@ void routing_manager_stub::send_subscribe_ack(client_t _client, service_t _servi
sizeof(_client));
std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 8], &_event,
sizeof(_event));
+ std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 10],
+ &DEFAULT_SUBSCRIPTION, sizeof(DEFAULT_SUBSCRIPTION));
its_endpoint->send(&its_command[0], sizeof(its_command), true);
}
@@ -1317,6 +1319,8 @@ void routing_manager_stub::send_subscribe_nack(client_t _client, service_t _serv
sizeof(_client));
std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 8], &_event,
sizeof(_event));
+ std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 10],
+ &DEFAULT_SUBSCRIPTION, sizeof(DEFAULT_SUBSCRIPTION));
its_endpoint->send(&its_command[0], sizeof(its_command), true);
}
@@ -1420,6 +1424,8 @@ void routing_manager_stub::check_watchdog() {
}
void routing_manager_stub::create_local_receiver() {
+ std::lock_guard<std::mutex> its_lock(local_receiver_mutex_);
+
if (local_receiver_) {
return;
}
@@ -1791,9 +1797,9 @@ void routing_manager_stub::on_client_id_timer_expired(boost::system::error_code
}
}
for (auto client : erroneous_clients) {
- VSOMEIP_WARNING << "Expected client 0x" << std::hex
- << client << " hasn't reconnected to the routing manager. "
- << "Release identifier as client went offline while no"
+ VSOMEIP_WARNING << "Releasing client identifier "
+ << std::hex << std::setw(4) << std::setfill('0') << client << ". "
+ << "Its corresponding application went offline while no "
<< "routing manager was running.";
host_->handle_client_error(client);
}
diff --git a/implementation/runtime/include/application_impl.hpp b/implementation/runtime/include/application_impl.hpp
index 28ce86b..2d6cd82 100644
--- a/implementation/runtime/include/application_impl.hpp
+++ b/implementation/runtime/include/application_impl.hpp
@@ -368,8 +368,8 @@ private:
std::map<std::thread::id, std::shared_ptr<std::thread>> dispatchers_;
// Dispatcher threads that elapsed and can be removed
std::set<std::thread::id> elapsed_dispatchers_;
- // Dispatcher threads that blocked
- std::set<std::thread::id> blocked_dispatchers_;
+ // Dispatcher threads that are running
+ std::set<std::thread::id> running_dispatchers_;
// Mutex to protect access to dispatchers_ & elapsed_dispatchers_
std::mutex dispatcher_mutex_;
// Condition to wakeup the dispatcher thread
@@ -418,6 +418,7 @@ private:
std::chrono::seconds watchdog_interval_;
bool client_side_logging_;
+ std::set<std::tuple<service_t, instance_t> > client_side_logging_filter_;
};
} // namespace vsomeip
diff --git a/implementation/runtime/src/application_impl.cpp b/implementation/runtime/src/application_impl.cpp
index a282399..1d49df1 100644
--- a/implementation/runtime/src/application_impl.cpp
+++ b/implementation/runtime/src/application_impl.cpp
@@ -108,6 +108,48 @@ bool application_impl::init() {
client_side_logging_ = true;
VSOMEIP_INFO << "Client side logging for application: " << name_
<< " is enabled";
+
+ if ('\0' != *client_side_logging) {
+ std::stringstream its_converter(client_side_logging);
+ if ('"' == its_converter.peek()) {
+ its_converter.get(); // skip quote
+ }
+ uint16_t val(0xffffu);
+ bool stop_parsing(false);
+ do {
+ const uint16_t prev_val(val);
+ its_converter >> std::hex >> std::setw(4) >> val;
+ if (its_converter.good()) {
+ const std::stringstream::int_type c = its_converter.eof()?'\0':its_converter.get();
+ switch (c) {
+ case '"':
+ case '.':
+ case ':':
+ case ' ':
+ case '\0': {
+ if ('.' != c) {
+ if (0xffffu == prev_val) {
+ VSOMEIP_INFO << "+filter "
+ << std::hex << std::setw(4) << std::setfill('0') << val;
+ client_side_logging_filter_.insert(std::make_tuple(val, ANY_INSTANCE));
+ } else {
+ VSOMEIP_INFO << "+filter "
+ << std::hex << std::setw(4) << std::setfill('0') << prev_val << "."
+ << std::hex << std::setw(4) << std::setfill('0') << val;
+ client_side_logging_filter_.insert(std::make_tuple(prev_val, val));
+ }
+ val = 0xffffu;
+ }
+ }
+ break;
+ default:
+ stop_parsing = true;
+ break;
+ }
+ }
+ }
+ while (!stop_parsing && its_converter.good());
+ }
}
std::shared_ptr<configuration> its_configuration = get_configuration();
@@ -157,7 +199,7 @@ bool application_impl::init() {
routing_ = std::make_shared<routing_manager_impl>(this);
} else {
VSOMEIP_INFO << "Instantiating routing manager [Proxy].";
- routing_ = std::make_shared<routing_manager_proxy>(this, client_side_logging_);
+ routing_ = std::make_shared<routing_manager_proxy>(this, client_side_logging_, client_side_logging_filter_);
}
routing_->init();
@@ -273,8 +315,8 @@ void application_impl::start() {
{
std::lock_guard<std::mutex> its_lock_start_stop(block_stop_mutex_);
block_stopping_ = true;
+ block_stop_cv_.notify_all();
}
- block_stop_cv_.notify_all();
stopped_ = false;
return;
@@ -357,8 +399,8 @@ void application_impl::start() {
{
std::lock_guard<std::mutex> its_lock_start_stop(block_stop_mutex_);
block_stopping_ = true;
+ block_stop_cv_.notify_all();
}
- block_stop_cv_.notify_all();
{
std::lock_guard<std::mutex> its_lock(start_stop_mutex_);
@@ -414,7 +456,10 @@ void application_impl::stop() {
}
- stop_cv_.notify_one();
+ {
+ std::lock_guard<std::mutex> its_lock_start_stop(start_stop_mutex_);
+ stop_cv_.notify_one();
+ }
if (block) {
std::unique_lock<std::mutex> block_stop_lock(block_stop_mutex_);
@@ -697,7 +742,10 @@ bool application_impl::are_available_unlocked(available_t &_available,
void application_impl::send(std::shared_ptr<message> _message, bool _flush) {
std::lock_guard<std::mutex> its_lock(session_mutex_);
bool is_request = utility::is_request(_message);
- if (client_side_logging_) {
+ if (client_side_logging_
+ && (client_side_logging_filter_.empty()
+ || (1 == client_side_logging_filter_.count(std::make_tuple(_message->get_service(), ANY_INSTANCE)))
+ || (1 == client_side_logging_filter_.count(std::make_tuple(_message->get_service(), _message->get_instance()))))) {
VSOMEIP_INFO << "application_impl::send: ("
<< std::hex << std::setw(4) << std::setfill('0') << client_ <<"): ["
<< std::hex << std::setw(4) << std::setfill('0') << _message->get_service() << "."
@@ -1029,24 +1077,26 @@ void application_impl::deliver_subscription_state(service_t _service, instance_t
}
}
}
- for (auto &handler : handlers) {
+ {
std::unique_lock<std::mutex> handlers_lock(handlers_mutex_);
- std::shared_ptr<sync_handler> its_sync_handler
- = std::make_shared<sync_handler>([handler, _service,
- _instance, _eventgroup,
- _event, _error]() {
- handler(_service, _instance,
- _eventgroup, _event, _error);
- });
- its_sync_handler->handler_type_ = handler_type_e::SUBSCRIPTION;
- its_sync_handler->service_id_ = _service;
- its_sync_handler->instance_id_ = _instance;
- its_sync_handler->method_id_ = _event;
- its_sync_handler->eventgroup_id_ = _eventgroup;
- handlers_.push_back(its_sync_handler);
- }
- if (handlers.size()) {
- dispatcher_condition_.notify_all();
+ for (auto &handler : handlers) {
+ std::shared_ptr<sync_handler> its_sync_handler
+ = std::make_shared<sync_handler>([handler, _service,
+ _instance, _eventgroup,
+ _event, _error]() {
+ handler(_service, _instance,
+ _eventgroup, _event, _error);
+ });
+ its_sync_handler->handler_type_ = handler_type_e::SUBSCRIPTION;
+ its_sync_handler->service_id_ = _service;
+ its_sync_handler->instance_id_ = _instance;
+ its_sync_handler->method_id_ = _event;
+ its_sync_handler->eventgroup_id_ = _eventgroup;
+ handlers_.push_back(its_sync_handler);
+ }
+ if (handlers.size()) {
+ dispatcher_condition_.notify_one();
+ }
}
}
@@ -1069,18 +1119,16 @@ void application_impl::on_subscription_error(service_t _service,
}
}
if (handler) {
- {
- std::unique_lock<std::mutex> handlers_lock(handlers_mutex_);
- std::shared_ptr<sync_handler> its_sync_handler
- = std::make_shared<sync_handler>([handler, _error]() {
- handler(_error);
- });
- its_sync_handler->handler_type_ = handler_type_e::SUBSCRIPTION;
- its_sync_handler->service_id_ = _service;
- its_sync_handler->instance_id_ = _instance;
- its_sync_handler->eventgroup_id_ = _eventgroup;
- handlers_.push_back(its_sync_handler);
- }
+ std::unique_lock<std::mutex> handlers_lock(handlers_mutex_);
+ std::shared_ptr<sync_handler> its_sync_handler
+ = std::make_shared<sync_handler>([handler, _error]() {
+ handler(_error);
+ });
+ its_sync_handler->handler_type_ = handler_type_e::SUBSCRIPTION;
+ its_sync_handler->service_id_ = _service;
+ its_sync_handler->instance_id_ = _instance;
+ its_sync_handler->eventgroup_id_ = _eventgroup;
+ handlers_.push_back(its_sync_handler);
dispatcher_condition_.notify_all();
}
}
@@ -1257,15 +1305,13 @@ void application_impl::on_state(state_type_e _state) {
}
}
if (has_state_handler) {
- {
- std::lock_guard<std::mutex> its_lock(handlers_mutex_);
- std::shared_ptr<sync_handler> its_sync_handler
- = std::make_shared<sync_handler>([handler, _state]() {
- handler(_state);
- });
- its_sync_handler->handler_type_ = handler_type_e::STATE;
- handlers_.push_back(its_sync_handler);
- }
+ std::lock_guard<std::mutex> its_lock(handlers_mutex_);
+ std::shared_ptr<sync_handler> its_sync_handler
+ = std::make_shared<sync_handler>([handler, _state]() {
+ handler(_state);
+ });
+ its_sync_handler->handler_type_ = handler_type_e::STATE;
+ handlers_.push_back(its_sync_handler);
dispatcher_condition_.notify_one();
}
}
@@ -1391,6 +1437,7 @@ void application_impl::on_availability(service_t _service, instance_t _instance,
}
if (its_handlers.size()) {
+ std::lock_guard<std::mutex> handlers_lock(handlers_mutex_);
dispatcher_condition_.notify_one();
}
}
@@ -1466,21 +1513,19 @@ void application_impl::on_message(const std::shared_ptr<message> &&_message) {
}
if (its_handlers.size()) {
- {
- std::lock_guard<std::mutex> its_lock(handlers_mutex_);
- for (const auto &its_handler : its_handlers) {
- auto handler = its_handler.handler_;
- std::shared_ptr<sync_handler> its_sync_handler =
- std::make_shared<sync_handler>([handler, _message]() {
- handler(std::move(_message));
- });
- its_sync_handler->handler_type_ = handler_type_e::MESSAGE;
- its_sync_handler->service_id_ = _message->get_service();
- its_sync_handler->instance_id_ = _message->get_instance();
- its_sync_handler->method_id_ = _message->get_method();
- its_sync_handler->session_id_ = _message->get_session();
- handlers_.push_back(its_sync_handler);
- }
+ std::lock_guard<std::mutex> its_lock(handlers_mutex_);
+ for (const auto &its_handler : its_handlers) {
+ auto handler = its_handler.handler_;
+ std::shared_ptr<sync_handler> its_sync_handler =
+ std::make_shared<sync_handler>([handler, _message]() {
+ handler(std::move(_message));
+ });
+ its_sync_handler->handler_type_ = handler_type_e::MESSAGE;
+ its_sync_handler->service_id_ = _message->get_service();
+ its_sync_handler->instance_id_ = _message->get_instance();
+ its_sync_handler->method_id_ = _message->get_method();
+ its_sync_handler->session_id_ = _message->get_session();
+ handlers_.push_back(its_sync_handler);
}
dispatcher_condition_.notify_one();
}
@@ -1588,7 +1633,6 @@ void application_impl::invoke_handler(std::shared_ptr<sync_handler> &_handler) {
bool active_dispatcher_available(false);
if (is_dispatching_) {
std::lock_guard<std::mutex> its_lock(dispatcher_mutex_);
- blocked_dispatchers_.insert(its_id);
active_dispatcher_available = has_active_dispatcher();
}
if (active_dispatcher_available) {
@@ -1612,7 +1656,10 @@ void application_impl::invoke_handler(std::shared_ptr<sync_handler> &_handler) {
}
}
});
- if (client_side_logging_) {
+ if (client_side_logging_
+ && (client_side_logging_filter_.empty()
+ || (1 == client_side_logging_filter_.count(std::make_tuple(its_sync_handler->service_id_, ANY_INSTANCE)))
+ || (1 == client_side_logging_filter_.count(std::make_tuple(its_sync_handler->service_id_, its_sync_handler->instance_id_))))) {
VSOMEIP_INFO << "Invoking handler: ("
<< std::hex << std::setw(4) << std::setfill('0') << client_ <<"): ["
<< std::hex << std::setw(4) << std::setfill('0') << its_sync_handler->service_id_ << "."
@@ -1622,17 +1669,28 @@ void application_impl::invoke_handler(std::shared_ptr<sync_handler> &_handler) {
<< "type=" << static_cast<std::uint32_t>(its_sync_handler->handler_type_)
<< " thread=" << std::hex << its_id;
}
- _handler->handler_();
- its_dispatcher_timer.cancel();
+ {
+ std::lock_guard<std::mutex> its_lock(dispatcher_mutex_);
+ running_dispatchers_.insert(its_id);
+ }
+ try {
+ _handler->handler_();
+ } catch (const std::exception &e) {
+ VSOMEIP_ERROR << "application_impl::invoke_handler caught exception: "
+ << e.what();
+ print_blocking_call(its_sync_handler);
+ }
+ boost::system::error_code ec;
+ its_dispatcher_timer.cancel(ec);
if (is_dispatching_) {
std::lock_guard<std::mutex> its_lock(dispatcher_mutex_);
- blocked_dispatchers_.erase(its_id);
+ running_dispatchers_.erase(its_id);
}
}
bool application_impl::has_active_dispatcher() {
for (const auto &d : dispatchers_) {
- if (blocked_dispatchers_.find(d.first) == blocked_dispatchers_.end() &&
+ if (running_dispatchers_.find(d.first) == running_dispatchers_.end() &&
elapsed_dispatchers_.find(d.first) == elapsed_dispatchers_.end()) {
return true;
}
@@ -1647,7 +1705,7 @@ bool application_impl::is_active_dispatcher(const std::thread::id &_id) {
std::lock_guard<std::mutex> its_lock(dispatcher_mutex_);
for (const auto &d : dispatchers_) {
if (d.first != _id &&
- blocked_dispatchers_.find(d.first) == blocked_dispatchers_.end() &&
+ running_dispatchers_.find(d.first) == running_dispatchers_.end() &&
elapsed_dispatchers_.find(d.first) == elapsed_dispatchers_.end()) {
return false;
}
@@ -1741,7 +1799,7 @@ void application_impl::shutdown() {
its_dispatcher.second->detach();
}
}
- blocked_dispatchers_.clear();
+ running_dispatchers_.clear();
elapsed_dispatchers_.clear();
dispatchers_.clear();
}
@@ -2064,15 +2122,13 @@ void application_impl::on_offered_services_info(std::vector<std::pair<service_t,
}
}
if (has_offered_services_handler) {
- {
- std::lock_guard<std::mutex> its_lock(handlers_mutex_);
- std::shared_ptr<sync_handler> its_sync_handler
- = std::make_shared<sync_handler>([handler, _services]() {
- handler(_services);
- });
- its_sync_handler->handler_type_ = handler_type_e::OFFERED_SERVICES_INFO;
- handlers_.push_back(its_sync_handler);
- }
+ std::lock_guard<std::mutex> its_lock(handlers_mutex_);
+ std::shared_ptr<sync_handler> its_sync_handler
+ = std::make_shared<sync_handler>([handler, _services]() {
+ handler(_services);
+ });
+ its_sync_handler->handler_type_ = handler_type_e::OFFERED_SERVICES_INFO;
+ handlers_.push_back(its_sync_handler);
dispatcher_condition_.notify_one();
}
}
@@ -2097,9 +2153,8 @@ void application_impl::watchdog_cbk(boost::system::error_code const &_error) {
= std::make_shared<sync_handler>([handler]() { handler(); });
its_sync_handler->handler_type_ = handler_type_e::WATCHDOG;
handlers_.push_back(its_sync_handler);
+ dispatcher_condition_.notify_one();
}
- dispatcher_condition_.notify_one();
-
}
}
diff --git a/implementation/service_discovery/src/service_discovery_impl.cpp b/implementation/service_discovery/src/service_discovery_impl.cpp
index e25ca5b..f2171fb 100644
--- a/implementation/service_discovery/src/service_discovery_impl.cpp
+++ b/implementation/service_discovery/src/service_discovery_impl.cpp
@@ -1085,7 +1085,6 @@ bool service_discovery_impl::send(bool _is_announcing) {
std::shared_ptr < message_impl > its_message;
if(_is_announcing) {
- remote_subscription_not_acknowledge_all();
its_message = its_runtime->create_message();
its_messages.push_back(its_message);
diff --git a/test/application_tests/application_test.cpp b/test/application_tests/application_test.cpp
index b7c3ac0..7862528 100644
--- a/test/application_tests/application_test.cpp
+++ b/test/application_tests/application_test.cpp
@@ -310,6 +310,123 @@ protected:
std::thread shutdown_thread_;
};
+class someip_application_exception_test: public ::testing::Test {
+
+protected:
+ void SetUp() {
+ is_registered_ = false;
+ is_available_ = false;
+
+ app_ = runtime::get()->create_application("application_test");
+ if (!app_->init()) {
+ ADD_FAILURE() << "Couldn't initialize application";
+ return;
+ }
+
+ app_->register_message_handler(vsomeip_test::TEST_SERVICE_SERVICE_ID,
+ vsomeip_test::TEST_SERVICE_INSTANCE_ID,
+ vsomeip_test::TEST_SERVICE_METHOD_ID_SHUTDOWN,
+ std::bind(&someip_application_exception_test::on_message_shutdown, 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+1,
+ std::bind(&someip_application_exception_test::on_message_exception, this,
+ std::placeholders::_1));
+
+ app_->register_state_handler(
+ std::bind(&someip_application_exception_test::on_state, this,
+ std::placeholders::_1));
+ app_->register_availability_handler(
+ vsomeip_test::TEST_SERVICE_SERVICE_ID,
+ vsomeip_test::TEST_SERVICE_INSTANCE_ID,
+ std::bind(&someip_application_exception_test::on_availability,
+ this, std::placeholders::_1, std::placeholders::_2,
+ std::placeholders::_3));
+
+ shutdown_thread_ = std::thread(&someip_application_exception_test::send_shutdown_message, this);
+
+ app_->start();
+ }
+
+ void TearDown() {
+ shutdown_thread_.join();
+ app_->stop();
+ }
+
+ void on_state(vsomeip::state_type_e _state) {
+ if(_state == vsomeip::state_type_e::ST_REGISTERED)
+ {
+ std::lock_guard<std::mutex> its_lock(mutex_);
+ is_registered_ = true;
+ cv_.notify_one();
+ }
+ }
+
+ void on_availability(vsomeip::service_t _service,
+ vsomeip::instance_t _instance, bool _is_available) {
+ (void)_service;
+ (void)_instance;
+ if(_is_available) {
+ std::lock_guard<std::mutex> its_lock(mutex_);
+ is_available_ = _is_available;
+ cv_.notify_one();
+ }
+ }
+
+ void on_message_shutdown(const std::shared_ptr<message>& _request)
+ {
+ (void)_request;
+ VSOMEIP_INFO << "Shutdown method was called, going down now.";
+ app_->clear_all_handler();
+ app_->stop();
+ }
+
+ void on_message_exception(const std::shared_ptr<message>& _request)
+ {
+ (void)_request;
+ throw std::invalid_argument("something went terribly wrong");
+ }
+
+ void send_shutdown_message() {
+ {
+ std::unique_lock<std::mutex> its_lock(mutex_);
+ while(!is_registered_) {
+ cv_.wait(its_lock);
+ }
+ app_->request_service(vsomeip_test::TEST_SERVICE_SERVICE_ID,
+ vsomeip_test::TEST_SERVICE_INSTANCE_ID);
+ app_->offer_service(vsomeip_test::TEST_SERVICE_SERVICE_ID,
+ vsomeip_test::TEST_SERVICE_INSTANCE_ID);
+ while(!is_available_) {
+ cv_.wait(its_lock);
+ }
+ }
+
+ std::shared_ptr<message> r = runtime::get()->create_request();
+ // call method which throws exception
+ r->set_service(vsomeip_test::TEST_SERVICE_SERVICE_ID);
+ r->set_instance(vsomeip_test::TEST_SERVICE_INSTANCE_ID);
+ r->set_method(vsomeip_test::TEST_SERVICE_METHOD_ID_SHUTDOWN+1);
+ app_->send(r);
+ std::this_thread::sleep_for(std::chrono::milliseconds(50));
+
+
+ //shutdown test
+ r->set_service(vsomeip_test::TEST_SERVICE_SERVICE_ID);
+ r->set_instance(vsomeip_test::TEST_SERVICE_INSTANCE_ID);
+ r->set_method(vsomeip_test::TEST_SERVICE_METHOD_ID_SHUTDOWN);
+ app_->send(r);
+ }
+
+ bool is_registered_;
+ bool is_available_;
+ std::shared_ptr<application> app_;
+ std::condition_variable cv_;
+ std::mutex mutex_;
+ std::thread shutdown_thread_;
+};
+
/**
* @test Stop the application through a method invoked from a dispatcher thread
*/
@@ -317,6 +434,13 @@ TEST_F(someip_application_shutdown_test, stop_application_from_dispatcher_thread
}
+/**
+ * @test Catch unhandled exceptions from invoked handlers
+ */
+TEST_F(someip_application_exception_test, catch_exception_in_invoked_handler) {
+
+}
+
#ifndef _WIN32
int main(int argc, char** argv)
{