diff options
author | Jürgen Gehring <Juergen.Gehring@bmw.de> | 2016-12-12 03:57:25 -0800 |
---|---|---|
committer | Jürgen Gehring <Juergen.Gehring@bmw.de> | 2016-12-12 03:57:25 -0800 |
commit | ce34f857850ebf7bff1e4dc6c79574ff75abca56 (patch) | |
tree | d74c50b547412cc5dd847508b7d405ccd1520aaf | |
parent | 30b6688d9f77d40352cc3cec99052e0946a8affc (diff) | |
download | vSomeIP-ce34f857850ebf7bff1e4dc6c79574ff75abca56.tar.gz |
vSomeIP 2.5.12.5.1
136 files changed, 3950 insertions, 1177 deletions
@@ -12,6 +12,8 @@ /test/application_tests/application_test_no_dispatch_threads_daemon.json /test/big_payload_tests/big_payload_test_tcp_client.json /test/big_payload_tests/big_payload_test_tcp_service.json +/test/big_payload_tests/big_payload_test_tcp_client_random.json +/test/big_payload_tests/big_payload_test_tcp_service_random.json /test/magic_cookies_tests/magic_cookies_test_client.json /test/magic_cookies_tests/magic_cookies_test_service.json /test/payload_tests/external_local_payload_test_client_external.json @@ -242,3 +242,21 @@ v2.5.0 sending out the offers of the same service instance with a too high frequency. The default debounce time is set to 500ms. It can be changed via the new json file parameter service-discovery/offer_debounce_time. + +v2.5.1 +- Removed payload size limit. By default messages with an arbitrary length can + now be sent locally and via TCP. The payload-sizes configuration file array is + now used to limit the payload size for the specified endpoints instead of + increasing it. There are two new configuration file parameters: + - max-payload-size-local: limit maximum allowed payload size for node internal + communication. + - buffer-shrink-threshold: variable to control buffer memory deallocation + after big messages have been processed. For more information see the + vsomeipUserGuide. +- Fixed cleanup of endpoints for subscriptions using an exclusive proxy + (selective) which unnecessarily increased the number of open file descriptors. +- Fixed assignment of predefined application IDs via autoconfiguration. +- Decouple start of routing manager from network availability. +- Made number of internal threads per application configurable. +- Postpone notify_one events sent from subscription handler to ensure correct + message order on receiver side. diff --git a/CMakeLists.txt b/CMakeLists.txt index 1b0fd39..efdd3b4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,7 +8,7 @@ project (vsomeip) set (VSOMEIP_MAJOR_VERSION 2) set (VSOMEIP_MINOR_VERSION 5) -set (VSOMEIP_PATCH_VERSION 0) +set (VSOMEIP_PATCH_VERSION 1) 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/daemon/vsomeipd.cpp b/daemon/vsomeipd.cpp index 397abe9..d79b300 100644 --- a/daemon/vsomeipd.cpp +++ b/daemon/vsomeipd.cpp @@ -29,7 +29,7 @@ void vsomeipd_stop(int _signal) { if (_signal == SIGINT || _signal == SIGTERM) its_application->stop(); if (_signal == SIGABRT) { - VSOMEIP_DEBUG << "Suspending service discovery"; + VSOMEIP_INFO << "Suspending service discovery"; its_application->set_routing_state(vsomeip::routing_state_e::RS_SUSPENDED); its_application->stop(); } diff --git a/documentation/vsomeipUserGuide b/documentation/vsomeipUserGuide index 491a136..059992a 100644 --- a/documentation/vsomeipUserGuide +++ b/documentation/vsomeipUserGuide @@ -385,6 +385,11 @@ The maximum time that an application callback may consume before the callback is considered to be blocked (and an additional thread is used to execute pending callbacks if max_dispatchers is configured greater than 0). + +** 'threads' (optional) ++ +The number of internal threads to process messages and events within an application. +Valid values are 1-255. Default is 2. ++ * `services` (array) + Contains the services of the service provider. @@ -518,40 +523,62 @@ service instance. * `payload-sizes` (array) + -Array to specify the maximum allowed payload sizes per IP and port. If not -specified, or a smaller value than the default values is specified, the default -values are used. The settings in this array only affect communication over TCP -and local communication over UNIX domain sockets. +Array to limit the maximum allowed payload sizes per IP and port. If not +specified otherwise the allowed payload sizes are unlimited. The settings in +this array only affect communication over TCP. To limit the local payload size +`max-payload-size-local` can be used. ** `unicast` + -On client side: the IP of the remote service to which the oversized messages -should be sent. -On service side: the IP of the offered service which should receive the -oversized messages and is allowed to respond with oversized messages. -If client and service only communicate locally, any IP can be entered here as -for local communication only the maximum specified payload size is relevant. +On client side: the IP of the remote service for which the payload size should +be limited. ++ +On service side: the IP of the offered service for which the payload size for +receiving and sending should be limited. ** `ports` (array) + -Array which holds pairs of port and payload-size statements. +Array which holds pairs of port and payload size statements. *** `port` + -On client side: the port of the remote service to which the oversized messages -should be sent. -On service side: the port of the offered service which should receive the -oversized messages and is allowed to respond with oversized messages. -If client and service only communicate locally, any port number can be entered. +On client side: the port of the remote service for which the payload size should +be limited. ++ +On service side: the port of the offered service for which the payload size for +receiving and sending should be limited. *** `max-payload-size` + -On client side: the maximum payload size in bytes of a message sent to the +On client side: the payload size limit in bytes of a message sent to the remote service hosted on beforehand specified IP and port. -On service side: the maximum payload size in bytes of messages received by the -service offered on previously specified IP and port. If multiple services are -hosted on the same port all of them are allowed to receive oversized messages -and send oversized responses. ++ +On service side: the payload size limit in bytes of messages received and sent +by the service offered on previously specified IP and port. ++ +If multiple services are hosted on the same port all they share the limit +specified. + +* `max-payload-size-local` ++ +The maximum allowed payload size for node internal communication in bytes. By +default the payload size for node internal communication is unlimited. It can be +limited via this setting. + +* `buffer-shrink-threshold` ++ +The number of processed messages which are half the size or smaller than the +allocated buffer used to process them before the memory for the buffer is +released and starts to grow dynamically again. This setting can be useful in +scenarios where only a small number of the overall messages are a lot bigger +then the rest and the memory allocated to process them should be released in a +timely manner. If not specified via this setting the buffer sizes by default +aren't reseted and are as big as the biggest processed message. ++ +Example: `buffer-shrink-threshold` is set to 50. A message with 500 bytes has to +be processed and the buffers grow accordingly. After this message 50 consecutive +messages smaller than 250 bytes have to be processed before the buffer size is +reduced and starts to grow dynamically again. * `internal_services` (optional array) + diff --git a/examples/hello_world/hello_world_client.cpp b/examples/hello_world/hello_world_client.cpp index 8d5b33c..0854cc7 100644 --- a/examples/hello_world/hello_world_client.cpp +++ b/examples/hello_world/hello_world_client.cpp @@ -24,9 +24,12 @@ public: { } - void init(){ + bool init(){ // init the application - app_->init(); + if (!app_->init()) { + std::cerr << "Couldn't initialize application" << std::endl; + return false; + } // register a state handler to get called back after registration at the // runtime was successful @@ -45,6 +48,7 @@ public: std::bind(&hello_world_client::on_availability_cbk, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); + return true; } void start() @@ -118,6 +122,10 @@ public: // unregister the message handler app_->unregister_message_handler(vsomeip::ANY_SERVICE, service_instance_id, vsomeip::ANY_METHOD); + // alternatively unregister all registered handlers at once + app_->clear_all_handler(); + // release the service + app_->release_service(service_id, service_instance_id); // shutdown the application app_->stop(); } @@ -144,7 +152,10 @@ int main(int argc, char **argv) signal(SIGINT, handle_signal); signal(SIGTERM, handle_signal); #endif - hw_cl.init(); - hw_cl.start(); - return 0; + if (hw_cl.init()) { + hw_cl.start(); + return 0; + } else { + return 1; + } } diff --git a/examples/hello_world/hello_world_service.cpp b/examples/hello_world/hello_world_service.cpp index 7e6b615..0692b86 100644 --- a/examples/hello_world/hello_world_service.cpp +++ b/examples/hello_world/hello_world_service.cpp @@ -10,6 +10,7 @@ #include <thread> #include <condition_variable> #include <mutex> +#include <iostream> static vsomeip::service_t service_id = 0x1111; static vsomeip::instance_t service_instance_id = 0x2222; @@ -34,10 +35,13 @@ public: stop_thread_.join(); } - void init() + bool init() { // init the application - app_->init(); + if (!app_->init()) { + std::cerr << "Couldn't initialize application" << std::endl; + return false; + } // register a message handler callback for messages sent to our service app_->register_message_handler(service_id, service_instance_id, @@ -50,6 +54,7 @@ public: app_->register_state_handler( std::bind(&hello_world_service::on_state_cbk, this, std::placeholders::_1)); + return true; } void start() @@ -141,7 +146,10 @@ int main(int argc, char **argv) signal(SIGINT, handle_signal); signal(SIGTERM, handle_signal); #endif - hw_srv.init(); - hw_srv.start(); - return 0; + if (hw_srv.init()) { + hw_srv.start(); + return 0; + } else { + return 1; + } } diff --git a/examples/notify-sample.cpp b/examples/notify-sample.cpp index 172bf7d..bead4ba 100644 --- a/examples/notify-sample.cpp +++ b/examples/notify-sample.cpp @@ -30,10 +30,13 @@ public: notify_thread_(std::bind(&service_sample::notify, this)) { } - void init() { + bool init() { std::lock_guard<std::mutex> its_lock(mutex_); - app_->init(); + if (!app_->init()) { + std::cerr << "Couldn't initialize application" << std::endl; + return false; + } app_->register_state_handler( std::bind(&service_sample::on_state, this, std::placeholders::_1)); @@ -64,6 +67,7 @@ public: blocked_ = true; condition_.notify_one(); + return true; } void start() { @@ -79,6 +83,8 @@ public: blocked_ = true; condition_.notify_one(); notify_condition_.notify_one(); + app_->clear_all_handler(); + stop_offer(); offer_thread_.join(); notify_thread_.join(); app_->stop(); @@ -245,8 +251,10 @@ int main(int argc, char **argv) { signal(SIGINT, handle_signal); signal(SIGTERM, handle_signal); #endif - its_sample.init(); - its_sample.start(); - - return 0; + if (its_sample.init()) { + its_sample.start(); + return 0; + } else { + return 1; + } } diff --git a/examples/request-sample.cpp b/examples/request-sample.cpp index 93b8f0e..910c69e 100644 --- a/examples/request-sample.cpp +++ b/examples/request-sample.cpp @@ -30,8 +30,11 @@ public: sender_(std::bind(&client_sample::run, this)) { } - void init() { - app_->init(); + bool init() { + if (!app_->init()) { + std::cerr << "Couldn't initialize application" << std::endl; + return false; + } std::cout << "Client settings [protocol=" << (use_tcp_ ? "TCP" : "UDP") @@ -73,6 +76,7 @@ public: std::bind(&client_sample::on_availability, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); + return true; } void start() { @@ -86,6 +90,8 @@ public: void stop() { running_ = false; blocked_ = true; + app_->clear_all_handler(); + app_->release_service(SAMPLE_SERVICE_ID, SAMPLE_INSTANCE_ID); condition_.notify_one(); sender_.join(); app_->stop(); @@ -222,7 +228,10 @@ int main(int argc, char **argv) { signal(SIGINT, handle_signal); signal(SIGTERM, handle_signal); #endif - its_sample.init(); - its_sample.start(); - return 0; + if (its_sample.init()) { + its_sample.start(); + return 0; + } else { + return 1; + } } diff --git a/examples/response-sample.cpp b/examples/response-sample.cpp index 883d821..0d947c3 100644 --- a/examples/response-sample.cpp +++ b/examples/response-sample.cpp @@ -27,10 +27,13 @@ public: offer_thread_(std::bind(&service_sample::run, this)) { } - void init() { + bool init() { std::lock_guard<std::mutex> its_lock(mutex_); - app_->init(); + if (!app_->init()) { + std::cerr << "Couldn't initialize application" << std::endl; + return false; + } app_->register_state_handler( std::bind(&service_sample::on_state, this, std::placeholders::_1)); @@ -41,6 +44,7 @@ public: std::cout << "Static routing " << (use_static_routing_ ? "ON" : "OFF") << std::endl; + return true; } void start() { @@ -54,6 +58,8 @@ public: void stop() { running_ = false; blocked_ = true; + app_->clear_all_handler(); + stop_offer(); condition_.notify_one(); offer_thread_.join(); app_->stop(); @@ -172,8 +178,10 @@ int main(int argc, char **argv) { signal(SIGINT, handle_signal); signal(SIGTERM, handle_signal); #endif - its_sample.init(); - its_sample.start(); - - return 0; + if (its_sample.init()) { + its_sample.start(); + return 0; + } else { + return 1; + } } diff --git a/examples/subscribe-sample.cpp b/examples/subscribe-sample.cpp index 38b80c8..ab82df9 100644 --- a/examples/subscribe-sample.cpp +++ b/examples/subscribe-sample.cpp @@ -23,9 +23,11 @@ public: _use_tcp) { } - void init() { - app_->init(); - + bool init() { + if (!app_->init()) { + std::cerr << "Couldn't initialize application" << std::endl; + return false; + } std::cout << "Client settings [protocol=" << (use_tcp_ ? "TCP" : "UDP") << "]" @@ -53,6 +55,7 @@ public: SAMPLE_EVENT_ID, its_groups, true); + return true; } void start() { @@ -64,6 +67,10 @@ public: * Handle signal to shutdown */ void stop() { + app_->clear_all_handler(); + app_->unsubscribe(SAMPLE_SERVICE_ID, SAMPLE_INSTANCE_ID, SAMPLE_EVENTGROUP_ID); + app_->release_event(SAMPLE_SERVICE_ID, SAMPLE_INSTANCE_ID, SAMPLE_EVENT_ID); + app_->release_service(SAMPLE_SERVICE_ID, SAMPLE_INSTANCE_ID); app_->stop(); } #endif @@ -142,7 +149,6 @@ public: private: std::shared_ptr< vsomeip::application > app_; bool use_tcp_; - bool be_quiet_; }; #ifndef VSOMEIP_ENABLE_SIGNAL_HANDLING @@ -176,7 +182,10 @@ int main(int argc, char **argv) { signal(SIGINT, handle_signal); signal(SIGTERM, handle_signal); #endif - its_sample.init(); - its_sample.start(); - return 0; + if (its_sample.init()) { + its_sample.start(); + return 0; + } else { + return 1; + } } diff --git a/implementation/configuration/include/configuration.hpp b/implementation/configuration/include/configuration.hpp index 4a99ec3..75e7e55 100644 --- a/implementation/configuration/include/configuration.hpp +++ b/implementation/configuration/include/configuration.hpp @@ -57,8 +57,8 @@ public: virtual bool is_someip(service_t _service, instance_t _instance) const = 0; virtual bool get_client_port( - service_t _service, instance_t _instance, bool _reliable, - std::map<bool, std::set<uint16_t> > &_used, uint16_t &_port) const = 0; + service_t _service, instance_t _instance, bool _reliable, + std::map<bool, std::set<uint16_t> > &_used, uint16_t &_port) const = 0; virtual std::set<std::pair<service_t, instance_t> > get_remote_services() const = 0; @@ -73,10 +73,12 @@ 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::uint32_t get_max_message_size_local() const = 0; virtual std::uint32_t get_message_size_reliable(const std::string& _address, std::uint16_t _port) const = 0; + virtual std::uint32_t get_buffer_shrink_threshold() const = 0; virtual bool supports_selective_broadcasts(boost::asio::ip::address _address) const = 0; diff --git a/implementation/configuration/include/configuration_impl.hpp b/implementation/configuration/include/configuration_impl.hpp index 0dfc382..584a69a 100644 --- a/implementation/configuration/include/configuration_impl.hpp +++ b/implementation/configuration/include/configuration_impl.hpp @@ -70,7 +70,7 @@ public: VSOMEIP_EXPORT bool is_someip(service_t _service, instance_t _instance) const; VSOMEIP_EXPORT bool get_client_port(service_t _service, instance_t _instance, bool _reliable, - std::map<bool, std::set<uint16_t> > &_used, uint16_t &_port) const; + std::map<bool, std::set<uint16_t> > &_used, uint16_t &_port) const; VSOMEIP_EXPORT const std::string & get_routing_host() const; @@ -79,6 +79,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::set<std::pair<service_t, instance_t> > get_remote_services() const; @@ -91,6 +92,7 @@ public: VSOMEIP_EXPORT std::uint32_t get_max_message_size_local() const; VSOMEIP_EXPORT std::uint32_t get_message_size_reliable(const std::string& _address, std::uint16_t _port) const; + VSOMEIP_EXPORT std::uint32_t get_buffer_shrink_threshold() const; VSOMEIP_EXPORT bool supports_selective_broadcasts(boost::asio::ip::address _address) const; @@ -225,7 +227,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>> applications_; + std::map<std::string, std::tuple<client_t, std::size_t, std::size_t, size_t>> applications_; std::set<client_t> client_identifiers_; std::map<service_t, @@ -233,8 +235,8 @@ protected: std::shared_ptr<service> > > services_; std::map<service_t, - std::map<instance_t, - std::shared_ptr<client> > > clients_; + std::map<instance_t, + std::shared_ptr<client> > > clients_; std::string routing_host_; @@ -256,6 +258,8 @@ protected: std::map<std::string, std::map<std::uint16_t, std::uint32_t>> message_sizes_; std::uint32_t max_configured_message_size_; + std::uint32_t max_local_message_size_; + std::uint32_t buffer_shrink_threshold_; std::shared_ptr<trace> trace_; @@ -271,27 +275,27 @@ protected: enum element_type_e { ET_UNICAST, ET_DIAGNOSIS, - ET_LOGGING_CONSOLE, - ET_LOGGING_FILE, - ET_LOGGING_DLT, - ET_LOGGING_LEVEL, - ET_ROUTING, - ET_SERVICE_DISCOVERY_ENABLE, - ET_SERVICE_DISCOVERY_PROTOCOL, - ET_SERVICE_DISCOVERY_MULTICAST, - ET_SERVICE_DISCOVERY_PORT, - ET_SERVICE_DISCOVERY_INITIAL_DELAY_MIN, - ET_SERVICE_DISCOVERY_INITIAL_DELAY_MAX, - ET_SERVICE_DISCOVERY_REPETITION_BASE_DELAY, - ET_SERVICE_DISCOVERY_REPETITION_MAX, - ET_SERVICE_DISCOVERY_TTL, - ET_SERVICE_DISCOVERY_CYCLIC_OFFER_DELAY, - ET_SERVICE_DISCOVERY_REQUEST_RESPONSE_DELAY, - ET_WATCHDOG_ENABLE, - ET_WATCHDOG_TIMEOUT, - ET_WATCHDOG_ALLOWED_MISSING_PONGS, - ET_TRACING_ENABLE, - ET_TRACING_SD_ENABLE, + ET_LOGGING_CONSOLE, + ET_LOGGING_FILE, + ET_LOGGING_DLT, + ET_LOGGING_LEVEL, + ET_ROUTING, + ET_SERVICE_DISCOVERY_ENABLE, + ET_SERVICE_DISCOVERY_PROTOCOL, + ET_SERVICE_DISCOVERY_MULTICAST, + ET_SERVICE_DISCOVERY_PORT, + ET_SERVICE_DISCOVERY_INITIAL_DELAY_MIN, + ET_SERVICE_DISCOVERY_INITIAL_DELAY_MAX, + ET_SERVICE_DISCOVERY_REPETITION_BASE_DELAY, + ET_SERVICE_DISCOVERY_REPETITION_MAX, + ET_SERVICE_DISCOVERY_TTL, + ET_SERVICE_DISCOVERY_CYCLIC_OFFER_DELAY, + ET_SERVICE_DISCOVERY_REQUEST_RESPONSE_DELAY, + ET_WATCHDOG_ENABLE, + ET_WATCHDOG_TIMEOUT, + ET_WATCHDOG_ALLOWED_MISSING_PONGS, + ET_TRACING_ENABLE, + ET_TRACING_SD_ENABLE, ET_SERVICE_DISCOVERY_OFFER_DEBOUNCE_TIME, ET_MAX = 24 }; diff --git a/implementation/configuration/include/internal.hpp.in b/implementation/configuration/include/internal.hpp.in index 766a3f6..ca5a76c 100644 --- a/implementation/configuration/include/internal.hpp.in +++ b/implementation/configuration/include/internal.hpp.in @@ -7,6 +7,7 @@ #define VSOMEIP_INTERNAL_HPP #include <cstdint> +#include <limits> #define VSOMEIP_ENV_APPLICATION_NAME "VSOMEIP_APPLICATION_NAME" #define VSOMEIP_ENV_CONFIGURATION "VSOMEIP_CONFIGURATION" @@ -48,6 +49,8 @@ #define VSOMEIP_DEFAULT_WATCHDOG_TIMEOUT 5000 #define VSOMEIP_DEFAULT_MAX_MISSING_PONGS 3 +#define VSOMEIP_IO_THREAD_COUNT 2 + #define VSOMEIP_MAX_DISPATCHERS 10 #define VSOMEIP_MAX_DISPATCH_TIME 100 @@ -127,6 +130,14 @@ struct configuration_data_t { unsigned short routing_manager_host_; }; +#ifndef WIN32 +constexpr std::uint32_t MESSAGE_SIZE_UNLIMITED = std::numeric_limits<std::uint32_t>::max(); +#elif _MSC_VER >= 1900 +constexpr std::uint32_t MESSAGE_SIZE_UNLIMITED = (std::numeric_limits<std::uint32_t>::max)(); +#else +const std::uint32_t MESSAGE_SIZE_UNLIMITED = (std::numeric_limits<std::uint32_t>::max)(); +#endif + } // namespace vsomeip #endif // VSOMEIP_INTERNAL_HPP diff --git a/implementation/configuration/src/configuration_impl.cpp b/implementation/configuration/src/configuration_impl.cpp index c4fefb9..3c8d90b 100644 --- a/implementation/configuration/src/configuration_impl.cpp +++ b/implementation/configuration/src/configuration_impl.cpp @@ -8,6 +8,7 @@ #include <functional> #include <set> #include <sstream> +#include <limits> #define WIN32_LEAN_AND_MEAN @@ -58,6 +59,8 @@ configuration_impl::configuration_impl() sd_request_response_delay_(VSOMEIP_SD_DEFAULT_REQUEST_RESPONSE_DELAY), sd_offer_debounce_time_(VSOMEIP_SD_DEFAULT_OFFER_DEBOUNCE_TIME), max_configured_message_size_(0), + max_local_message_size_(0), + buffer_shrink_threshold_(0), trace_(std::make_shared<trace>()), watchdog_(std::make_shared<watchdog>()), log_version_(true), @@ -76,7 +79,9 @@ configuration_impl::configuration_impl(const configuration_impl &_other) is_loaded_(_other.is_loaded_), is_logging_loaded_(_other.is_logging_loaded_), mandatory_(_other.mandatory_), - max_configured_message_size_(0), + max_configured_message_size_(_other.max_configured_message_size_), + max_local_message_size_(_other.max_local_message_size_), + buffer_shrink_threshold_(_other.buffer_shrink_threshold_), permissions_shm_(VSOMEIP_DEFAULT_SHM_PERMISSION), umask_(VSOMEIP_DEFAULT_UMASK_LOCAL_ENDPOINTS) { @@ -209,7 +214,7 @@ bool configuration_impl::load(const std::string &_name) { set_magic_cookies_unicast_address(); std::chrono::steady_clock::time_point end = std::chrono::steady_clock::now(); - VSOMEIP_DEBUG << "Parsed vsomeip configuration in " + VSOMEIP_INFO << "Parsed vsomeip configuration in " << std::chrono::duration_cast<std::chrono::milliseconds>(end - begin).count() << "ms"; @@ -435,6 +440,7 @@ void configuration_impl::load_application_data( client_t its_id(0); std::size_t its_max_dispatchers(VSOMEIP_MAX_DISPATCHERS); std::size_t its_max_dispatch_time(VSOMEIP_MAX_DISPATCH_TIME); + std::size_t its_io_thread_count(VSOMEIP_IO_THREAD_COUNT); for (auto i = _tree.begin(); i != _tree.end(); ++i) { std::string its_key(i->first); std::string its_value(i->second.data()); @@ -454,13 +460,24 @@ void configuration_impl::load_application_data( } else if (its_key == "max_dispatch_time") { its_converter << std::dec << its_value; its_converter >> its_max_dispatch_time; + } else if (its_key == "threads") { + its_converter << std::dec << its_value; + its_converter >> its_io_thread_count; + if (its_io_thread_count == 0) { + VSOMEIP_WARNING << "Min. number of threads per application is 1"; + its_io_thread_count = 1; + } else if (its_io_thread_count > 255) { + VSOMEIP_WARNING << "Max. number of threads per application is 255"; + its_io_thread_count = 255; + } } } - if (its_name != "" && its_id != 0) { + if (its_name != "") { if (applications_.find(its_name) == applications_.end()) { if (!is_configured_client_id(its_id)) { applications_[its_name] - = std::make_tuple(its_id, its_max_dispatchers, its_max_dispatch_time); + = std::make_tuple(its_id, its_max_dispatchers, + its_max_dispatch_time, its_io_thread_count); client_identifiers_.insert(its_id); } else { VSOMEIP_WARNING << "Multiple configurations for application " @@ -1258,7 +1275,32 @@ void configuration_impl::load_watchdog(const element &_element) { void configuration_impl::load_payload_sizes(const element &_element) { const std::string payload_sizes("payload-sizes"); + const std::string max_local_payload_size("max-payload-size-local"); + const std::string buffer_shrink_threshold("buffer-shrink-threshold"); try { + if (_element.tree_.get_child_optional(max_local_payload_size)) { + auto mpsl = _element.tree_.get_child(max_local_payload_size); + std::string s(mpsl.data()); + try { + // add 16 Byte for the SOME/IP header + max_local_message_size_ = static_cast<std::uint32_t>(std::stoul( + s.c_str(), NULL, 10) + 16); + } catch (const std::exception &e) { + VSOMEIP_ERROR<< __func__ << ": " << max_local_payload_size + << " " << e.what(); + } + } + if (_element.tree_.get_child_optional(buffer_shrink_threshold)) { + auto bst = _element.tree_.get_child(buffer_shrink_threshold); + std::string s(bst.data()); + try { + buffer_shrink_threshold_ = static_cast<std::uint32_t>( + std::stoul(s.c_str(), NULL, 10)); + } catch (const std::exception &e) { + VSOMEIP_ERROR<< __func__ << ": " << buffer_shrink_threshold + << " " << e.what(); + } + } if (_element.tree_.get_child_optional(payload_sizes)) { const std::string unicast("unicast"); const std::string ports("ports"); @@ -1298,13 +1340,23 @@ void configuration_impl::load_payload_sizes(const element &_element) { if (its_port == ILLEGAL_PORT || its_message_size == 0) { continue; } - if(max_configured_message_size_ < its_message_size) { + if (max_configured_message_size_ < its_message_size) { max_configured_message_size_ = its_message_size; } message_sizes_[its_unicast][its_port] = its_message_size; } } + if (max_local_message_size_ != 0 + && max_configured_message_size_ != 0 + && max_configured_message_size_ > max_local_message_size_) { + VSOMEIP_WARNING << max_local_payload_size + << " is configured smaller than the biggest payloadsize" + << " for external communication. " + << max_local_payload_size << " will be increased to " + << max_configured_message_size_ - 16 << " to ensure " + << "local message distribution."; + } } } catch (...) { } @@ -1741,6 +1793,17 @@ 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_io_thread_count(const std::string &_name) const { + std::size_t its_io_thread_count = VSOMEIP_IO_THREAD_COUNT; + + auto found_application = applications_.find(_name); + if (found_application != applications_.end()) { + its_io_thread_count = std::get<3>(found_application->second); + } + + return its_io_thread_count; +} + std::size_t configuration_impl::get_max_dispatchers( const std::string &_name) const { std::size_t its_max_dispatchers = VSOMEIP_MAX_DISPATCHERS; @@ -1906,14 +1969,22 @@ std::shared_ptr<eventgroup> configuration_impl::find_eventgroup( } std::uint32_t configuration_impl::get_max_message_size_local() const { - uint32_t its_max_message_size = VSOMEIP_MAX_LOCAL_MESSAGE_SIZE; - if (VSOMEIP_MAX_TCP_MESSAGE_SIZE > its_max_message_size) { + if (max_local_message_size_ == 0 + && (VSOMEIP_MAX_LOCAL_MESSAGE_SIZE == 0 + || VSOMEIP_MAX_TCP_MESSAGE_SIZE == 0)) { + // no limit specified in configuration file and + // defines are set to unlimited + return MESSAGE_SIZE_UNLIMITED; + } + + uint32_t its_max_message_size = max_local_message_size_; + if (VSOMEIP_MAX_TCP_MESSAGE_SIZE >= its_max_message_size) { its_max_message_size = VSOMEIP_MAX_TCP_MESSAGE_SIZE; } if (VSOMEIP_MAX_UDP_MESSAGE_SIZE > its_max_message_size) { its_max_message_size = VSOMEIP_MAX_UDP_MESSAGE_SIZE; } - if(its_max_message_size < max_configured_message_size_) { + if (its_max_message_size < max_configured_message_size_) { its_max_message_size = max_configured_message_size_; } @@ -1933,7 +2004,13 @@ std::uint32_t configuration_impl::get_message_size_reliable( return its_port->second; } } - return VSOMEIP_MAX_TCP_MESSAGE_SIZE; + return (VSOMEIP_MAX_TCP_MESSAGE_SIZE == 0) ? + MESSAGE_SIZE_UNLIMITED : + VSOMEIP_MAX_TCP_MESSAGE_SIZE; +} + +std::uint32_t configuration_impl::get_buffer_shrink_threshold() const { + return buffer_shrink_threshold_; } bool configuration_impl::supports_selective_broadcasts(boost::asio::ip::address _address) const { diff --git a/implementation/endpoints/include/buffer.hpp b/implementation/endpoints/include/buffer.hpp index 1dac89a..e9bb811 100644 --- a/implementation/endpoints/include/buffer.hpp +++ b/implementation/endpoints/include/buffer.hpp @@ -14,8 +14,6 @@ namespace vsomeip { -typedef std::vector<byte_t> receive_buffer_t; - typedef std::vector<byte_t> message_buffer_t; typedef std::shared_ptr<message_buffer_t> message_buffer_ptr_t; diff --git a/implementation/endpoints/include/client_endpoint.hpp b/implementation/endpoints/include/client_endpoint.hpp new file mode 100644 index 0000000..cbf9063 --- /dev/null +++ b/implementation/endpoints/include/client_endpoint.hpp @@ -0,0 +1,24 @@ +// Copyright (C) 2014-2016 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef VSOMEIP_CLIENT_ENDPOINT_HPP_ +#define VSOMEIP_CLIENT_ENDPOINT_HPP_ + +#include "endpoint.hpp" + +namespace vsomeip { + +class client_endpoint : public virtual endpoint { +public: + virtual ~client_endpoint() {} + + virtual bool get_remote_address(boost::asio::ip::address &_address) const = 0; + virtual unsigned short get_remote_port() const = 0; +}; + +} // namespace vsomeip + + +#endif /* VSOMEIP_CLIENT_ENDPOINT_HPP_ */ diff --git a/implementation/endpoints/include/client_endpoint_impl.hpp b/implementation/endpoints/include/client_endpoint_impl.hpp index 9a889f3..32f0c20 100644 --- a/implementation/endpoints/include/client_endpoint_impl.hpp +++ b/implementation/endpoints/include/client_endpoint_impl.hpp @@ -19,6 +19,7 @@ #include "buffer.hpp"
#include "endpoint_impl.hpp"
+#include "client_endpoint.hpp"
namespace vsomeip {
@@ -26,15 +27,15 @@ class endpoint; class endpoint_host;
template<typename Protocol>
-class client_endpoint_impl: public endpoint_impl<Protocol>,
+class client_endpoint_impl: public endpoint_impl<Protocol>, public client_endpoint,
public std::enable_shared_from_this<client_endpoint_impl<Protocol> > {
public:
- typedef typename Protocol::endpoint endpoint_type;
+ typedef typename Protocol::endpoint endpoint_type;
typedef typename Protocol::socket socket_type;
client_endpoint_impl(std::shared_ptr<endpoint_host> _host,
- endpoint_type _local, endpoint_type _remote,
- boost::asio::io_service &_io,
+ endpoint_type _local, endpoint_type _remote,
+ boost::asio::io_service &_io,
std::uint32_t _max_message_size);
virtual ~client_endpoint_impl();
@@ -50,6 +51,9 @@ public: bool is_connected() const;
+ virtual bool get_remote_address(boost::asio::ip::address &_address) const;
+ virtual unsigned short get_remote_port() const;
+
public:
void connect_cbk(boost::system::error_code const &_error);
void wait_connect_cbk(boost::system::error_code const &_error);
@@ -59,8 +63,6 @@ public: public:
virtual void connect() = 0;
virtual void receive() = 0;
- typedef std::function<void()> endpoint_error_handler_t;
- void register_error_callback(endpoint_error_handler_t _callback);
protected:
virtual void send_queued() = 0;
@@ -82,9 +84,6 @@ protected: bool was_not_connected_;
- std::mutex error_handler_mutex_;
- endpoint_error_handler_t error_handler_;
-
std::mutex stop_mutex_;
};
diff --git a/implementation/endpoints/include/endpoint.hpp b/implementation/endpoints/include/endpoint.hpp index c063f2a..c09ab92 100644 --- a/implementation/endpoints/include/endpoint.hpp +++ b/implementation/endpoints/include/endpoint.hpp @@ -37,9 +37,7 @@ public: const std::string &_address, uint16_t _port) = 0;
virtual void remove_default_target(service_t _service) = 0;
- virtual bool get_remote_address(boost::asio::ip::address &_address) const = 0;
virtual unsigned short get_local_port() const = 0;
- virtual unsigned short get_remote_port() const = 0;
virtual bool is_reliable() const = 0;
virtual bool is_local() const = 0;
diff --git a/implementation/endpoints/include/endpoint_host.hpp b/implementation/endpoints/include/endpoint_host.hpp index 8834158..25218d4 100644 --- a/implementation/endpoints/include/endpoint_host.hpp +++ b/implementation/endpoints/include/endpoint_host.hpp @@ -28,9 +28,13 @@ public: virtual void on_message(const byte_t *_data, length_t _length, endpoint *_receiver, const boost::asio::ip::address &_destination = boost::asio::ip::address(), - client_t _bound_client = VSOMEIP_ROUTING_CLIENT) = 0; + client_t _bound_client = VSOMEIP_ROUTING_CLIENT, + const boost::asio::ip::address &_remote_address = boost::asio::ip::address(), + std::uint16_t _remote_port = 0) = 0; virtual void on_error(const byte_t *_data, length_t _length, - endpoint *_receiver) = 0; + endpoint *_receiver, + const boost::asio::ip::address &_remote_address, + std::uint16_t _remote_port) = 0; virtual void release_port(uint16_t _port, bool _reliable) = 0; virtual client_t get_client() const = 0; #ifndef WIN32 diff --git a/implementation/endpoints/include/endpoint_impl.hpp b/implementation/endpoints/include/endpoint_impl.hpp index b000011..341325b 100644 --- a/implementation/endpoints/include/endpoint_impl.hpp +++ b/implementation/endpoints/include/endpoint_impl.hpp @@ -20,7 +20,7 @@ namespace vsomeip { class endpoint_host;
template<typename Protocol>
-class endpoint_impl: public endpoint {
+class endpoint_impl: public virtual endpoint {
public:
typedef typename Protocol::endpoint endpoint_type;
@@ -40,12 +40,9 @@ public: void add_default_target(service_t, const std::string &, uint16_t);
void remove_default_target(service_t);
- bool get_remote_address(boost::asio::ip::address &_address) const;
-
// Dummy implementations as we only need these for server endpoints
// TODO: redesign
unsigned short get_local_port() const;
- unsigned short get_remote_port() const;
bool is_reliable() const;
void increment_use_count();
@@ -59,7 +56,6 @@ public: virtual void restart() = 0;
protected:
- virtual bool is_magic_cookie() const;
uint32_t find_magic_cookie(byte_t *_buffer, size_t _size);
protected:
diff --git a/implementation/endpoints/include/local_client_endpoint_impl.hpp b/implementation/endpoints/include/local_client_endpoint_impl.hpp index 79a0420..8f9b224 100644 --- a/implementation/endpoints/include/local_client_endpoint_impl.hpp +++ b/implementation/endpoints/include/local_client_endpoint_impl.hpp @@ -31,6 +31,8 @@ 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, @@ -42,6 +44,11 @@ public: bool is_local() const; + 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); + private: void send_queued(); @@ -52,7 +59,9 @@ private: void receive_cbk(boost::system::error_code const &_error, std::size_t _bytes); - receive_buffer_t recv_buffer_; + message_buffer_t recv_buffer_; + + error_handler_t error_handler_; }; } // namespace vsomeip diff --git a/implementation/endpoints/include/local_server_endpoint_impl.hpp b/implementation/endpoints/include/local_server_endpoint_impl.hpp index 66c1fc2..a66a410 100644 --- a/implementation/endpoints/include/local_server_endpoint_impl.hpp +++ b/implementation/endpoints/include/local_server_endpoint_impl.hpp @@ -41,13 +41,15 @@ public: local_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 _max_message_size, + std::uint32_t _buffer_shrink_threshold); local_server_endpoint_impl(std::shared_ptr<endpoint_host> _host, endpoint_type _local, boost::asio::io_service &_io, std::uint32_t _max_message_size, - int native_socket); + int native_socket, + std::uint32_t _buffer_shrink_threshold); virtual ~local_server_endpoint_impl(); @@ -74,7 +76,7 @@ private: typedef boost::shared_ptr<connection> ptr; static ptr create(std::weak_ptr<local_server_endpoint_impl> _server, - std::uint32_t _max_message_size); + std::uint32_t _buffer_shrink_threshold); socket_type & get_socket(); void start(); @@ -86,23 +88,28 @@ private: private: connection(std::weak_ptr<local_server_endpoint_impl> _server, - std::uint32_t _max_message_size); + std::uint32_t _recv_buffer_size_initial, + std::uint32_t _buffer_shrink_threshold); void send_magic_cookie(); local_server_endpoint_impl::socket_type socket_; std::weak_ptr<local_server_endpoint_impl> server_; - uint32_t max_message_size_; + const uint32_t recv_buffer_size_initial_; - receive_buffer_t recv_buffer_; + message_buffer_t recv_buffer_; size_t recv_buffer_size_; + std::uint32_t missing_capacity_; + std::uint32_t shrink_count_; + const std::uint32_t buffer_shrink_threshold_; client_t bound_client_; private: void receive_cbk(boost::system::error_code const &_error, std::size_t _bytes); + void calculate_shrink_count(); }; #ifdef WIN32 @@ -114,6 +121,7 @@ private: std::mutex connections_mutex_; std::map<endpoint_type, connection::ptr> connections_; connection::ptr current_; + const std::uint32_t buffer_shrink_threshold_; private: void remove_connection(connection *_connection); diff --git a/implementation/endpoints/include/netlink_connector.hpp b/implementation/endpoints/include/netlink_connector.hpp new file mode 100644 index 0000000..c47e0f4 --- /dev/null +++ b/implementation/endpoints/include/netlink_connector.hpp @@ -0,0 +1,220 @@ +// Copyright (C) 2014-2016 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef NETLINK_CONNECTOR_HPP_ +#define NETLINK_CONNECTOR_HPP_ + +#ifndef WIN32 + +#include <sys/socket.h> +#include <linux/netlink.h> +#include <linux/rtnetlink.h> + +#include <map> + +#include <boost/asio/ip/address.hpp> +#include <boost/asio/basic_raw_socket.hpp> + +#include "../../endpoints/include/buffer.hpp" + +namespace vsomeip { + +template <typename Protocol> +class nl_endpoint { +public: + /// The protocol type associated with the endpoint. + typedef Protocol protocol_type; + typedef boost::asio::detail::socket_addr_type data_type; + + /// Default constructor. + nl_endpoint() + { + sockaddr.nl_family = PF_NETLINK; + sockaddr.nl_groups = 0; + sockaddr.nl_pid = getpid(); + } + + /// Construct an endpoint using the specified path name. + nl_endpoint(int group, int pid=getpid()) + { + sockaddr.nl_family = PF_NETLINK; + sockaddr.nl_groups = group; + sockaddr.nl_pid = pid; + } + + /// Copy constructor. + nl_endpoint(const nl_endpoint& other) + { + sockaddr = other.sockaddr; + } + + /// Assign from another endpoint. + nl_endpoint& operator=(const nl_endpoint& other) + { + sockaddr = other.sockaddr; + return *this; + } + + /// The protocol associated with the endpoint. + protocol_type protocol() const + { + return protocol_type(); + } + + /// Get the underlying endpoint in the native type. + data_type* data() + { + return &sockaddr; + } + + /// Get the underlying endpoint in the native type. + const data_type* data() const + { + return (struct sockaddr*)&sockaddr; + } + + /// Get the underlying size of the endpoint in the native type. + std::size_t size() const + { + return sizeof(sockaddr); + } + + /// Set the underlying size of the endpoint in the native type. + void resize(std::size_t size) + { + /* nothing we can do here */ + } + + /// Get the capacity of the endpoint in the native type. + std::size_t capacity() const + { + return sizeof(sockaddr); + } + + /// Compare two endpoints for equality. + friend bool operator==(const nl_endpoint<Protocol>& e1, + const nl_endpoint<Protocol>& e2) + { + return e1.sockaddr == e2.sockaddr; + } + + /// Compare two endpoints for inequality. + friend bool operator!=(const nl_endpoint<Protocol>& e1, + const nl_endpoint<Protocol>& e2) + { + return !(e1.sockaddr == e2.sockaddr); + } + + /// Compare endpoints for ordering. + friend bool operator<(const nl_endpoint<Protocol>& e1, + const nl_endpoint<Protocol>& e2) + { + return e1.sockaddr < e2.sockaddr; + } + + /// Compare endpoints for ordering. + friend bool operator>(const nl_endpoint<Protocol>& e1, + const nl_endpoint<Protocol>& e2) + { + return e2.sockaddr < e1.sockaddr; + } + + /// Compare endpoints for ordering. + friend bool operator<=(const nl_endpoint<Protocol>& e1, + const nl_endpoint<Protocol>& e2) + { + return !(e2 < e1); + } + + /// Compare endpoints for ordering. + friend bool operator>=(const nl_endpoint<Protocol>& e1, + const nl_endpoint<Protocol>& e2) + { + return !(e1 < e2); + } + +private: + sockaddr_nl sockaddr; +}; + +class nl_protocol { +public: + nl_protocol() { + proto = 0; + } + nl_protocol(int proto) { + this->proto = proto; + } + /// Obtain an identifier for the type of the protocol. + int type() const + { + return SOCK_RAW; + } + /// Obtain an identifier for the protocol. + int protocol() const + { + return proto; + } + /// Obtain an identifier for the protocol family. + int family() const + { + return PF_NETLINK; + } + + typedef nl_endpoint<nl_protocol> endpoint; + typedef boost::asio::basic_raw_socket<nl_protocol> socket; + +private: + int proto; +}; + +typedef std::function< void (std::string, bool) > net_if_changed_handler_t; + +class netlink_connector : public std::enable_shared_from_this<netlink_connector> { +public: + netlink_connector(boost::asio::io_service& _io, boost::asio::ip::address _address): + net_if_index_for_address_(0), + handler_(nullptr), + socket_(_io), + recv_buffer_(recv_buffer_size, 0), + address_(_address) + { + } + ~netlink_connector() {} + + void register_net_if_changes_handler(net_if_changed_handler_t _handler); + void unregister_net_if_changes_handler(); + + void start(); + void stop(); + +private: + bool has_address(const struct ifaddrmsg * ifa_struct, + size_t length, + const unsigned int address); + void send_ifa_request(); + void send_ifi_request(); + + void receive_cbk(boost::system::error_code const &_error, std::size_t _bytes); + void send_cbk(boost::system::error_code const &_error, std::size_t _bytes); + + std::map<int, unsigned int> net_if_flags_; + int net_if_index_for_address_; + + net_if_changed_handler_t handler_; + + boost::asio::basic_raw_socket<nl_protocol> socket_; + + const size_t recv_buffer_size = 16384; + message_buffer_t recv_buffer_; + + boost::asio::ip::address address_; +}; + +} + +#endif // NOT WIN32 + +#endif /* NETLINK_CONNECTOR_HPP_ */ diff --git a/implementation/endpoints/include/tcp_client_endpoint_impl.hpp b/implementation/endpoints/include/tcp_client_endpoint_impl.hpp index e6aaa33..9f5d19d 100644 --- a/implementation/endpoints/include/tcp_client_endpoint_impl.hpp +++ b/implementation/endpoints/include/tcp_client_endpoint_impl.hpp @@ -21,9 +21,10 @@ class tcp_client_endpoint_impl: public tcp_client_endpoint_base_impl { public:
tcp_client_endpoint_impl(std::shared_ptr<endpoint_host> _host,
endpoint_type _local,
- endpoint_type _remote,
+ endpoint_type _remote,
boost::asio::io_service &_io,
- std::uint32_t _max_message_size);
+ std::uint32_t _max_message_size,
+ std::uint32_t buffer_shrink_threshold);
virtual ~tcp_client_endpoint_impl();
void start();
@@ -44,9 +45,14 @@ private: void connect();
void receive();
+ void calculate_shrink_count();
- receive_buffer_t recv_buffer_;
+ const std::uint32_t recv_buffer_size_initial_;
+ message_buffer_t recv_buffer_;
size_t recv_buffer_size_;
+ std::uint32_t missing_capacity_;
+ std::uint32_t shrink_count_;
+ const std::uint32_t buffer_shrink_threshold_;
};
} // namespace vsomeip
diff --git a/implementation/endpoints/include/tcp_server_endpoint_impl.hpp b/implementation/endpoints/include/tcp_server_endpoint_impl.hpp index e976644..8ded105 100644 --- a/implementation/endpoints/include/tcp_server_endpoint_impl.hpp +++ b/implementation/endpoints/include/tcp_server_endpoint_impl.hpp @@ -27,7 +27,8 @@ public: 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 _max_message_size,
+ std::uint32_t _buffer_shrink_threshold);
virtual ~tcp_server_endpoint_impl();
void start();
@@ -39,8 +40,6 @@ public: VSOMEIP_EXPORT bool is_established(std::shared_ptr<endpoint_definition> _endpoint);
- bool get_remote_address(boost::asio::ip::address &_address) const;
- unsigned short get_remote_port() const;
bool get_default_target(service_t, endpoint_type &) const;
unsigned short get_local_port() const;
@@ -61,7 +60,8 @@ private: typedef boost::shared_ptr<connection> ptr;
static ptr create(std::weak_ptr<tcp_server_endpoint_impl> _server,
- std::uint32_t _max_message_size);
+ std::uint32_t _max_message_size,
+ std::uint32_t _buffer_shrink_threshold);
socket_type & get_socket();
void start();
@@ -74,28 +74,35 @@ private: private:
connection(std::weak_ptr<tcp_server_endpoint_impl> _server,
- std::uint32_t _max_message_size);
+ std::uint32_t _max_message_size,
+ std::uint32_t _recv_buffer_size_initial,
+ std::uint32_t _buffer_shrink_threshold);
void send_magic_cookie(message_buffer_ptr_t &_buffer);
tcp_server_endpoint_impl::socket_type socket_;
std::weak_ptr<tcp_server_endpoint_impl> server_;
- uint32_t max_message_size_;
+ const uint32_t max_message_size_;
+ const uint32_t recv_buffer_size_initial_;
- receive_buffer_t recv_buffer_;
+ message_buffer_t recv_buffer_;
size_t recv_buffer_size_;
+ std::uint32_t missing_capacity_;
+ std::uint32_t shrink_count_;
+ const std::uint32_t buffer_shrink_threshold_;
private:
bool is_magic_cookie(size_t _offset) const;
void receive_cbk(boost::system::error_code const &_error,
std::size_t _bytes);
+ void calculate_shrink_count();
std::mutex stop_mutex_;
};
boost::asio::ip::tcp::acceptor acceptor_;
std::mutex connections_mutex_;
std::map<endpoint_type, connection::ptr> connections_;
- connection *current_;
+ const std::uint32_t buffer_shrink_threshold_;
private:
void remove_connection(connection *_connection);
diff --git a/implementation/endpoints/include/udp_client_endpoint_impl.hpp b/implementation/endpoints/include/udp_client_endpoint_impl.hpp index 07d2179..cd3bb25 100644 --- a/implementation/endpoints/include/udp_client_endpoint_impl.hpp +++ b/implementation/endpoints/include/udp_client_endpoint_impl.hpp @@ -47,7 +47,7 @@ private: void connect();
void receive();
- receive_buffer_t recv_buffer_;
+ message_buffer_t recv_buffer_;
};
} // namespace vsomeip
diff --git a/implementation/endpoints/include/udp_server_endpoint_impl.hpp b/implementation/endpoints/include/udp_server_endpoint_impl.hpp index 0f2f830..cdadb0a 100644 --- a/implementation/endpoints/include/udp_server_endpoint_impl.hpp +++ b/implementation/endpoints/include/udp_server_endpoint_impl.hpp @@ -37,9 +37,6 @@ public: const byte_t *_data, uint32_t _size, bool _flush);
void send_queued(queue_iterator_type _queue_iterator);
- bool get_remote_address(boost::asio::ip::address &_address) const;
- unsigned short get_remote_port() const;
-
void join(const std::string &_address);
void leave(const std::string &_address);
@@ -69,7 +66,7 @@ private: std::map<service_t, endpoint_type> default_targets_;
std::set<std::string> joined_;
- receive_buffer_t recv_buffer_;
+ message_buffer_t recv_buffer_;
std::mutex stop_mutex_;
};
diff --git a/implementation/endpoints/src/client_endpoint_impl.cpp b/implementation/endpoints/src/client_endpoint_impl.cpp index 9a33aad..5027aa7 100644 --- a/implementation/endpoints/src/client_endpoint_impl.cpp +++ b/implementation/endpoints/src/client_endpoint_impl.cpp @@ -7,6 +7,7 @@ #include <iomanip>
#include <sstream>
#include <thread>
+#include <limits>
#include <boost/asio/buffer.hpp>
#include <boost/asio/ip/tcp.hpp>
@@ -124,9 +125,17 @@ bool client_endpoint_impl<Protocol>::send(const uint8_t *_data, for (uint32_t i = 0; i < _size; i++)
msg << std::hex << std::setw(2) << std::setfill('0')
<< (int)_data[i] << " ";
- VSOMEIP_DEBUG << msg.str();
+ VSOMEIP_INFO << msg.str();
#endif
+ if (endpoint_impl<Protocol>::max_message_size_ != MESSAGE_SIZE_UNLIMITED
+ && _size > endpoint_impl<Protocol>::max_message_size_) {
+ VSOMEIP_ERROR << "cei::send: Dropping to big message (" << std::dec
+ << _size << " Bytes). Maximum allowed message size is: "
+ << endpoint_impl<Protocol>::max_message_size_ << " Bytes.";
+ return false;
+ }
+
const bool queue_size_zero_on_entry(queue_.empty());
if (packetizer_->size() + _size > endpoint_impl<Protocol>::max_message_size_
&& !packetizer_->empty()) {
@@ -199,7 +208,7 @@ void client_endpoint_impl<Protocol>::connect_cbk( // Double the timeout as long as the maximum allowed is larger
if (connect_timeout_ < VSOMEIP_MAX_CONNECT_TIMEOUT)
- connect_timeout_ <<= 1;
+ connect_timeout_ <<= 1;
if (is_connected_) {
is_connected_ = false;
@@ -245,15 +254,11 @@ void client_endpoint_impl<Protocol>::send_cbk( }
} else if (_error == boost::asio::error::broken_pipe) {
is_connected_ = false;
- if (endpoint_impl<Protocol>::sending_blocked_ || error_handler_) {
+ if (endpoint_impl<Protocol>::sending_blocked_) {
{
std::lock_guard<std::mutex> its_lock(mutex_);
queue_.clear();
}
- if (error_handler_) {
- std::lock_guard<std::mutex> its_lock(error_handler_mutex_);
- error_handler_();
- }
}
if (socket_.is_open()) {
shutdown_and_close_socket();
@@ -278,13 +283,6 @@ void client_endpoint_impl<Protocol>::flush_cbk( }
template<typename Protocol>
-void client_endpoint_impl<Protocol>::register_error_callback(
- endpoint_error_handler_t _callback) {
- std::lock_guard<std::mutex> its_lock(error_handler_mutex_);
- error_handler_ = _callback;
-}
-
-template<typename Protocol>
void client_endpoint_impl<Protocol>::shutdown_and_close_socket() {
std::lock_guard<std::mutex> its_lock(stop_mutex_);
if (socket_.is_open()) {
@@ -294,6 +292,18 @@ void client_endpoint_impl<Protocol>::shutdown_and_close_socket() { }
}
+template<typename Protocol>
+bool client_endpoint_impl<Protocol>::get_remote_address(
+ boost::asio::ip::address &_address) const {
+ (void)_address;
+ return false;
+}
+
+template<typename Protocol>
+unsigned short client_endpoint_impl<Protocol>::get_remote_port() const {
+ return 0;
+}
+
// Instantiate template
#ifndef WIN32
template class client_endpoint_impl<boost::asio::local::stream_protocol>;
diff --git a/implementation/endpoints/src/endpoint_impl.cpp b/implementation/endpoints/src/endpoint_impl.cpp index 109cff8..7238d83 100644 --- a/implementation/endpoints/src/endpoint_impl.cpp +++ b/implementation/endpoints/src/endpoint_impl.cpp @@ -20,9 +20,9 @@ namespace vsomeip { template<typename Protocol>
endpoint_impl<Protocol>::endpoint_impl(
std::shared_ptr<endpoint_host> _host,
- endpoint_type _local,
- boost::asio::io_service &_io,
- std::uint32_t _max_message_size)
+ endpoint_type _local,
+ boost::asio::io_service &_io,
+ std::uint32_t _max_message_size)
: service_(_io),
host_(_host),
is_supporting_magic_cookies_(false),
@@ -30,7 +30,7 @@ endpoint_impl<Protocol>::endpoint_impl( max_message_size_(_max_message_size),
use_count_(0),
sending_blocked_(false),
- local_(_local) {
+ local_(_local) {
}
template<typename Protocol>
@@ -43,11 +43,6 @@ void endpoint_impl<Protocol>::enable_magic_cookies() { }
template<typename Protocol>
-bool endpoint_impl<Protocol>::is_magic_cookie() const {
- return false;
-}
-
-template<typename Protocol>
uint32_t endpoint_impl<Protocol>::find_magic_cookie(
byte_t *_buffer, size_t _size) {
bool is_found(false);
@@ -114,23 +109,11 @@ void endpoint_impl<Protocol>::remove_default_target(service_t) { }
template<typename Protocol>
-bool endpoint_impl<Protocol>::get_remote_address(
- boost::asio::ip::address &_address) const {
- (void)_address;
- return false;
-}
-
-template<typename Protocol>
unsigned short endpoint_impl<Protocol>::get_local_port() const {
return 0;
}
template<typename Protocol>
-unsigned short endpoint_impl<Protocol>::get_remote_port() const {
- return 0;
-}
-
-template<typename Protocol>
bool endpoint_impl<Protocol>::is_reliable() const {
return false;
}
diff --git a/implementation/endpoints/src/local_client_endpoint_impl.cpp b/implementation/endpoints/src/local_client_endpoint_impl.cpp index 1a13e91..1466ac0 100644 --- a/implementation/endpoints/src/local_client_endpoint_impl.cpp +++ b/implementation/endpoints/src/local_client_endpoint_impl.cpp @@ -46,13 +46,6 @@ bool local_client_endpoint_impl::is_local() const { void local_client_endpoint_impl::start() {
if (socket_.is_open()) {
sending_blocked_ = false;
- {
- std::lock_guard<std::mutex> its_lock(stop_mutex_);
- boost::system::error_code its_error;
- socket_.cancel(its_error);
- socket_.shutdown(socket_type::shutdown_both, its_error);
- socket_.close(its_error);
- }
restart();
} else {
connect();
@@ -122,7 +115,7 @@ msg << "lce<" << this << ">::sq: "; for (std::size_t i = 0; i < its_buffer->size(); i++)
msg << std::setw(2) << std::setfill('0') << std::hex
<< (int)(*its_buffer)[i] << " ";
-VSOMEIP_DEBUG << msg.str();
+VSOMEIP_INFO << msg.str();
#endif
bufs.push_back(boost::asio::buffer(its_start_tag));
@@ -149,20 +142,42 @@ void local_client_endpoint_impl::send_magic_cookie() { void local_client_endpoint_impl::receive_cbk(
boost::system::error_code const &_error, std::size_t _bytes) {
(void)_bytes;
- if (_error == boost::asio::error::operation_aborted) {
- // endpoint was stopped
- shutdown_and_close_socket();
- } else if (_error == boost::asio::error::connection_reset
- || _error == boost::asio::error::eof
- || _error != boost::asio::error::bad_descriptor) {
- VSOMEIP_TRACE << "local_client_endpoint:"
- " connection_reseted/EOF/bad_descriptor";
- } else if (_error) {
- VSOMEIP_ERROR << "Local endpoint received message ("
- << _error.message() << ")";
+ if (_error) {
+ if (_error == boost::asio::error::operation_aborted) {
+ // endpoint was stopped
+ shutdown_and_close_socket();
+ } else if (_error == boost::asio::error::connection_reset
+ || _error == boost::asio::error::eof
+ || _error == boost::asio::error::bad_descriptor) {
+ VSOMEIP_TRACE << "local_client_endpoint:"
+ " connection_reseted/EOF/bad_descriptor";
+ } else if (_error) {
+ VSOMEIP_ERROR << "Local endpoint received message ("
+ << _error.message() << ")";
+ }
+ // The error handler is set only if the endpoint is hosted by the
+ // 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_();
} else {
receive();
}
}
+bool local_client_endpoint_impl::get_remote_address(
+ boost::asio::ip::address &_address) const {
+ (void)_address;
+ return false;
+}
+
+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/local_server_endpoint_impl.cpp b/implementation/endpoints/src/local_server_endpoint_impl.cpp index 851185a..697fd3b 100644 --- a/implementation/endpoints/src/local_server_endpoint_impl.cpp +++ b/implementation/endpoints/src/local_server_endpoint_impl.cpp @@ -14,6 +14,8 @@ #include "../include/local_server_endpoint_impl.hpp" #include "../../logging/include/logger.hpp" +#include "../../utility/include/byteorder.hpp" +#include "../../configuration/include/internal.hpp" #include "../../configuration/include/configuration.hpp" // Credentials @@ -26,9 +28,12 @@ namespace vsomeip { local_server_endpoint_impl::local_server_endpoint_impl( std::shared_ptr< endpoint_host > _host, endpoint_type _local, boost::asio::io_service &_io, - std::uint32_t _max_message_size) + std::uint32_t _max_message_size, + std::uint32_t _buffer_shrink_threshold) : local_server_endpoint_base_impl(_host, _local, _io, _max_message_size), - acceptor_(_io), current_(nullptr) { + acceptor_(_io), + current_(nullptr), + buffer_shrink_threshold_(_buffer_shrink_threshold) { is_supporting_magic_cookies_ = false; boost::system::error_code ec; @@ -52,9 +57,12 @@ local_server_endpoint_impl::local_server_endpoint_impl( std::shared_ptr< endpoint_host > _host, endpoint_type _local, boost::asio::io_service &_io, std::uint32_t _max_message_size, - int native_socket) + int native_socket, + std::uint32_t _buffer_shrink_threshold) : local_server_endpoint_base_impl(_host, _local, _io, _max_message_size), - acceptor_(_io), current_(nullptr) { + acceptor_(_io), + current_(nullptr), + buffer_shrink_threshold_(_buffer_shrink_threshold) { is_supporting_magic_cookies_ = false; boost::system::error_code ec; @@ -79,7 +87,7 @@ void local_server_endpoint_impl::start() { if (acceptor_.is_open()) { current_ = connection::create( std::dynamic_pointer_cast<local_server_endpoint_impl>( - shared_from_this()), max_message_size_); + shared_from_this()), buffer_shrink_threshold_); acceptor_.async_accept( current_->get_socket(), @@ -161,8 +169,9 @@ void local_server_endpoint_impl::remove_connection( void local_server_endpoint_impl::accept_cbk( connection::ptr _connection, boost::system::error_code const &_error) { - if (_error != boost::asio::error::bad_descriptor && - _error != boost::asio::error::operation_aborted) { + if (_error != boost::asio::error::bad_descriptor + && _error != boost::asio::error::operation_aborted + && _error != boost::asio::error::no_descriptors) { start(); } @@ -206,19 +215,28 @@ void local_server_endpoint_impl::accept_cbk( local_server_endpoint_impl::connection::connection( std::weak_ptr<local_server_endpoint_impl> _server, - std::uint32_t _max_message_size) + std::uint32_t _initial_recv_buffer_size, + std::uint32_t _buffer_shrink_threshold) : socket_(_server.lock()->service_), server_(_server), - max_message_size_(_max_message_size + 8), - recv_buffer_(max_message_size_, 0), - recv_buffer_size_(0), bound_client_(VSOMEIP_ROUTING_CLIENT) { + recv_buffer_size_initial_(_initial_recv_buffer_size + 8), + recv_buffer_(recv_buffer_size_initial_, 0), + recv_buffer_size_(0), + missing_capacity_(0), + shrink_count_(0), + buffer_shrink_threshold_(_buffer_shrink_threshold), + bound_client_(VSOMEIP_ROUTING_CLIENT) { } local_server_endpoint_impl::connection::ptr local_server_endpoint_impl::connection::create( std::weak_ptr<local_server_endpoint_impl> _server, - std::uint32_t _max_message_size) { - return ptr(new connection(_server, _max_message_size)); + std::uint32_t _buffer_shrink_threshold) { + const std::uint32_t its_initial_buffer_size = VSOMEIP_COMMAND_HEADER_SIZE + + VSOMEIP_MAX_LOCAL_MESSAGE_SIZE + sizeof(instance_t) + sizeof(bool) + + sizeof(bool); + return ptr(new connection(_server, its_initial_buffer_size, + _buffer_shrink_threshold)); } local_server_endpoint_impl::socket_type & @@ -228,11 +246,24 @@ local_server_endpoint_impl::connection::get_socket() { void local_server_endpoint_impl::connection::start() { if (socket_.is_open()) { - if (recv_buffer_size_ == max_message_size_) { - // Overrun -> Reset buffer - recv_buffer_size_ = 0; + const std::size_t its_capacity(recv_buffer_.capacity()); + size_t buffer_size = its_capacity - recv_buffer_size_; + if (missing_capacity_) { + const std::size_t its_required_capacity(recv_buffer_size_ + missing_capacity_); + if (its_capacity < its_required_capacity) { + recv_buffer_.reserve(its_required_capacity); + recv_buffer_.resize(its_required_capacity, 0x0); + } + buffer_size = missing_capacity_; + missing_capacity_ = 0; + } else if (buffer_shrink_threshold_ + && shrink_count_ > buffer_shrink_threshold_ + && recv_buffer_size_ == 0) { + recv_buffer_.resize(recv_buffer_size_initial_, 0x0); + recv_buffer_.shrink_to_fit(); + buffer_size = recv_buffer_size_initial_; + shrink_count_ = 0; } - size_t buffer_size = max_message_size_ - recv_buffer_size_; socket_.async_receive( boost::asio::buffer(&recv_buffer_[recv_buffer_size_], buffer_size), std::bind( @@ -273,7 +304,7 @@ void local_server_endpoint_impl::connection::send_queued( for (std::size_t i = 0; i < its_buffer->size(); i++) msg << std::setw(2) << std::setfill('0') << std::hex << (int)(*its_buffer)[i] << " "; - VSOMEIP_DEBUG << msg.str(); + VSOMEIP_INFO << msg.str(); #endif boost::asio::async_write( socket_, @@ -306,9 +337,10 @@ void local_server_endpoint_impl::connection::receive_cbk( } std::shared_ptr<endpoint_host> its_host = its_server->host_.lock(); if (its_host) { - std::size_t its_start; - std::size_t its_end; + std::size_t its_start = 0; + std::size_t its_end = 0; std::size_t its_iteration_gap = 0; + std::uint32_t its_command_size = 0; if (!_error && 0 < _bytes) { #if 0 @@ -317,7 +349,7 @@ void local_server_endpoint_impl::connection::receive_cbk( for (std::size_t i = 0; i < _bytes + recv_buffer_size_; i++) msg << std::setw(2) << std::setfill('0') << std::hex << (int) (recv_buffer_[i]) << " "; - VSOMEIP_DEBUG << msg.str(); + VSOMEIP_INFO << msg.str(); #endif recv_buffer_size_ += _bytes; @@ -332,14 +364,24 @@ void local_server_endpoint_impl::connection::receive_cbk( recv_buffer_[its_start+1] != 0x37 || recv_buffer_[its_start+2] != 0x6d || recv_buffer_[its_start+3] != 0x07)) { - its_start ++; + its_start++; } its_start = (its_start + 3 == recv_buffer_size_ + its_iteration_gap ? MESSAGE_IS_EMPTY : its_start+4); if (its_start != MESSAGE_IS_EMPTY) { - its_end = its_start; + if (its_start + 6 < recv_buffer_size_ + its_iteration_gap) { + its_command_size = VSOMEIP_BYTES_TO_LONG( + recv_buffer_[its_start + 6], + recv_buffer_[its_start + 5], + recv_buffer_[its_start + 4], + recv_buffer_[its_start + 3]); + + its_end = its_start + 6 + its_command_size; + } else { + its_end = its_start; + } while (its_end + 3 < recv_buffer_size_ + its_iteration_gap && (recv_buffer_[its_end] != 0x07 || recv_buffer_[its_end+1] != 0x6d || @@ -347,6 +389,30 @@ void local_server_endpoint_impl::connection::receive_cbk( recv_buffer_[its_end+3] != 0x67)) { its_end ++; } + // check if we received a full message + if (recv_buffer_size_ + its_iteration_gap < its_end + 4 + || recv_buffer_[its_end] != 0x07 + || recv_buffer_[its_end+1] != 0x6d + || recv_buffer_[its_end+2] != 0x37 + || recv_buffer_[its_end+3] != 0x67) { + // start tag (4 Byte) + command (1 Byte) + client id (2 Byte) + // + command size (4 Byte) + data itself + stop tag (4 byte) + // = 15 Bytes not covered in command size. + if (its_command_size && its_command_size + 15 > recv_buffer_size_) { + missing_capacity_ = its_command_size + 15 - std::uint32_t(recv_buffer_size_); + } else if (recv_buffer_size_ < 11) { + // to little data to read out the command size + // minimal amount of data needed to read out command size = 11 + missing_capacity_ = 11 - static_cast<std::uint32_t>(recv_buffer_size_); + } else { + VSOMEIP_ERROR << "lse::c<" << this + << ">rcb: recv_buffer_size is: " << std::dec + << recv_buffer_size_ << " but couldn't read " + "out command size. recv_buffer_capacity: " + << recv_buffer_.capacity() + << " its_iteration_gap: " << its_iteration_gap; + } + } } if (its_start != MESSAGE_IS_EMPTY && @@ -361,10 +427,12 @@ void local_server_endpoint_impl::connection::receive_cbk( for (std::size_t i = its_start; i < its_end; i++) local_msg << std::setw(2) << std::setfill('0') << std::hex << (int) recv_buffer_[i] << " "; - VSOMEIP_DEBUG << local_msg.str(); + VSOMEIP_INFO << local_msg.str(); #endif - + calculate_shrink_count(); recv_buffer_size_ -= (its_end + 4 - its_iteration_gap); + missing_capacity_ = 0; + its_command_size = 0; its_start = FOUND_MESSAGE; its_iteration_gap = its_end + 4; } else { @@ -374,6 +442,11 @@ void local_server_endpoint_impl::connection::receive_cbk( for (size_t i = 0; i < recv_buffer_size_; ++i) { recv_buffer_[i] = recv_buffer_[i + its_iteration_gap]; } + // Still more capacity needed after shifting everything to front? + if (missing_capacity_ && + missing_capacity_ <= recv_buffer_.capacity() - recv_buffer_size_) { + missing_capacity_ = 0; + } } } } while (recv_buffer_size_ > 0 && its_start == FOUND_MESSAGE); @@ -396,4 +469,16 @@ void local_server_endpoint_impl::connection::set_bound_client(client_t _client) bound_client_ = _client; } +void local_server_endpoint_impl::connection::calculate_shrink_count() { + if (buffer_shrink_threshold_) { + if (recv_buffer_.capacity() != recv_buffer_size_initial_) { + if (recv_buffer_size_ < (recv_buffer_.capacity() >> 1)) { + shrink_count_++; + } else { + shrink_count_ = 0; + } + } + } +} + } // namespace vsomeip diff --git a/implementation/endpoints/src/netlink_connector.cpp b/implementation/endpoints/src/netlink_connector.cpp new file mode 100644 index 0000000..aab5363 --- /dev/null +++ b/implementation/endpoints/src/netlink_connector.cpp @@ -0,0 +1,262 @@ +// Copyright (C) 2014-2016 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef WIN32 + +#include <thread> + +#include <boost/asio/write.hpp> +#include <boost/asio/read.hpp> + +#include "../include/netlink_connector.hpp" +#include "../../logging/include/logger.hpp" + +namespace vsomeip { + +void netlink_connector::register_net_if_changes_handler(net_if_changed_handler_t _handler) { + handler_ = _handler; +} + +void netlink_connector::unregister_net_if_changes_handler() { + handler_ = nullptr; +} + +void netlink_connector::stop() { + boost::system::error_code its_error; + socket_.close(its_error); + if (its_error) { + VSOMEIP_WARNING << "Error closing NETLINK socket!"; + } +} + +void netlink_connector::start() { + boost::system::error_code ec; + if (socket_.is_open()) { + socket_.close(ec); + if (ec) { + VSOMEIP_WARNING << "Error closing NETLINK socket: " << ec.message(); + } + } + socket_.open(nl_protocol(NETLINK_ROUTE), ec); + if (ec) { + VSOMEIP_WARNING << "Error opening NETLINK socket: " << ec.message(); + if (handler_) { + handler_("n/a", true); + } + return; + } + if (socket_.is_open()) { + socket_.bind(nl_endpoint<nl_protocol>(RTMGRP_LINK|RTMGRP_IPV4_IFADDR|RTMGRP_IPV6_IFADDR), ec); + + if (ec) { + VSOMEIP_WARNING << "Error binding NETLINK socket: " << ec.message(); + if (handler_) { + handler_("n/a", true); + } + return; + } + + send_ifa_request(); + + socket_.async_receive( + boost::asio::buffer(&recv_buffer_[0], recv_buffer_size), + std::bind( + &netlink_connector::receive_cbk, + shared_from_this(), + std::placeholders::_1, + std::placeholders::_2 + ) + ); + } else { + VSOMEIP_WARNING << "Error opening NETLINK socket!"; + if (handler_) { + handler_("n/a", true); + } + } +} + +void netlink_connector::receive_cbk(boost::system::error_code const &_error, + std::size_t _bytes) { + if (!_error) { + size_t len = _bytes; + + unsigned int address; + if (address_.is_v4()) { + inet_pton(AF_INET, address_.to_string().c_str(), &address); + } else { + inet_pton(AF_INET6, address_.to_string().c_str(), &address); + } + + struct nlmsghdr *nlh = (struct nlmsghdr *)&recv_buffer_[0]; + + while ((NLMSG_OK(nlh, len)) && (nlh->nlmsg_type != NLMSG_DONE)) { + char ifname[1024]; + struct ifinfomsg *ifi = (ifinfomsg *)NLMSG_DATA(nlh); + struct ifaddrmsg *ifa = (ifaddrmsg *)NLMSG_DATA(nlh); + switch (nlh->nlmsg_type) { + case RTM_NEWADDR: + // New Address information + if (has_address((struct ifaddrmsg *)NLMSG_DATA(nlh), + IFA_PAYLOAD(nlh), address)) { + net_if_index_for_address_ = ifa->ifa_index; + auto its_if = net_if_flags_.find(ifa->ifa_index); + if (its_if != net_if_flags_.end()) { + if ((its_if->second & IFF_UP) && + (its_if->second & IFF_RUNNING)) { + if (handler_) { + if_indextoname(ifa->ifa_index,ifname); + handler_(ifname, true); + } + } else { + if (handler_) { + if_indextoname(ifa->ifa_index,ifname); + handler_(ifname, false); + } + } + } else { + // Request interface information + // as we don't know about up/running state! + send_ifi_request(); + } + } + break; + case RTM_NEWLINK: + // New Interface information + net_if_flags_[ifi->ifi_index] = ifi->ifi_flags; + if (net_if_index_for_address_ == ifi->ifi_index) { + if ((ifi->ifi_flags & IFF_UP) && + (ifi->ifi_flags & IFF_RUNNING)) { + if (handler_) { + if_indextoname(ifi->ifi_index,ifname); + handler_(ifname, true); + } + } else { + if (handler_) { + if_indextoname(ifi->ifi_index,ifname); + handler_(ifname, false); + } + } + } + break; + default: + break; + } + nlh = NLMSG_NEXT(nlh, len); + } + socket_.async_receive( + boost::asio::buffer(&recv_buffer_[0], recv_buffer_size), + std::bind( + &netlink_connector::receive_cbk, + shared_from_this(), + std::placeholders::_1, + std::placeholders::_2 + ) + ); + } else { + if (_error != boost::asio::error::operation_aborted) { + VSOMEIP_WARNING << "Error receive_cbk NETLINK socket!" << _error.message(); + boost::system::error_code its_error; + if (socket_.is_open()) { + socket_.close(its_error); + if (its_error) { + VSOMEIP_WARNING << "Error closing NETLINK socket!" << its_error.message(); + } + } + if (handler_) { + handler_("n/a", true); + } + } + } +} + +void netlink_connector::send_cbk(boost::system::error_code const &_error, std::size_t _bytes) { + (void)_bytes; + if (_error) { + VSOMEIP_WARNING << "Netlink send error : " << _error.message(); + if (handler_) { + handler_("n/a", true); + } + } +} + +void netlink_connector::send_ifa_request() { + typedef struct { + struct nlmsghdr nlhdr; + struct ifaddrmsg addrmsg; + } netlink_address_msg; + netlink_address_msg get_address_msg; + memset(&get_address_msg, 0, sizeof(get_address_msg)); + get_address_msg.nlhdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg)); + get_address_msg.nlhdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_ROOT; + get_address_msg.nlhdr.nlmsg_type = RTM_GETADDR; + if (address_.is_v4()) { + get_address_msg.addrmsg.ifa_family = AF_INET; + } else { + get_address_msg.addrmsg.ifa_family = AF_INET6; + } + + socket_.async_send( + boost::asio::buffer(&get_address_msg, get_address_msg.nlhdr.nlmsg_len), + std::bind( + &netlink_connector::send_cbk, + shared_from_this(), + std::placeholders::_1, + std::placeholders::_2 + ) + ); +} + +void netlink_connector::send_ifi_request() { + typedef struct { + struct nlmsghdr nlhdr; + struct ifinfomsg infomsg; + } netlink_link_msg; + netlink_link_msg get_link_msg; + memset(&get_link_msg, 0, sizeof(get_link_msg)); + get_link_msg.nlhdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)); + get_link_msg.nlhdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_ROOT; + get_link_msg.nlhdr.nlmsg_type = RTM_GETLINK; + get_link_msg.infomsg.ifi_family = AF_UNSPEC; + + socket_.async_send( + boost::asio::buffer(&get_link_msg, get_link_msg.nlhdr.nlmsg_len), + std::bind( + &netlink_connector::send_cbk, + shared_from_this(), + std::placeholders::_1, + std::placeholders::_2 + ) + ); +} + +bool netlink_connector::has_address(const struct ifaddrmsg * ifa_struct, + size_t length, + const unsigned int address) { + + struct rtattr *retrta; + retrta = (struct rtattr *)IFA_RTA(ifa_struct); + while RTA_OK(retrta, length) { + if (retrta->rta_type == IFA_ADDRESS) { + char pradd[128]; + unsigned int * tmp_address = (unsigned int *)RTA_DATA(retrta); + if (address_.is_v4()) { + inet_ntop(AF_INET, tmp_address, pradd, sizeof(pradd)); + } else { + inet_ntop(AF_INET6, tmp_address, pradd, sizeof(pradd)); + } + if (address == *tmp_address) { + return true; + } + } + retrta = RTA_NEXT(retrta, length); + } + + return false; +} + +} // namespace vsomeip + +#endif + diff --git a/implementation/endpoints/src/server_endpoint_impl.cpp b/implementation/endpoints/src/server_endpoint_impl.cpp index c8e513b..4d4686b 100644 --- a/implementation/endpoints/src/server_endpoint_impl.cpp +++ b/implementation/endpoints/src/server_endpoint_impl.cpp @@ -5,6 +5,7 @@ #include <iomanip>
#include <sstream>
+#include <limits>
#include <boost/asio/buffer.hpp>
#include <boost/asio/ip/tcp.hpp>
@@ -55,7 +56,7 @@ bool server_endpoint_impl<Protocol>::send(const uint8_t *_data, msg << "sei::send ";
for (uint32_t i = 0; i < _size; i++)
msg << std::setw(2) << std::setfill('0') << (int)_data[i] << " ";
- VSOMEIP_DEBUG << msg.str();
+ VSOMEIP_INFO << msg.str();
#endif
endpoint_type its_target;
bool is_valid_target(false);
@@ -110,6 +111,14 @@ bool server_endpoint_impl<Protocol>::send_intern( return false;
}
+ if (endpoint_impl<Protocol>::max_message_size_ != MESSAGE_SIZE_UNLIMITED
+ && _size > endpoint_impl<Protocol>::max_message_size_) {
+ VSOMEIP_ERROR << "sei::send_intern: Dropping to big message (" << _size
+ << " Bytes). Maximum allowed message size is: "
+ << endpoint_impl<Protocol>::max_message_size_ << " Bytes.";
+ return false;
+ }
+
auto found_packetizer = packetizer_.find(_target);
if (found_packetizer != packetizer_.end()) {
target_packetizer = found_packetizer->second;
diff --git a/implementation/endpoints/src/tcp_client_endpoint_impl.cpp b/implementation/endpoints/src/tcp_client_endpoint_impl.cpp index 5165e4b..808efe5 100644 --- a/implementation/endpoints/src/tcp_client_endpoint_impl.cpp +++ b/implementation/endpoints/src/tcp_client_endpoint_impl.cpp @@ -14,6 +14,7 @@ #include "../include/tcp_client_endpoint_impl.hpp"
#include "../../logging/include/logger.hpp"
#include "../../utility/include/utility.hpp"
+#include "../../configuration/include/internal.hpp"
namespace ip = boost::asio::ip;
@@ -24,18 +25,23 @@ tcp_client_endpoint_impl::tcp_client_endpoint_impl( endpoint_type _local,
endpoint_type _remote,
boost::asio::io_service &_io,
- std::uint32_t _max_message_size)
+ std::uint32_t _max_message_size,
+ std::uint32_t _buffer_shrink_threshold)
: tcp_client_endpoint_base_impl(_host, _local, _remote, _io, _max_message_size),
- recv_buffer_(_max_message_size, 0),
- recv_buffer_size_(0) {
+ recv_buffer_size_initial_(VSOMEIP_SOMEIP_HEADER_SIZE),
+ recv_buffer_(recv_buffer_size_initial_, 0),
+ recv_buffer_size_(0),
+ missing_capacity_(0),
+ shrink_count_(0),
+ buffer_shrink_threshold_(_buffer_shrink_threshold) {
is_supporting_magic_cookies_ = true;
}
tcp_client_endpoint_impl::~tcp_client_endpoint_impl() {
- std::shared_ptr<endpoint_host> its_host = host_.lock();
- if (its_host) {
- its_host->release_port(local_.port(), true);
- }
+ std::shared_ptr<endpoint_host> its_host = host_.lock();
+ if (its_host) {
+ its_host->release_port(local_.port(), true);
+ }
}
bool tcp_client_endpoint_impl::is_local() const {
@@ -85,20 +91,35 @@ void tcp_client_endpoint_impl::connect() { }
void tcp_client_endpoint_impl::receive() {
- if (recv_buffer_size_ == max_message_size_) {
- // Overrun -> Reset buffer
- recv_buffer_size_ = 0;
+ if(socket_.is_open()) {
+ const std::size_t its_capacity(recv_buffer_.capacity());
+ size_t buffer_size = its_capacity - recv_buffer_size_;
+ if (missing_capacity_) {
+ const std::size_t its_required_capacity(recv_buffer_size_ + missing_capacity_);
+ if (its_capacity < its_required_capacity) {
+ recv_buffer_.reserve(its_required_capacity);
+ recv_buffer_.resize(its_required_capacity, 0x0);
+ }
+ buffer_size = missing_capacity_;
+ missing_capacity_ = 0;
+ } else if (buffer_shrink_threshold_
+ && shrink_count_ > buffer_shrink_threshold_
+ && recv_buffer_size_ == 0) {
+ recv_buffer_.resize(recv_buffer_size_initial_, 0x0);
+ recv_buffer_.shrink_to_fit();
+ buffer_size = recv_buffer_size_initial_;
+ shrink_count_ = 0;
+ }
+ socket_.async_receive(
+ boost::asio::buffer(&recv_buffer_[recv_buffer_size_], buffer_size),
+ std::bind(
+ &tcp_client_endpoint_impl::receive_cbk,
+ std::dynamic_pointer_cast< tcp_client_endpoint_impl >(shared_from_this()),
+ std::placeholders::_1,
+ std::placeholders::_2
+ )
+ );
}
- size_t buffer_size = max_message_size_ - recv_buffer_size_;
- socket_.async_receive(
- boost::asio::buffer(&recv_buffer_[recv_buffer_size_], buffer_size),
- std::bind(
- &tcp_client_endpoint_impl::receive_cbk,
- std::dynamic_pointer_cast< tcp_client_endpoint_impl >(shared_from_this()),
- std::placeholders::_1,
- std::placeholders::_2
- )
- );
}
void tcp_client_endpoint_impl::send_queued() {
@@ -119,7 +140,7 @@ void tcp_client_endpoint_impl::send_queued() { for (std::size_t i = 0; i < its_buffer->size(); i++)
msg << std::hex << std::setw(2) << std::setfill('0')
<< (int)(*its_buffer)[i] << " ";
- VSOMEIP_DEBUG << msg.str();
+ VSOMEIP_INFO << msg.str();
#endif
boost::asio::async_write(
@@ -136,18 +157,28 @@ void tcp_client_endpoint_impl::send_queued() { bool tcp_client_endpoint_impl::get_remote_address(
boost::asio::ip::address &_address) const {
- _address = remote_.address();
+ const boost::asio::ip::address its_address = remote_.address();
+ if (its_address.is_unspecified()) {
+ return false;
+ }
+ _address = its_address;
return true;
}
unsigned short tcp_client_endpoint_impl::get_local_port() const {
boost::system::error_code its_error;
- return socket_.local_endpoint(its_error).port();
+ if (socket_.is_open()) {
+ return socket_.local_endpoint(its_error).port();
+ }
+ return 0;
}
unsigned short tcp_client_endpoint_impl::get_remote_port() const {
boost::system::error_code its_error;
- return socket_.remote_endpoint(its_error).port();
+ if (socket_.is_open()) {
+ return socket_.remote_endpoint(its_error).port();
+ }
+ return 0;
}
bool tcp_client_endpoint_impl::is_reliable() const {
@@ -159,7 +190,8 @@ bool tcp_client_endpoint_impl::is_magic_cookie(size_t _offset) const { }
void tcp_client_endpoint_impl::send_magic_cookie(message_buffer_ptr_t &_buffer) {
- if (VSOMEIP_MAX_TCP_MESSAGE_SIZE - _buffer->size() >=
+ if (max_message_size_ == MESSAGE_SIZE_UNLIMITED
+ || max_message_size_ - _buffer->size() >=
VSOMEIP_SOMEIP_HEADER_SIZE + VSOMEIP_SOMEIP_MAGIC_COOKIE_SIZE) {
_buffer->insert(
_buffer->begin(),
@@ -184,13 +216,17 @@ void tcp_client_endpoint_impl::receive_cbk( for (std::size_t i = 0; i < _bytes + recv_buffer_size_; ++i)
msg << std::hex << std::setw(2) << std::setfill('0')
<< (int) recv_buffer_[i] << " ";
- VSOMEIP_DEBUG << msg.str();
+ VSOMEIP_INFO << msg.str();
#endif
std::shared_ptr<endpoint_host> its_host = host_.lock();
if (its_host) {
if (!_error && 0 < _bytes) {
recv_buffer_size_ += _bytes;
+ boost::system::error_code its_error;
+ endpoint_type its_endpoint(socket_.remote_endpoint(its_error));
+ const boost::asio::ip::address its_remote_address(its_endpoint.address());
+ const std::uint16_t its_remote_port(its_endpoint.port());
size_t its_iteration_gap = 0;
bool has_full_message;
do {
@@ -217,25 +253,42 @@ void tcp_client_endpoint_impl::receive_cbk( if (needs_forwarding) {
if (!has_enabled_magic_cookies_) {
its_host->on_message(&recv_buffer_[its_iteration_gap],
- current_message_size, this);
+ current_message_size, this,
+ boost::asio::ip::address(),
+ VSOMEIP_ROUTING_CLIENT,
+ its_remote_address,
+ its_remote_port);
} else {
// Only call on_message without a magic cookie in front of the buffer!
if (!is_magic_cookie(its_iteration_gap)) {
its_host->on_message(&recv_buffer_[its_iteration_gap],
- current_message_size, this);
+ current_message_size, this,
+ boost::asio::ip::address(),
+ VSOMEIP_ROUTING_CLIENT,
+ its_remote_address,
+ its_remote_port);
}
}
}
+ calculate_shrink_count();
recv_buffer_size_ -= current_message_size;
its_iteration_gap += current_message_size;
- } else if (has_enabled_magic_cookies_ && recv_buffer_size_ > 0){
+ missing_capacity_ = 0;
+ } else if (current_message_size > recv_buffer_size_) {
+ missing_capacity_ = current_message_size
+ - static_cast<std::uint32_t>(recv_buffer_size_);
+ } else if (VSOMEIP_SOMEIP_HEADER_SIZE > recv_buffer_size_) {
+ missing_capacity_ = VSOMEIP_SOMEIP_HEADER_SIZE
+ - static_cast<std::uint32_t>(recv_buffer_size_);
+ } else if (has_enabled_magic_cookies_ && recv_buffer_size_ > 0) {
uint32_t its_offset = find_magic_cookie(&recv_buffer_[its_iteration_gap], recv_buffer_size_);
if (its_offset < recv_buffer_size_) {
recv_buffer_size_ -= its_offset;
its_iteration_gap += its_offset;
has_full_message = true; // trigger next loop
}
- } else if (current_message_size > max_message_size_) {
+ } else if (max_message_size_ != MESSAGE_SIZE_UNLIMITED &&
+ current_message_size > max_message_size_) {
if (has_enabled_magic_cookies_) {
VSOMEIP_ERROR << "Received a TCP message which exceeds "
<< "maximum message size ("
@@ -252,6 +305,13 @@ void tcp_client_endpoint_impl::receive_cbk( recv_buffer_size_ = 0;
return;
}
+ } else {
+ VSOMEIP_ERROR << "tce::c<" << this
+ << ">rcb: recv_buffer_size is: " << std::dec
+ << recv_buffer_size_ << " but couldn't read "
+ "out message_size. recv_buffer_capacity: "
+ << recv_buffer_.capacity()
+ << " its_iteration_gap: " << its_iteration_gap;
}
} while (has_full_message && recv_buffer_size_);
if (its_iteration_gap) {
@@ -259,6 +319,11 @@ void tcp_client_endpoint_impl::receive_cbk( for (size_t i = 0; i < recv_buffer_size_; ++i) {
recv_buffer_[i] = recv_buffer_[i + its_iteration_gap];
}
+ // Still more capacity needed after shifting everything to front?
+ if (missing_capacity_ &&
+ missing_capacity_ <= recv_buffer_.capacity() - recv_buffer_size_) {
+ missing_capacity_ = 0;
+ }
}
receive();
} else {
@@ -273,4 +338,16 @@ void tcp_client_endpoint_impl::receive_cbk( }
}
+void tcp_client_endpoint_impl::calculate_shrink_count() {
+ if (buffer_shrink_threshold_) {
+ if (recv_buffer_.capacity() != recv_buffer_size_initial_) {
+ if (recv_buffer_size_ < (recv_buffer_.capacity() >> 1)) {
+ shrink_count_++;
+ } else {
+ shrink_count_ = 0;
+ }
+ }
+ }
+}
+
} // namespace vsomeip
diff --git a/implementation/endpoints/src/tcp_server_endpoint_impl.cpp b/implementation/endpoints/src/tcp_server_endpoint_impl.cpp index 8e98fd0..4c5bdc7 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 "../../configuration/include/internal.hpp" namespace ip = boost::asio::ip; @@ -21,10 +22,11 @@ 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) + boost::asio::io_service &_io, std::uint32_t _max_message_size, + std::uint32_t _buffer_shrink_threshold) : tcp_server_endpoint_base_impl(_host, _local, _io, _max_message_size), acceptor_(_io), - current_(0) { + buffer_shrink_threshold_(_buffer_shrink_threshold) { is_supporting_magic_cookies_ = true; boost::system::error_code ec; @@ -48,7 +50,8 @@ bool tcp_server_endpoint_impl::is_local() const { void tcp_server_endpoint_impl::start() { connection::ptr new_connection = connection::create( std::dynamic_pointer_cast<tcp_server_endpoint_impl>( - shared_from_this()), max_message_size_); + shared_from_this()), max_message_size_, + buffer_shrink_threshold_); acceptor_.async_accept(new_connection->get_socket(), std::bind(&tcp_server_endpoint_impl::accept_cbk, @@ -92,7 +95,7 @@ void tcp_server_endpoint_impl::send_queued(queue_iterator_type _queue_iterator) if (connection_iterator != connections_.end()) { its_connection = connection_iterator->second; } else { - VSOMEIP_DEBUG << "Didn't find connection: " + VSOMEIP_INFO << "Didn't find connection: " << _queue_iterator->first.address().to_string() << ":" << std::dec << static_cast<std::uint16_t>(_queue_iterator->first.port()) << " dropping message."; @@ -113,7 +116,7 @@ bool tcp_server_endpoint_impl::is_established(std::shared_ptr<endpoint_definitio if (connection_iterator != connections_.end()) { is_connected = true; } else { - VSOMEIP_DEBUG << "Didn't find TCP connection: Subscription " + VSOMEIP_INFO << "Didn't find TCP connection: Subscription " << "rejected for: " << endpoint.address().to_string() << ":" << std::dec << static_cast<std::uint16_t>(endpoint.port()); } @@ -121,36 +124,6 @@ bool tcp_server_endpoint_impl::is_established(std::shared_ptr<endpoint_definitio return is_connected; } -bool tcp_server_endpoint_impl::get_remote_address( - boost::asio::ip::address &_address) const { - - if (current_) { - boost::system::error_code its_error; - tcp_server_endpoint_impl::endpoint_type its_endpoint = - current_->get_socket().remote_endpoint(its_error); - if (!its_error) { - boost::asio::ip::address its_address = its_endpoint.address(); - if (!its_address.is_unspecified()) { - _address = its_address; - return true; - } - } - } - return false; -} - -unsigned short tcp_server_endpoint_impl::get_remote_port() const { - if (current_) { - boost::system::error_code its_error; - tcp_server_endpoint_impl::endpoint_type its_endpoint = - current_->get_socket().remote_endpoint(its_error); - if (!its_error) { - return its_endpoint.port(); - } - } - return 0; -} - bool tcp_server_endpoint_impl::get_default_target(service_t, tcp_server_endpoint_impl::endpoint_type &) const { return false; @@ -161,6 +134,7 @@ void tcp_server_endpoint_impl::remove_connection( std::lock_guard<std::mutex> its_lock(connections_mutex_); for (auto it = connections_.begin(); it != connections_.end();) { if (it->second.get() == _connection) { + it = connections_.erase(it); break; } else { @@ -183,10 +157,11 @@ void tcp_server_endpoint_impl::accept_cbk(connection::ptr _connection, } } if (_error != boost::asio::error::bad_descriptor - && _error != boost::asio::error::operation_aborted) { + && _error != boost::asio::error::operation_aborted + && _error != boost::asio::error::no_descriptors) { start(); } else { - VSOMEIP_DEBUG << "Endpoint was stopped, don't starting again"; + VSOMEIP_INFO << "Endpoint was stopped, don't starting again"; } } @@ -204,18 +179,30 @@ bool tcp_server_endpoint_impl::is_reliable() const { /////////////////////////////////////////////////////////////////////////////// tcp_server_endpoint_impl::connection::connection( std::weak_ptr<tcp_server_endpoint_impl> _server, - std::uint32_t _max_message_size) : - socket_(_server.lock()->service_), server_(_server), + std::uint32_t _max_message_size, + std::uint32_t _initial_recv_buffer_size, + std::uint32_t _buffer_shrink_threshold) : + socket_(_server.lock()->service_), + server_(_server), max_message_size_(_max_message_size), - recv_buffer_(_max_message_size, 0), - recv_buffer_size_(0) { + recv_buffer_size_initial_(_initial_recv_buffer_size), + recv_buffer_(_initial_recv_buffer_size, 0), + recv_buffer_size_(0), + missing_capacity_(0), + shrink_count_(0), + buffer_shrink_threshold_(_buffer_shrink_threshold) { } tcp_server_endpoint_impl::connection::ptr tcp_server_endpoint_impl::connection::create( std::weak_ptr<tcp_server_endpoint_impl> _server, - std::uint32_t _max_message_size) { - return ptr(new connection(_server, _max_message_size)); + std::uint32_t _max_message_size, std::uint32_t _buffer_shrink_threshold) { + 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)); } tcp_server_endpoint_impl::socket_type & @@ -231,13 +218,26 @@ void tcp_server_endpoint_impl::connection::start() { } void tcp_server_endpoint_impl::connection::receive() { - if (recv_buffer_size_ == max_message_size_) { - // Overrun -> Reset buffer - recv_buffer_size_ = 0; - } std::lock_guard<std::mutex> its_lock(stop_mutex_); if(socket_.is_open()) { - size_t buffer_size = max_message_size_ - recv_buffer_size_; + const std::size_t its_capacity(recv_buffer_.capacity()); + size_t buffer_size = its_capacity - recv_buffer_size_; + if (missing_capacity_) { + const std::size_t its_required_capacity(recv_buffer_size_ + missing_capacity_); + if (its_capacity < its_required_capacity) { + recv_buffer_.reserve(its_required_capacity); + recv_buffer_.resize(its_required_capacity, 0x0); + } + buffer_size = missing_capacity_; + missing_capacity_ = 0; + } else if (buffer_shrink_threshold_ + && shrink_count_ > buffer_shrink_threshold_ + && recv_buffer_size_ == 0) { + recv_buffer_.resize(recv_buffer_size_initial_, 0x0); + recv_buffer_.shrink_to_fit(); + buffer_size = recv_buffer_size_initial_; + shrink_count_ = 0; + } socket_.async_receive(boost::asio::buffer(&recv_buffer_[recv_buffer_size_], buffer_size), std::bind(&tcp_server_endpoint_impl::connection::receive_cbk, shared_from_this(), std::placeholders::_1, @@ -276,7 +276,8 @@ void tcp_server_endpoint_impl::connection::send_queued( void tcp_server_endpoint_impl::connection::send_magic_cookie( message_buffer_ptr_t &_buffer) { - if (VSOMEIP_MAX_TCP_MESSAGE_SIZE - _buffer->size() >= + if (recv_buffer_size_initial_ == MESSAGE_SIZE_UNLIMITED + || recv_buffer_size_initial_ - _buffer->size() >= VSOMEIP_SOMEIP_HEADER_SIZE + VSOMEIP_SOMEIP_MAGIC_COOKIE_SIZE) { _buffer->insert(_buffer->begin(), SERVICE_COOKIE, SERVICE_COOKIE + sizeof(SERVICE_COOKIE)); @@ -306,13 +307,17 @@ void tcp_server_endpoint_impl::connection::receive_cbk( for (std::size_t i = 0; i < _bytes + recv_buffer_size_; ++i) msg << std::hex << std::setw(2) << std::setfill('0') << (int) recv_buffer_[i] << " "; - VSOMEIP_DEBUG<< msg.str(); + VSOMEIP_INFO << msg.str(); #endif std::shared_ptr<endpoint_host> its_host = its_server->host_.lock(); if (its_host) { if (!_error && 0 < _bytes) { recv_buffer_size_ += _bytes; + boost::system::error_code its_error; + endpoint_type its_endpoint(socket_.remote_endpoint(its_error)); + const boost::asio::ip::address its_remote_address(its_endpoint.address()); + const std::uint16_t its_remote_port(its_endpoint.port()); size_t its_iteration_gap = 0; bool has_full_message; do { @@ -334,7 +339,8 @@ void tcp_server_endpoint_impl::connection::receive_cbk( VSOMEIP_ERROR << "Detected Magic Cookie within message data. Resyncing."; if (!is_magic_cookie(its_iteration_gap)) { its_host->on_error(&recv_buffer_[its_iteration_gap], - static_cast<length_t>(recv_buffer_size_), its_server.get()); + static_cast<length_t>(recv_buffer_size_),its_server.get(), + its_remote_address, its_remote_port); } current_message_size = its_offset; needs_forwarding = false; @@ -357,27 +363,32 @@ void tcp_server_endpoint_impl::connection::receive_cbk( std::lock_guard<std::mutex> its_lock(stop_mutex_); if (socket_.is_open()) { its_server->clients_mutex_.lock(); - boost::system::error_code its_error; - endpoint_type its_endpoint(socket_.remote_endpoint(its_error)); if (!its_error) { its_server->clients_[its_client][its_session] = its_endpoint; } its_server->clients_mutex_.unlock(); - its_server->current_ = this; } } } if (!its_server->has_enabled_magic_cookies_) { its_host->on_message(&recv_buffer_[its_iteration_gap], - current_message_size, its_server.get()); + current_message_size, its_server.get(), + boost::asio::ip::address(), + VSOMEIP_ROUTING_CLIENT, its_remote_address, + its_remote_port); } else { // Only call on_message without a magic cookie in front of the buffer! if (!is_magic_cookie(its_iteration_gap)) { its_host->on_message(&recv_buffer_[its_iteration_gap], - current_message_size, its_server.get()); + current_message_size, its_server.get(), + boost::asio::ip::address(), + VSOMEIP_ROUTING_CLIENT, + its_remote_address, its_remote_port); } } } + calculate_shrink_count(); + missing_capacity_ = 0; recv_buffer_size_ -= current_message_size; its_iteration_gap += current_message_size; } else if (its_server->has_enabled_magic_cookies_ && recv_buffer_size_ > 0){ @@ -388,21 +399,25 @@ void tcp_server_endpoint_impl::connection::receive_cbk( VSOMEIP_ERROR << "Detected Magic Cookie within message data. Resyncing."; if (!is_magic_cookie(its_iteration_gap)) { its_host->on_error(&recv_buffer_[its_iteration_gap], - static_cast<length_t>(recv_buffer_size_), its_server.get()); + static_cast<length_t>(recv_buffer_size_), its_server.get(), + its_remote_address, its_remote_port); } recv_buffer_size_ -= its_offset; its_iteration_gap += its_offset; has_full_message = true; // trigger next loop if (!is_magic_cookie(its_iteration_gap)) { its_host->on_error(&recv_buffer_[its_iteration_gap], - static_cast<length_t>(recv_buffer_size_), its_server.get()); + static_cast<length_t>(recv_buffer_size_), its_server.get(), + its_remote_address, its_remote_port); } } - } else if (current_message_size > max_message_size_) { + } else if (max_message_size_ != MESSAGE_SIZE_UNLIMITED + && current_message_size > max_message_size_) { if (its_server->has_enabled_magic_cookies_) { VSOMEIP_ERROR << "Received a TCP message which exceeds " << "maximum message size (" << std::dec << current_message_size + << " > " << std::dec << max_message_size_ << "). Magic Cookies are enabled: " << "Resetting receiver."; recv_buffer_size_ = 0; @@ -410,18 +425,41 @@ void tcp_server_endpoint_impl::connection::receive_cbk( VSOMEIP_ERROR << "Received a TCP message which exceeds " << "maximum message size (" << std::dec << current_message_size + << " > " << std::dec << max_message_size_ << ") Magic cookies are disabled: " << "Connection will be disabled!"; recv_buffer_size_ = 0; return; } } + + if (!has_full_message) { + if (current_message_size > recv_buffer_size_) { + missing_capacity_ = current_message_size + - static_cast<std::uint32_t>(recv_buffer_size_); + } else if (VSOMEIP_SOMEIP_HEADER_SIZE > recv_buffer_size_) { + missing_capacity_ = VSOMEIP_SOMEIP_HEADER_SIZE + - static_cast<std::uint32_t>(recv_buffer_size_); + } else { + VSOMEIP_ERROR << "tse::c<" << this + << ">rcb: recv_buffer_size is: " << std::dec + << recv_buffer_size_ << " but couldn't read " + "out message_size. recv_buffer_capacity: " + << recv_buffer_.capacity() + << " its_iteration_gap: " << its_iteration_gap; + } + } } while (has_full_message && recv_buffer_size_); if (its_iteration_gap) { // Copy incomplete message to front for next receive_cbk iteration for (size_t i = 0; i < recv_buffer_size_; ++i) { recv_buffer_[i] = recv_buffer_[i + its_iteration_gap]; } + // Still more capacity needed after shifting everything to front? + if (missing_capacity_ && + missing_capacity_ <= recv_buffer_.capacity() - recv_buffer_size_) { + missing_capacity_ = 0; + } } receive(); } @@ -436,6 +474,18 @@ void tcp_server_endpoint_impl::connection::receive_cbk( } } +void tcp_server_endpoint_impl::connection::calculate_shrink_count() { + if (buffer_shrink_threshold_) { + if (recv_buffer_.capacity() != recv_buffer_size_initial_) { + if (recv_buffer_size_ < (recv_buffer_.capacity() >> 1)) { + shrink_count_++; + } else { + shrink_count_ = 0; + } + } + } +} + client_t tcp_server_endpoint_impl::get_client(std::shared_ptr<endpoint_definition> _endpoint) { endpoint_type endpoint(_endpoint->get_address(), _endpoint->get_port()); { diff --git a/implementation/endpoints/src/udp_client_endpoint_impl.cpp b/implementation/endpoints/src/udp_client_endpoint_impl.cpp index 4513845..6025252 100644 --- a/implementation/endpoints/src/udp_client_endpoint_impl.cpp +++ b/implementation/endpoints/src/udp_client_endpoint_impl.cpp @@ -17,19 +17,19 @@ namespace vsomeip { udp_client_endpoint_impl::udp_client_endpoint_impl(
std::shared_ptr< endpoint_host > _host,
- endpoint_type _local,
- endpoint_type _remote,
+ endpoint_type _local,
+ endpoint_type _remote,
boost::asio::io_service &_io)
: udp_client_endpoint_base_impl(_host, _local, _remote, _io,
- VSOMEIP_MAX_UDP_MESSAGE_SIZE),
+ VSOMEIP_MAX_UDP_MESSAGE_SIZE),
recv_buffer_(VSOMEIP_MAX_UDP_MESSAGE_SIZE, 0) {
}
udp_client_endpoint_impl::~udp_client_endpoint_impl() {
- std::shared_ptr<endpoint_host> its_host = host_.lock();
- if (its_host) {
- its_host->release_port(local_.port(), false);
- }
+ std::shared_ptr<endpoint_host> its_host = host_.lock();
+ if (its_host) {
+ its_host->release_port(local_.port(), false);
+ }
}
bool udp_client_endpoint_impl::is_local() const {
@@ -37,13 +37,18 @@ bool udp_client_endpoint_impl::is_local() const { }
void udp_client_endpoint_impl::connect() {
- // In case a client endpoint port was configured,
- // bind to it before connecting
- if (local_.port() != ILLEGAL_PORT) {
- socket_.bind(local_);
- }
+ // In case a client endpoint port was configured,
+ // bind to it before connecting
+ if (local_.port() != ILLEGAL_PORT) {
+ boost::system::error_code its_bind_error;
+ socket_.bind(local_, its_bind_error);
+ if(its_bind_error) {
+ VSOMEIP_WARNING << "tcp_client_endpoint::connect: "
+ "Error binding socket: " << its_bind_error.message();
+ }
+ }
- socket_.async_connect(
+ socket_.async_connect(
remote_,
std::bind(
&udp_client_endpoint_base_impl::connect_cbk,
@@ -78,7 +83,7 @@ void udp_client_endpoint_impl::send_queued() { for (std::size_t i = 0; i < its_buffer->size(); i++)
msg << std::hex << std::setw(2) << std::setfill('0')
<< (int)(*its_buffer)[i] << " ";
- VSOMEIP_DEBUG << msg.str();
+ VSOMEIP_INFO << msg.str();
#endif
socket_.async_send(
boost::asio::buffer(*its_buffer),
@@ -108,18 +113,28 @@ void udp_client_endpoint_impl::receive() { bool udp_client_endpoint_impl::get_remote_address(
boost::asio::ip::address &_address) const {
- _address = remote_.address();
+ const boost::asio::ip::address its_address = remote_.address();
+ if (its_address.is_unspecified()) {
+ return false;
+ }
+ _address = its_address;
return true;
}
unsigned short udp_client_endpoint_impl::get_local_port() const {
boost::system::error_code its_error;
- return socket_.local_endpoint(its_error).port();
+ if (socket_.is_open()) {
+ return socket_.local_endpoint(its_error).port();
+ }
+ return 0;
}
unsigned short udp_client_endpoint_impl::get_remote_port() const {
boost::system::error_code its_error;
- return socket_.remote_endpoint(its_error).port();
+ if (socket_.is_open()) {
+ return socket_.remote_endpoint(its_error).port();
+ }
+ return 0;
}
void udp_client_endpoint_impl::receive_cbk(
@@ -137,10 +152,15 @@ void udp_client_endpoint_impl::receive_cbk( for (std::size_t i = 0; i < _bytes + recv_buffer_size_; ++i)
msg << std::hex << std::setw(2) << std::setfill('0')
<< (int) recv_buffer_[i] << " ";
- VSOMEIP_DEBUG << msg.str();
+ VSOMEIP_INFO << msg.str();
#endif
std::size_t remaining_bytes = _bytes;
std::size_t i = 0;
+ boost::system::error_code its_error;
+ endpoint_type its_endpoint(socket_.remote_endpoint(its_error));
+ const boost::asio::ip::address its_remote_address(its_endpoint.address());
+ const std::uint16_t its_remote_port(its_endpoint.port());
+
do {
uint32_t current_message_size
= utility::get_message_size(&this->recv_buffer_[i],
@@ -149,11 +169,17 @@ void udp_client_endpoint_impl::receive_cbk( current_message_size <= remaining_bytes) {
remaining_bytes -= current_message_size;
- its_host->on_message(&recv_buffer_[i], current_message_size, this);
- } else {
- VSOMEIP_ERROR << "Received a unreliable vSomeIP message with bad length field";
- remaining_bytes = 0;
- }
+ its_host->on_message(&recv_buffer_[i], current_message_size,
+ this, boost::asio::ip::address(),
+ VSOMEIP_ROUTING_CLIENT, its_remote_address,
+ its_remote_port);
+ } else {
+ VSOMEIP_ERROR << "Received a unreliable vSomeIP message with bad "
+ "length field. Message size: " << current_message_size
+ << " Bytes. From: " << remote_.address() << ":"
+ << remote_.port() << ". Dropping message.";
+ remaining_bytes = 0;
+ }
i += current_message_size;
} while (remaining_bytes > 0);
}
diff --git a/implementation/endpoints/src/udp_server_endpoint_impl.cpp b/implementation/endpoints/src/udp_server_endpoint_impl.cpp index 1585826..28079d1 100644 --- a/implementation/endpoints/src/udp_server_endpoint_impl.cpp +++ b/implementation/endpoints/src/udp_server_endpoint_impl.cpp @@ -129,7 +129,7 @@ void udp_server_endpoint_impl::send_queued( for (std::size_t i = 0; i < its_buffer->size(); ++i) msg << std::hex << std::setw(2) << std::setfill('0') << (int)(*its_buffer)[i] << " "; - VSOMEIP_DEBUG << msg.str(); + VSOMEIP_INFO << msg.str(); #endif socket_.async_send_to( boost::asio::buffer(*its_buffer), @@ -144,21 +144,6 @@ void udp_server_endpoint_impl::send_queued( ); } -bool udp_server_endpoint_impl::get_remote_address( - boost::asio::ip::address &_address) const { - boost::asio::ip::address its_address = remote_.address(); - if (its_address.is_unspecified()) { - return false; - } else { - _address = its_address; - } - return true; -} - -unsigned short udp_server_endpoint_impl::get_remote_port() const { - return remote_.port(); -} - bool udp_server_endpoint_impl::is_joined(const std::string &_address) const { return (joined_.find(_address) != joined_.end()); } @@ -193,7 +178,7 @@ void udp_server_endpoint_impl::join(const std::string &_address) { } joined_.insert(_address); } else { - VSOMEIP_DEBUG << "udp_server_endpoint_impl::join: " + VSOMEIP_INFO << "udp_server_endpoint_impl::join: " "Trying to join already joined address: " << _address; } } @@ -257,13 +242,15 @@ void udp_server_endpoint_impl::receive_cbk( for (std::size_t i = 0; i < _bytes; ++i) msg << std::hex << std::setw(2) << std::setfill('0') << (int) recv_buffer_[i] << " "; - VSOMEIP_DEBUG << msg.str(); + VSOMEIP_INFO << msg.str(); #endif std::shared_ptr<endpoint_host> its_host = this->host_.lock(); if (its_host) { if (!_error && 0 < _bytes) { std::size_t remaining_bytes = _bytes; std::size_t i = 0; + const boost::asio::ip::address its_remote_address(remote_.address()); + const std::uint16_t its_remote_port(remote_.port()); do { uint32_t current_message_size = utility::get_message_size(&this->recv_buffer_[i], @@ -290,7 +277,10 @@ void udp_server_endpoint_impl::receive_cbk( if (its_service != VSOMEIP_SD_SERVICE || (current_message_size > VSOMEIP_SOMEIP_HEADER_SIZE && current_message_size >= remaining_bytes)) { - its_host->on_message(&recv_buffer_[i], current_message_size, this, _destination); + its_host->on_message(&recv_buffer_[i], + current_message_size, this, _destination, + VSOMEIP_ROUTING_CLIENT, its_remote_address, + its_remote_port); } else { //ignore messages for service discovery with shorter SomeIP length VSOMEIP_ERROR << "Received an unreliable vSomeIP SD message with too short length field"; @@ -301,7 +291,9 @@ void udp_server_endpoint_impl::receive_cbk( service_t its_service = VSOMEIP_BYTES_TO_WORD(recv_buffer_[VSOMEIP_SERVICE_POS_MIN], recv_buffer_[VSOMEIP_SERVICE_POS_MAX]); if (its_service != VSOMEIP_SD_SERVICE) { - its_host->on_error(&recv_buffer_[i], (uint32_t)remaining_bytes, this); + its_host->on_error(&recv_buffer_[i], + (uint32_t)remaining_bytes, this, + its_remote_address, its_remote_port); } remaining_bytes = 0; } diff --git a/implementation/helper/boost/asio/detail/socket_ops_ext.hpp b/implementation/helper/boost/asio/detail/socket_ops_ext.hpp index 9280830..a272202 100644 --- a/implementation/helper/boost/asio/detail/socket_ops_ext.hpp +++ b/implementation/helper/boost/asio/detail/socket_ops_ext.hpp @@ -37,7 +37,7 @@ BOOST_ASIO_DECL size_t sync_recvfrom(socket_type s, state_type state, BOOST_ASIO_DECL void complete_iocp_recvfrom(
const weak_cancel_token_type& cancel_token,
boost::system::error_code& ec,
- boost::asio::ip::address& da);
+ boost::asio::ip::address& da);
#else // defined(BOOST_ASIO_HAS_IOCP)
diff --git a/implementation/logging/src/dlt_sink_backend.cpp b/implementation/logging/src/dlt_sink_backend.cpp index 9da5ae9..0af7722 100644 --- a/implementation/logging/src/dlt_sink_backend.cpp +++ b/implementation/logging/src/dlt_sink_backend.cpp @@ -21,9 +21,7 @@ dlt_sink_backend::dlt_sink_backend(const std::string &_app_id, const std::string &_context_id) { (void)_app_id; #ifdef USE_DLT - DLT_REGISTER_CONTEXT_LL_TS(dlt_, _context_id.c_str(), - VSOMEIP_LOG_DEFAULT_CONTEXT_NAME, DLT_LOG_DEBUG, - DLT_TRACE_STATUS_ON); + DLT_REGISTER_CONTEXT(dlt_, _context_id.c_str(), VSOMEIP_LOG_DEFAULT_CONTEXT_NAME); #else (void)_context_id; #endif diff --git a/implementation/message/include/deserializer.hpp b/implementation/message/include/deserializer.hpp index 0588aa7..7add37c 100644 --- a/implementation/message/include/deserializer.hpp +++ b/implementation/message/include/deserializer.hpp @@ -17,8 +17,9 @@ class message; class deserializer {
public:
- VSOMEIP_EXPORT deserializer();
- VSOMEIP_EXPORT deserializer(byte_t *_data, std::size_t _length);
+ VSOMEIP_EXPORT deserializer(std::uint32_t _buffer_shrink_threshold);
+ VSOMEIP_EXPORT deserializer(byte_t *_data, std::size_t _length,
+ std::uint32_t _buffer_shrink_threshold);
VSOMEIP_EXPORT deserializer(const deserializer& _other);
VSOMEIP_EXPORT virtual ~deserializer();
@@ -55,6 +56,10 @@ protected: std::vector<byte_t> data_;
std::vector<byte_t>::iterator position_;
std::size_t remaining_;
+private:
+ const std::uint32_t buffer_shrink_threshold_;
+ std::uint32_t shrink_count_;
+
};
} // namespace vsomeip
diff --git a/implementation/message/include/serializer.hpp b/implementation/message/include/serializer.hpp index a61f9ef..f19c853 100644 --- a/implementation/message/include/serializer.hpp +++ b/implementation/message/include/serializer.hpp @@ -17,7 +17,7 @@ class serializable; class VSOMEIP_IMPORT_EXPORT serializer {
public:
- serializer();
+ serializer(std::uint32_t _buffer_shrink_threshold);
virtual ~serializer();
bool serialize(const serializable *_from);
@@ -26,12 +26,12 @@ public: bool serialize(const uint16_t _value);
bool serialize(const uint32_t _value, bool _omit_last_byte = false);
bool serialize(const uint8_t *_data, uint32_t _length);
+ bool serialize(const std::vector<byte_t> &_data);
- virtual uint8_t * get_data() const;
+ virtual const uint8_t * get_data() const;
virtual uint32_t get_capacity() const;
virtual uint32_t get_size() const;
- virtual void create_data(uint32_t _capacity);
virtual void set_data(uint8_t *_data, uint32_t _capacity);
virtual void reset();
@@ -40,11 +40,9 @@ public: virtual void show();
#endif
private:
- byte_t * data_;
- uint32_t capacity_;
-
- byte_t *position_;
- uint32_t remaining_;
+ std::vector<byte_t> data_;
+ std::uint32_t shrink_count_;
+ std::uint32_t buffer_shrink_threshold_;
};
} // namespace vsomeip
diff --git a/implementation/message/src/deserializer.cpp b/implementation/message/src/deserializer.cpp index fb6f670..63713e3 100644 --- a/implementation/message/src/deserializer.cpp +++ b/implementation/message/src/deserializer.cpp @@ -17,20 +17,28 @@ namespace vsomeip {
-deserializer::deserializer()
+deserializer::deserializer(std::uint32_t _buffer_shrink_threshold)
: position_(data_.begin()),
- remaining_(0) {
+ remaining_(0),
+ buffer_shrink_threshold_(_buffer_shrink_threshold),
+ shrink_count_(0) {
}
-deserializer::deserializer(byte_t *_data, std::size_t _length)
+deserializer::deserializer(byte_t *_data, std::size_t _length,
+ std::uint32_t _buffer_shrink_threshold)
: data_(_data, _data + _length),
position_(data_.begin()),
- remaining_(_length) {
+ remaining_(_length),
+ buffer_shrink_threshold_(_buffer_shrink_threshold),
+ shrink_count_(0) {
}
deserializer::deserializer(const deserializer &_other)
: data_(_other.data_),
- position_(_other.position_){
+ position_(_other.position_),
+ remaining_(_other.remaining_),
+ buffer_shrink_threshold_(_other.buffer_shrink_threshold_),
+ shrink_count_(_other.shrink_count_) {
}
deserializer::~deserializer() {
@@ -183,9 +191,20 @@ void deserializer::drop_data(std::size_t _length) { }
void deserializer::reset() {
- data_.erase(data_.begin(), position_);
+ if (buffer_shrink_threshold_) {
+ if (data_.size() < (data_.capacity() >> 1)) {
+ shrink_count_++;
+ } else {
+ shrink_count_ = 0;
+ }
+ }
+ data_.clear();
position_ = data_.begin();
remaining_ = data_.size();
+ if (buffer_shrink_threshold_ && shrink_count_ > buffer_shrink_threshold_) {
+ data_.shrink_to_fit();
+ shrink_count_ = 0;
+ }
}
#ifdef VSOMEIP_DEBUGGING
@@ -198,7 +217,7 @@ void deserializer::show() const { for (int i = 0; i < data_.size(); ++i)
its_message << std::hex << std::setw(2) << std::setfill('0')
<< (int)data_[i] << " ";
- VSOMEIP_DEBUG << its_message;
+ VSOMEIP_INFO << its_message;
}
#endif
diff --git a/implementation/message/src/message_header_impl.cpp b/implementation/message/src/message_header_impl.cpp index 3262c8d..fb33bc1 100644 --- a/implementation/message/src/message_header_impl.cpp +++ b/implementation/message/src/message_header_impl.cpp @@ -13,22 +13,23 @@ namespace vsomeip {
message_header_impl::message_header_impl()
- : service_(0x0), method_(0x0),
+ : service_(0x0), method_(0x0), length_(0x0),
client_(0x0), session_(0x0),
protocol_version_(0x1), interface_version_(0x0),
type_(message_type_e::MT_UNKNOWN),
code_(return_code_e::E_UNKNOWN),
- instance_(0x0) {
+ instance_(0x0), owner_(0x0) {
};
message_header_impl::message_header_impl(const message_header_impl &_header)
: service_(_header.service_), method_(_header.method_),
+ length_(_header.length_),
client_(_header.client_), session_(_header.session_),
protocol_version_(_header.protocol_version_),
interface_version_(_header.interface_version_),
type_(_header.type_),
code_(_header.code_),
- instance_(_header.instance_) {
+ instance_(_header.instance_), owner_(_header.owner_) {
};
bool message_header_impl::serialize(serializer *_to) const {
diff --git a/implementation/message/src/payload_impl.cpp b/implementation/message/src/payload_impl.cpp index 663a7b8..8920e0c 100644 --- a/implementation/message/src/payload_impl.cpp +++ b/implementation/message/src/payload_impl.cpp @@ -69,7 +69,7 @@ void payload_impl::set_data(std::vector< byte_t > &&_data) { }
bool payload_impl::serialize(serializer *_to) const {
- return (0 != _to && _to->serialize(data_.data(), uint32_t(data_.size())));
+ return (0 != _to && _to->serialize(data_));
}
bool payload_impl::deserialize(deserializer *_from) {
diff --git a/implementation/message/src/serializer.cpp b/implementation/message/src/serializer.cpp index 6c064ab..97ba410 100644 --- a/implementation/message/src/serializer.cpp +++ b/implementation/message/src/serializer.cpp @@ -3,29 +3,28 @@ // 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 <cstring>
+//#include <cstring>
#ifdef VSOMEIP_DEBUGGING
#include <iomanip>
#include <sstream>
-
-#include "../../logging/include/logger.hpp"
#endif
#include <vsomeip/internal/serializable.hpp>
#include "../include/serializer.hpp"
#include "../../utility/include/byteorder.hpp"
+#include "../../logging/include/logger.hpp"
namespace vsomeip {
-serializer::serializer()
- : data_(0), capacity_(0), position_(0), remaining_(0) {
+serializer::serializer(std::uint32_t _buffer_shrink_threshold) :
+ data_(0),
+ shrink_count_(0),
+ buffer_shrink_threshold_(_buffer_shrink_threshold) {
}
serializer::~serializer() {
- if (0 != data_)
- delete [] data_;
};
bool serializer::serialize(const serializable *_from) {
@@ -33,104 +32,90 @@ bool serializer::serialize(const serializable *_from) { }
bool serializer::serialize(const uint8_t _value) {
- if (1 > remaining_)
- return false;
-
- *position_++ = _value;
- remaining_--;
-
+ data_.push_back(_value);
return true;
}
bool serializer::serialize(const uint16_t _value) {
- if (2 > remaining_)
- return false;
-
- *position_++ = VSOMEIP_WORD_BYTE1(_value);
- *position_++ = VSOMEIP_WORD_BYTE0(_value);
- remaining_ -= 2;
-
+ data_.push_back(VSOMEIP_WORD_BYTE1(_value));
+ data_.push_back(VSOMEIP_WORD_BYTE0(_value));
return true;
}
bool serializer::serialize(const uint32_t _value, bool _omit_last_byte) {
- if (3 > remaining_ || (!_omit_last_byte && 4 > remaining_))
- return false;
-
if (!_omit_last_byte) {
- *position_++ = VSOMEIP_LONG_BYTE3(_value);
- remaining_--;
+ data_.push_back(VSOMEIP_LONG_BYTE3(_value));
}
- *position_++ = VSOMEIP_LONG_BYTE2(_value);
- *position_++ = VSOMEIP_LONG_BYTE1(_value);
- *position_++ = VSOMEIP_LONG_BYTE0(_value);
- remaining_ -= 3;
-
+ data_.push_back(VSOMEIP_LONG_BYTE2(_value));
+ data_.push_back(VSOMEIP_LONG_BYTE1(_value));
+ data_.push_back(VSOMEIP_LONG_BYTE0(_value));
return true;
}
bool serializer::serialize(const uint8_t *_data, uint32_t _length) {
- if (_length > remaining_)
+ try {
+ data_.insert(data_.end(), _data, _data + _length);
+ } catch(const std::bad_alloc &e) {
+ VSOMEIP_ERROR << "Couldn't allocate memory in serializer::serialize(*_data, length)" << e.what();
return false;
+ }
+ return true;
+}
- ::memcpy(position_, _data, _length);
- position_ += _length;
- remaining_ -= _length;
-
+bool serializer::serialize(const std::vector<byte_t> &_data) {
+ try {
+ data_.insert(data_.end(),_data.begin(), _data.end());
+ } catch(const std::bad_alloc &e) {
+ VSOMEIP_ERROR << "Couldn't allocate memory in serializer::serialize(vector)" << e.what();
+ return false;
+ }
return true;
}
-byte_t * serializer::get_data() const {
- return data_;
+const byte_t * serializer::get_data() const {
+ return data_.data();
}
uint32_t serializer::get_capacity() const {
- return capacity_;
+ return static_cast<std::uint32_t>(data_.max_size());
}
uint32_t serializer::get_size() const {
- return capacity_ - remaining_;
-}
-
-void serializer::create_data(uint32_t _capacity) {
- if (0 != data_)
- delete [] data_;
-
- data_ = new byte_t[_capacity];
- position_ = data_;
- if (0 != data_) {
- capacity_ = remaining_ = _capacity;
- } else {
- capacity_ = remaining_ = 0;
- }
+ return static_cast<std::uint32_t>(data_.size());
}
void serializer::set_data(byte_t *_data, uint32_t _capacity) {
- delete [] data_;
-
- data_ = _data;
- position_ = _data;
-
- if (0 != data_) {
- capacity_ = remaining_ = _capacity;
- } else {
- capacity_ = remaining_ = 0;
+ data_.clear();
+ try {
+ data_.insert(data_.end(), _data, _data + _capacity);
+ } catch(const std::bad_alloc &e) {
+ VSOMEIP_ERROR << "Couldn't allocate memory in serializer::set_data" << e.what();
}
}
void serializer::reset() {
- position_ = data_;
- remaining_ = capacity_;
+ if (buffer_shrink_threshold_) {
+ if (data_.size() < (data_.capacity() >> 1)) {
+ shrink_count_++;
+ } else {
+ shrink_count_ = 0;
+ }
+ }
+ data_.clear();
+ if (buffer_shrink_threshold_ && shrink_count_ > buffer_shrink_threshold_) {
+ data_.shrink_to_fit();
+ shrink_count_ = 0;
+ }
}
#ifdef VSOMEIP_DEBUGGING
void serializer::show() {
std::stringstream its_data;
its_data << "SERIALIZED: ";
- for (int i = 0; i < position_ - data_; ++i)
+ for (const byte_t& e : data_)
its_data << std::setw(2) << std::setfill('0')
- << std::hex << (int)data_[i];
- VSOMEIP_DEBUG << its_data.str();
+ << std::hex << (int)e;
+ VSOMEIP_INFO << its_data.str();
}
#endif
diff --git a/implementation/routing/include/event.hpp b/implementation/routing/include/event.hpp index ef7e7eb..6e1de4a 100644 --- a/implementation/routing/include/event.hpp +++ b/implementation/routing/include/event.hpp @@ -124,6 +124,7 @@ private: bool is_set_; bool is_provided_; + std::mutex refs_mutex_; std::map<client_t, std::map<bool, uint32_t>> refs_; bool is_shadow_; diff --git a/implementation/routing/include/routing_manager_base.hpp b/implementation/routing/include/routing_manager_base.hpp index a1320ec..75d42c4 100644 --- a/implementation/routing/include/routing_manager_base.hpp +++ b/implementation/routing/include/routing_manager_base.hpp @@ -106,15 +106,17 @@ public: virtual void on_disconnect(std::shared_ptr<endpoint> _endpoint) = 0; virtual void on_message(const byte_t *_data, length_t _length, endpoint *_receiver, const boost::asio::ip::address &_destination - = boost::asio::ip::address(), client_t _bound_client = VSOMEIP_ROUTING_CLIENT) = 0; + = boost::asio::ip::address(), client_t _bound_client = VSOMEIP_ROUTING_CLIENT, + const boost::asio::ip::address &_remote_address = boost::asio::ip::address(), + std::uint16_t _remote_port = 0) = 0; virtual void on_error(const byte_t *_data, length_t _length, - endpoint *_receiver) = 0; + 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 - virtual void on_clientendpoint_error(client_t _client); - virtual void set_routing_state(routing_state_e _routing_state) = 0; protected: @@ -172,6 +174,14 @@ protected: void remove_pending_subscription(service_t _service, instance_t _instance); + void send_pending_notify_ones(service_t _service, instance_t _instance, + eventgroup_t _eventgroup, client_t _client); + +private: + std::shared_ptr<endpoint> create_local_unlocked(client_t _client); + std::shared_ptr<endpoint> find_local_unlocked(client_t _client); + +protected: routing_manager_host *host_; boost::asio::io_service &io_; client_t client_; @@ -227,6 +237,12 @@ private: std::map<client_t, std::shared_ptr<endpoint> > local_endpoints_; mutable std::mutex local_endpoint_mutex_; + + std::map<service_t, + std::map<instance_t, + std::map<eventgroup_t, + std::shared_ptr<message> > > > pending_notify_ones_; + std::mutex pending_notify_ones_mutex_; }; } // namespace vsomeip diff --git a/implementation/routing/include/routing_manager_host.hpp b/implementation/routing/include/routing_manager_host.hpp index 3a60d8c..27a1b1e 100644 --- a/implementation/routing/include/routing_manager_host.hpp +++ b/implementation/routing/include/routing_manager_host.hpp @@ -30,7 +30,7 @@ public: virtual void on_availability(service_t _service, instance_t _instance, bool _is_available, major_version_t _major = DEFAULT_MAJOR, minor_version_t _minor = DEFAULT_MINOR) = 0; virtual void on_state(state_type_e _state) = 0; - virtual void on_message(std::shared_ptr<message> _message) = 0; + virtual void on_message(const std::shared_ptr<message> &&_message) = 0; virtual void on_error(error_code_e _error) = 0; virtual bool on_subscription(service_t _service, instance_t _instance, eventgroup_t _eventgroup, client_t _client, bool _subscribed) = 0; diff --git a/implementation/routing/include/routing_manager_impl.hpp b/implementation/routing/include/routing_manager_impl.hpp index 81c1530..2671566 100644 --- a/implementation/routing/include/routing_manager_impl.hpp +++ b/implementation/routing/include/routing_manager_impl.hpp @@ -21,11 +21,12 @@ #include "routing_manager_base.hpp" #include "routing_manager_stub_host.hpp" + +#include "../../endpoints/include/netlink_connector.hpp" #include "../../service_discovery/include/service_discovery_host.hpp" namespace vsomeip { -class client_endpoint; class configuration; class deserializer; class eventgroupinfo; @@ -130,6 +131,9 @@ public: void on_stop_offer_service(client_t _client, service_t _service, instance_t _instance, major_version_t _major, minor_version_t _minor); + void on_availability(service_t _service, instance_t _instance, + bool _is_available, major_version_t _major, minor_version_t _minor); + void on_pong(client_t _client); // interface "endpoint_host" @@ -138,10 +142,14 @@ public: bool _reliable, client_t _client); void on_connect(std::shared_ptr<endpoint> _endpoint); void on_disconnect(std::shared_ptr<endpoint> _endpoint); - void on_error(const byte_t *_data, length_t _length, endpoint *_receiver); + void on_error(const byte_t *_data, length_t _length, endpoint *_receiver, + const boost::asio::ip::address &_remote_address, + std::uint16_t _remote_port); void on_message(const byte_t *_data, length_t _length, endpoint *_receiver, const boost::asio::ip::address &_destination, - client_t _bound_client); + client_t _bound_client, + const boost::asio::ip::address &_remote_address, + std::uint16_t _remote_port); void on_message(service_t _service, instance_t _instance, const byte_t *_data, length_t _size, bool _reliable); void on_notification(client_t _client, service_t _service, @@ -244,10 +252,16 @@ private: void send_error(return_code_e _return_code, const byte_t *_data, length_t _size, instance_t _instance, bool _reliable, - endpoint *_receiver); + endpoint *_receiver, + const boost::asio::ip::address &_remote_address, + std::uint16_t _remote_port); void identify_for_subscribe(client_t _client, service_t _service, - instance_t _instance, major_version_t _major); + instance_t _instance, major_version_t _major, + subscription_type_e _subscription_type); + bool send_identify_message(client_t _client, service_t _service, + instance_t _instance, major_version_t _major, + bool _reliable); bool supports_selective(service_t _service, instance_t _instance); @@ -276,6 +290,8 @@ private: void remove_identifying_client(service_t _service, instance_t _instance, client_t _client); + void unsubscribe_specific_client_at_sd(service_t _service, instance_t _instance, client_t _client); + inline std::shared_ptr<endpoint> find_local(service_t _service, instance_t _instance) { return routing_manager_base::find_local(_service, _instance); } @@ -284,6 +300,10 @@ private: instance_t _instance, eventgroup_t _eventgroup, major_version_t _major, subscription_type_e _subscription_type); + void on_net_if_state_changed(std::string _if, bool _available); + + void start_ip_routing(); + std::shared_ptr<routing_manager_stub> stub_; std::shared_ptr<sd::service_discovery> discovery_; @@ -330,6 +350,13 @@ private: boost::asio::steady_timer version_log_timer_; + bool if_state_running_; + std::mutex pending_sd_offers_mutex_; + std::vector<std::pair<service_t, instance_t>> pending_sd_offers_; +#ifndef WIN32 + std::shared_ptr<netlink_connector> netlink_connector_; +#endif + #ifndef WITHOUT_SYSTEMD boost::asio::steady_timer watchdog_timer_; void watchdog_cbk(boost::system::error_code const &_error); diff --git a/implementation/routing/include/routing_manager_proxy.hpp b/implementation/routing/include/routing_manager_proxy.hpp index 33c6c26..b3ae769 100644 --- a/implementation/routing/include/routing_manager_proxy.hpp +++ b/implementation/routing/include/routing_manager_proxy.hpp @@ -83,8 +83,12 @@ public: void on_disconnect(std::shared_ptr<endpoint> _endpoint); void on_message(const byte_t *_data, length_t _length, endpoint *_receiver, const boost::asio::ip::address &_destination, - client_t _bound_client); - void on_error(const byte_t *_data, length_t _length, endpoint *_receiver); + client_t _bound_client, + const boost::asio::ip::address &_remote_address, + std::uint16_t _remote_port); + void on_error(const byte_t *_data, length_t _length, endpoint *_receiver, + const boost::asio::ip::address &_remote_address, + std::uint16_t _remote_port); void release_port(uint16_t _port, bool _reliable); void on_routing_info(const byte_t *_data, uint32_t _size); diff --git a/implementation/routing/include/routing_manager_stub.hpp b/implementation/routing/include/routing_manager_stub.hpp index f1e657a..9cc0255 100644 --- a/implementation/routing/include/routing_manager_stub.hpp +++ b/implementation/routing/include/routing_manager_stub.hpp @@ -44,8 +44,12 @@ public: void on_disconnect(std::shared_ptr<endpoint> _endpoint); void on_message(const byte_t *_data, length_t _length, endpoint *_receiver, const boost::asio::ip::address &_destination, - client_t _bound_client); - void on_error(const byte_t *_data, length_t _length, endpoint *_receiver); + client_t _bound_client, + const boost::asio::ip::address &_remote_address, + std::uint16_t _remote_port); + void on_error(const byte_t *_data, length_t _length, endpoint *_receiver, + const boost::asio::ip::address &_remote_address, + std::uint16_t _remote_port); void release_port(uint16_t _port, bool _reliable); void on_offer_service(client_t _client, service_t _service, @@ -75,6 +79,7 @@ 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; #ifndef WIN32 @@ -133,6 +138,7 @@ private: 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_; const std::chrono::milliseconds configured_watchdog_timeout_; boost::asio::steady_timer pinged_clients_timer_; diff --git a/implementation/routing/include/routing_manager_stub_host.hpp b/implementation/routing/include/routing_manager_stub_host.hpp index aa8fe02..65bb28b 100644 --- a/implementation/routing/include/routing_manager_stub_host.hpp +++ b/implementation/routing/include/routing_manager_stub_host.hpp @@ -63,6 +63,9 @@ public: instance_t _instance, major_version_t _major, minor_version_t _minor) = 0; + virtual void on_availability(service_t _service, instance_t _instance, + bool _is_available, major_version_t _major, minor_version_t _minor) = 0; + virtual std::shared_ptr<endpoint> find_local(client_t _client) = 0; virtual std::shared_ptr<endpoint> find_or_create_local( diff --git a/implementation/routing/src/event.cpp b/implementation/routing/src/event.cpp index 653f262..b6947d0 100644 --- a/implementation/routing/src/event.cpp +++ b/implementation/routing/src/event.cpp @@ -118,7 +118,7 @@ void event::set_payload(const std::shared_ptr<payload> &_payload, } } } else { - VSOMEIP_DEBUG << "Can't set payload for event " << std::hex + VSOMEIP_INFO << "Can't set payload for event " << std::hex << message_->get_method() << " as it isn't provided"; } } @@ -134,7 +134,7 @@ void event::set_payload(const std::shared_ptr<payload> &_payload, client_t _clie } } } else { - VSOMEIP_DEBUG << "Can't set payload for event " << std::hex + VSOMEIP_INFO << "Can't set payload for event " << std::hex << message_->get_method() << " as it isn't provided"; } } @@ -151,7 +151,7 @@ void event::set_payload(const std::shared_ptr<payload> &_payload, } } } else { - VSOMEIP_DEBUG << "Can't set payload for event " << std::hex + VSOMEIP_INFO << "Can't set payload for event " << std::hex << message_->get_method() << " as it isn't provided"; } } @@ -221,7 +221,7 @@ void event::notify(bool _flush) { if (is_set_) { routing_->send(VSOMEIP_ROUTING_CLIENT, message_, _flush); } else { - VSOMEIP_DEBUG << "Notify event " << std::hex << message_->get_method() + VSOMEIP_INFO << "Notify event " << std::hex << message_->get_method() << "failed. Event payload not set!"; } } @@ -230,7 +230,7 @@ void event::notify_one(const std::shared_ptr<endpoint_definition> &_target, bool if (is_set_) { routing_->send_to(_target, message_, _flush); } else { - VSOMEIP_DEBUG << "Notify one event " << std::hex << message_->get_method() + VSOMEIP_INFO << "Notify one event " << std::hex << message_->get_method() << "failed. Event payload not set!"; } } @@ -239,7 +239,7 @@ void event::notify_one(client_t _client, bool _flush) { if (is_set_) { routing_->send(_client, message_, _flush); } else { - VSOMEIP_DEBUG << "Notify one event " << std::hex << message_->get_method() + VSOMEIP_INFO << "Notify one event " << std::hex << message_->get_method() << " to client " << _client << " failed. Event payload not set!"; } } @@ -266,6 +266,7 @@ void event::reset_payload(const std::shared_ptr<payload> &_payload) { } void event::add_ref(client_t _client, bool _is_provided) { + std::lock_guard<std::mutex> its_lock(refs_mutex_); auto its_client = refs_.find(_client); if (its_client == refs_.end()) { refs_[_client][_is_provided] = 1; @@ -280,6 +281,7 @@ void event::add_ref(client_t _client, bool _is_provided) { } void event::remove_ref(client_t _client, bool _is_provided) { + std::lock_guard<std::mutex> its_lock(refs_mutex_); auto its_client = refs_.find(_client); if (its_client != refs_.end()) { auto its_provided = its_client->second.find(_is_provided); @@ -296,6 +298,7 @@ void event::remove_ref(client_t _client, bool _is_provided) { } bool event::has_ref() { + std::lock_guard<std::mutex> its_lock(refs_mutex_); return refs_.size() != 0; } diff --git a/implementation/routing/src/eventgroupinfo.cpp b/implementation/routing/src/eventgroupinfo.cpp index fd63c4d..3b3e657 100644 --- a/implementation/routing/src/eventgroupinfo.cpp +++ b/implementation/routing/src/eventgroupinfo.cpp @@ -14,11 +14,11 @@ namespace vsomeip { eventgroupinfo::eventgroupinfo() - : major_(DEFAULT_MAJOR), ttl_(DEFAULT_TTL) { + : major_(DEFAULT_MAJOR), ttl_(DEFAULT_TTL), port_(ILLEGAL_PORT), threshold_(0) { } eventgroupinfo::eventgroupinfo(major_version_t _major, ttl_t _ttl) - : major_(_major), ttl_(_ttl) { + : major_(_major), ttl_(_ttl), port_(ILLEGAL_PORT), threshold_(0) { } eventgroupinfo::~eventgroupinfo() { diff --git a/implementation/routing/src/routing_manager_base.cpp b/implementation/routing/src/routing_manager_base.cpp index 89a5843..751a588 100644 --- a/implementation/routing/src/routing_manager_base.cpp +++ b/implementation/routing/src/routing_manager_base.cpp @@ -5,6 +5,8 @@ #include <iomanip> +#include <vsomeip/runtime.hpp> + #include "../../utility/include/utility.hpp" #include "../../utility/include/byteorder.hpp" #include "../include/routing_manager_base.hpp" @@ -20,13 +22,18 @@ routing_manager_base::routing_manager_base(routing_manager_host *_host) : io_(host_->get_io()), client_(host_->get_client()), configuration_(host_->get_configuration()), - serializer_(std::make_shared<serializer>()) + serializer_( + std::make_shared<serializer>( + configuration_->get_buffer_shrink_threshold())) #ifdef USE_DLT , tc_(tc::trace_connector::get()) #endif { + const uint32_t its_buffer_shrink_threshold = + configuration_->get_buffer_shrink_threshold(); for (int i = 0; i < VSOMEIP_MAX_DESERIALIZER; ++i) { - deserializers_.push(std::make_shared<deserializer>()); + deserializers_.push( + std::make_shared<deserializer>(its_buffer_shrink_threshold)); } } @@ -42,7 +49,6 @@ client_t routing_manager_base::get_client() const { } void routing_manager_base::init() { - serializer_->create_data(configuration_->get_max_message_size_local()); } bool routing_manager_base::offer_service(client_t _client, service_t _service, @@ -74,6 +80,7 @@ void routing_manager_base::stop_offer_service(client_t _client, service_t _servi (void)_client; (void)_major; (void)_minor; + std::map<event_t, std::shared_ptr<event> > events; { std::lock_guard<std::mutex> its_lock(events_mutex_); auto its_events_service = events_.find(_service); @@ -81,10 +88,14 @@ void routing_manager_base::stop_offer_service(client_t _client, service_t _servi auto its_events_instance = its_events_service->second.find(_instance); if (its_events_instance != its_events_service->second.end()) { for (auto &e : its_events_instance->second) - e.second->unset_payload(); + events[e.first] = e.second; + } } } + for (auto &e : events) { + e.second->unset_payload(); + } { std::lock_guard<std::mutex> its_lock(eventgroup_clients_mutex_); auto its_service = eventgroup_clients_.find(_service); @@ -346,6 +357,8 @@ void routing_manager_base::notify_one(service_t _service, instance_t _instance, if (its_event) { // Event is valid for service/instance bool found_eventgroup(false); + bool already_subscribed(false); + eventgroup_t valid_group = 0; // Iterate over all groups of the event to ensure at least // one valid eventgroup for service/instance exists. for (auto its_group : its_event->get_eventgroups()) { @@ -353,11 +366,48 @@ void routing_manager_base::notify_one(service_t _service, instance_t _instance, if (its_eventgroup) { // Eventgroup is valid for service/instance found_eventgroup = true; + valid_group = its_group; + if (find_local(_client)) { + std::lock_guard<std::mutex> its_lock(eventgroup_clients_mutex_); + auto its_service = eventgroup_clients_.find(_service); + if (its_service != eventgroup_clients_.end()) { + auto its_instance = its_service->second.find(_instance); + if (its_instance != its_service->second.end()) { + auto found_eventgroup = its_instance->second.find(its_group); + if (found_eventgroup != its_instance->second.end()) { + auto its_client = found_eventgroup->second.find(_client); + if (its_client != found_eventgroup->second.end()) { + already_subscribed = true; + } + } + } + } + } else { + // Remotes always needs to be marked as subscribed here + already_subscribed = true; + } break; } } if (found_eventgroup) { - its_event->set_payload(_payload, _client, _force, _flush); + if (already_subscribed) { + its_event->set_payload(_payload, _client, _force, _flush); + } else { + std::shared_ptr<message> its_notification + = runtime::get()->create_notification(); + its_notification->set_service(_service); + its_notification->set_instance(_instance); + its_notification->set_method(_event); + its_notification->set_payload(_payload); + auto service_info = find_service(_service, _instance); + if (service_info) { + its_notification->set_interface_version(service_info->get_major()); + } + { + std::lock_guard<std::mutex> its_lock(pending_notify_ones_mutex_); + pending_notify_ones_[_service][_instance][valid_group] = its_notification; + } + } } } else { VSOMEIP_WARNING << "Attempt to update the undefined event/field [" @@ -366,6 +416,23 @@ void routing_manager_base::notify_one(service_t _service, instance_t _instance, } } +void routing_manager_base::send_pending_notify_ones(service_t _service, instance_t _instance, + eventgroup_t _eventgroup, client_t _client) { + std::lock_guard<std::mutex> its_lock(pending_notify_ones_mutex_); + auto its_service = pending_notify_ones_.find(_service); + if (its_service != pending_notify_ones_.end()) { + auto its_instance = its_service->second.find(_instance); + if (its_instance != its_service->second.end()) { + auto its_group = its_instance->second.find(_eventgroup); + if (its_group != its_instance->second.end()) { + notify_one(_service, _instance, its_group->second->get_method(), + its_group->second->get_payload(), _client, false, true); + its_instance->second.erase(_eventgroup); + } + } + } +} + bool routing_manager_base::send(client_t its_client, std::shared_ptr<message> _message, bool _flush) { @@ -472,19 +539,17 @@ client_t routing_manager_base::find_local_client(service_t _service, instance_t return its_client; } -std::shared_ptr<endpoint> routing_manager_base::create_local(client_t _client) { - std::lock_guard<std::mutex> its_lock(local_endpoint_mutex_); - +std::shared_ptr<endpoint> routing_manager_base::create_local_unlocked(client_t _client) { std::stringstream its_path; its_path << VSOMEIP_BASE_PATH << std::hex << _client; #ifdef WIN32 boost::asio::ip::address address = boost::asio::ip::address::from_string("127.0.0.1"); int port = VSOMEIP_INTERNAL_BASE_PORT + _client; - VSOMEIP_DEBUG<< "Connecting to [" + VSOMEIP_INFO << "Connecting to [" << std::hex << _client << "] at " << port; #else - VSOMEIP_DEBUG << "Client [" << std::hex << get_client() << "] is connecting to [" + VSOMEIP_INFO << "Client [" << std::hex << get_client() << "] is connecting to [" << std::hex << _client << "] at " << its_path.str(); #endif std::shared_ptr<local_client_endpoint_impl> its_endpoint = std::make_shared< @@ -501,24 +566,25 @@ std::shared_ptr<endpoint> routing_manager_base::create_local(client_t _client) { // 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); - if (routing_manager_impl *rm_impl = dynamic_cast<routing_manager_impl*>(this)) { - its_endpoint->register_error_callback( + + 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, - rm_impl, _client)); - } else { - its_endpoint->register_error_callback( - std::bind(&routing_manager_base::on_clientendpoint_error, this, - _client)); + its_manager, _client)); } } return (its_endpoint); } -std::shared_ptr<endpoint> routing_manager_base::find_local(client_t _client) { +std::shared_ptr<endpoint> routing_manager_base::create_local(client_t _client) { std::lock_guard<std::mutex> its_lock(local_endpoint_mutex_); + return create_local_unlocked(_client); +} + +std::shared_ptr<endpoint> routing_manager_base::find_local_unlocked(client_t _client) { std::shared_ptr<endpoint> its_endpoint; auto found_endpoint = local_endpoints_.find(_client); if (found_endpoint != local_endpoints_.end()) { @@ -527,10 +593,16 @@ std::shared_ptr<endpoint> routing_manager_base::find_local(client_t _client) { return (its_endpoint); } +std::shared_ptr<endpoint> routing_manager_base::find_local(client_t _client) { + std::lock_guard<std::mutex> its_lock(local_endpoint_mutex_); + return find_local_unlocked(_client); +} + std::shared_ptr<endpoint> routing_manager_base::find_or_create_local(client_t _client) { - std::shared_ptr<endpoint> its_endpoint(find_local(_client)); + std::lock_guard<std::mutex> its_lock(local_endpoint_mutex_); + std::shared_ptr<endpoint> its_endpoint(find_local_unlocked(_client)); if (!its_endpoint) { - its_endpoint = create_local(_client); + its_endpoint = create_local_unlocked(_client); its_endpoint->start(); } return (its_endpoint); @@ -540,7 +612,7 @@ void routing_manager_base::remove_local(client_t _client) { std::shared_ptr<endpoint> its_endpoint(find_local(_client)); if (its_endpoint) { its_endpoint->stop(); - VSOMEIP_DEBUG << "Client [" << std::hex << get_client() << "] is closing connection to [" + VSOMEIP_INFO << "Client [" << std::hex << get_client() << "] is closing connection to [" << std::hex << _client << "]"; std::lock_guard<std::mutex> its_lock(local_endpoint_mutex_); local_endpoints_.erase(_client); @@ -743,7 +815,7 @@ bool routing_manager_base::send_local_notification(client_t _client, #ifdef USE_DLT // Trace the message if a local client but will _not_ be forwarded to the routing manager if (has_local && !has_remote) { - uint16_t its_data_size + const uint16_t its_data_size = uint16_t(_size > USHRT_MAX ? USHRT_MAX : _size); tc::trace_header its_header; @@ -759,19 +831,18 @@ bool routing_manager_base::send_local( std::shared_ptr<endpoint>& _target, client_t _client, const byte_t *_data, uint32_t _size, instance_t _instance, bool _flush, bool _reliable, uint8_t _command) const { - + std::size_t its_complete_size = _size + sizeof(instance_t) + + sizeof(bool) + sizeof(bool); client_t sender = get_client(); - size_t additional_size = 0; if (_command == VSOMEIP_NOTIFY_ONE) { - additional_size +=sizeof(client_t); + its_complete_size +=sizeof(client_t); } std::vector<byte_t> its_command( - VSOMEIP_COMMAND_HEADER_SIZE + _size + sizeof(instance_t) - + sizeof(bool) + sizeof(bool) + additional_size); + VSOMEIP_COMMAND_HEADER_SIZE + its_complete_size); its_command[VSOMEIP_COMMAND_TYPE_POS] = _command; std::memcpy(&its_command[VSOMEIP_COMMAND_CLIENT_POS], &sender, sizeof(client_t)); - std::memcpy(&its_command[VSOMEIP_COMMAND_SIZE_POS_MIN], &_size, + std::memcpy(&its_command[VSOMEIP_COMMAND_SIZE_POS_MIN], &its_complete_size, sizeof(_size)); std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS], _data, _size); @@ -811,12 +882,6 @@ bool routing_manager_base::insert_subscription( return true; } -void routing_manager_base::on_clientendpoint_error(client_t _client) { - VSOMEIP_ERROR << "Client endpoint error for application: " << std::hex - << std::setfill('0') << std::setw(4) << _client; - remove_local(_client); -} - std::shared_ptr<deserializer> routing_manager_base::get_deserializer() { std::unique_lock<std::mutex> its_lock(deserializer_mutex_); while (deserializers_.empty()) { diff --git a/implementation/routing/src/routing_manager_impl.cpp b/implementation/routing/src/routing_manager_impl.cpp index 7a27e4e..c1daec7 100644 --- a/implementation/routing/src/routing_manager_impl.cpp +++ b/implementation/routing/src/routing_manager_impl.cpp @@ -47,7 +47,8 @@ namespace vsomeip { routing_manager_impl::routing_manager_impl(routing_manager_host *_host) : routing_manager_base(_host), - version_log_timer_(_host->get_io()) + version_log_timer_(_host->get_io()), + if_state_running_(false) #ifndef WITHOUT_SYSTEMD , watchdog_timer_(_host->get_io()) #endif @@ -87,16 +88,22 @@ void routing_manager_impl::init() { discovery_ = (*its_runtime)->create_service_discovery(this); discovery_->init(); } - } else { - init_routing_info(); // Static routing } } void routing_manager_impl::start() { - stub_->start(); - if (discovery_) - discovery_->start(); +#ifndef WIN32 + netlink_connector_ = std::make_shared<netlink_connector>(host_->get_io(), + configuration_->get_unicast_address()); + netlink_connector_->register_net_if_changes_handler( + std::bind(&routing_manager_impl::on_net_if_state_changed, + this, std::placeholders::_1, std::placeholders::_2)); + netlink_connector_->start(); +#else + start_ip_routing(); +#endif + stub_->start(); host_->on_state(state_type_e::ST_REGISTERED); if (configuration_->log_version()) { @@ -115,6 +122,11 @@ void routing_manager_impl::start() { void routing_manager_impl::stop() { version_log_timer_.cancel(); +#ifndef WIN32 + if (netlink_connector_) { + netlink_connector_->stop(); + } +#endif #ifndef WITHOUT_SYSTEMD watchdog_timer_.cancel(); @@ -136,7 +148,7 @@ void routing_manager_impl::stop() { bool routing_manager_impl::offer_service(client_t _client, service_t _service, instance_t _instance, major_version_t _major, minor_version_t _minor) { - VSOMEIP_DEBUG << "OFFER(" + VSOMEIP_INFO << "OFFER(" << 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') << _instance @@ -146,7 +158,14 @@ bool routing_manager_impl::offer_service(client_t _client, service_t _service, return false; } - init_service_info(_service, _instance, true); + { + std::lock_guard<std::mutex> its_lock(pending_sd_offers_mutex_); + if (if_state_running_) { + init_service_info(_service, _instance, true); + } else { + pending_sd_offers_.push_back(std::make_pair(_service, _instance)); + } + } { std::lock_guard<std::mutex> its_lock(events_mutex_); @@ -181,7 +200,7 @@ bool routing_manager_impl::offer_service(client_t _client, service_t _service, send_pending_subscriptions(_service, _instance, _major); } stub_->on_offer_service(_client, _service, _instance, _major, _minor); - host_->on_availability(_service, _instance, true, _major, _minor); + on_availability(_service, _instance, true, _major, _minor); return true; } @@ -189,23 +208,35 @@ void routing_manager_impl::stop_offer_service(client_t _client, service_t _service, instance_t _instance, major_version_t _major, minor_version_t _minor) { - VSOMEIP_DEBUG << "STOP OFFER(" + VSOMEIP_INFO << "STOP OFFER(" << 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') << _instance << ":" << std::dec << int(_major) << "." << _minor << "]"; + { + std::lock_guard<std::mutex> its_lock(pending_sd_offers_mutex_); + for (auto it = pending_sd_offers_.begin(); it != pending_sd_offers_.end(); ) { + if (it->first == _service && it->second == _instance) { + it = pending_sd_offers_.erase(it); + break; + } else { + ++it; + } + } + } + routing_manager_base::stop_offer_service(_client, _service, _instance, _major, _minor); on_stop_offer_service(_client, _service, _instance, _major, _minor); stub_->on_stop_offer_service(_client, _service, _instance, _major, _minor); - host_->on_availability(_service, _instance, false, _major, _minor); + on_availability(_service, _instance, false, _major, _minor); } void routing_manager_impl::request_service(client_t _client, service_t _service, instance_t _instance, major_version_t _major, minor_version_t _minor, bool _use_exclusive_proxy) { - VSOMEIP_DEBUG << "REQUEST(" + VSOMEIP_INFO << "REQUEST(" << 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') << _instance << ":" @@ -226,7 +257,7 @@ void routing_manager_impl::request_service(client_t _client, service_t _service, discovery_->request_service(_service, _instance, _major, _minor, DEFAULT_TTL); } else { - VSOMEIP_DEBUG << std::hex + VSOMEIP_INFO << std::hex << "Avoid trigger SD find-service message" << " for local service/instance/major/minor: " << _service << "/" << _instance << std::dec @@ -269,7 +300,7 @@ void routing_manager_impl::request_service(client_t _client, service_t _service, void routing_manager_impl::release_service(client_t _client, service_t _service, instance_t _instance) { - VSOMEIP_DEBUG << "RELEASE(" + VSOMEIP_INFO << "RELEASE(" << 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') << _instance << "]"; @@ -292,9 +323,11 @@ void routing_manager_impl::release_service(client_t _client, service_t _service, std::shared_ptr<serviceinfo> its_info(find_service(_service, _instance)); if(its_info && !its_info->is_local()) { + unsubscribe_specific_client_at_sd(_service, _instance, _client); if(!its_info->get_requesters_size()) { if(discovery_) { discovery_->release_service(_service, _instance); + discovery_->unsubscribe_client(_service, _instance, VSOMEIP_ROUTING_CLIENT); } clear_client_endpoints(_service, _instance, true); clear_client_endpoints(_service, _instance, false); @@ -319,7 +352,7 @@ void routing_manager_impl::subscribe(client_t _client, service_t _service, instance_t _instance, eventgroup_t _eventgroup, major_version_t _major, subscription_type_e _subscription_type) { - VSOMEIP_DEBUG << "SUBSCRIBE(" + VSOMEIP_INFO << "SUBSCRIBE(" << 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') << _instance << "." @@ -339,6 +372,7 @@ void routing_manager_impl::subscribe(client_t _client, service_t _service, stub_->send_subscribe_ack(_client, _service, _instance, _eventgroup); } routing_manager_base::subscribe(_client, _service, _instance, _eventgroup, _major, _subscription_type); + send_pending_notify_ones(_service, _instance, _eventgroup, _client); } else { if (discovery_) { client_t subscriber = VSOMEIP_ROUTING_CLIENT; @@ -365,7 +399,7 @@ void routing_manager_impl::subscribe(client_t _client, service_t _service, } } if(identify) { - identify_for_subscribe(_client, _service, _instance, _major); + identify_for_subscribe(_client, _service, _instance, _major, _subscription_type); } } bool inserted = insert_subscription(_service, _instance, _eventgroup, _client); @@ -404,7 +438,7 @@ void routing_manager_impl::subscribe(client_t _client, service_t _service, void routing_manager_impl::unsubscribe(client_t _client, service_t _service, instance_t _instance, eventgroup_t _eventgroup) { - VSOMEIP_DEBUG << "UNSUBSCRIBE(" + VSOMEIP_INFO << "UNSUBSCRIBE(" << 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') << _instance << "." @@ -447,8 +481,14 @@ void routing_manager_impl::unsubscribe(client_t _client, service_t _service, } } } - if( last_subscriber_removed ) + if (subscriber == VSOMEIP_ROUTING_CLIENT && last_subscriber_removed) { + // for normal subscribers only unsubscribe via SD if last + // subscriber was removed + discovery_->unsubscribe(_service, _instance, _eventgroup, subscriber); + } else if (subscriber != VSOMEIP_ROUTING_CLIENT) { + // for selective subscribers always unsubscribe at the SD discovery_->unsubscribe(_service, _instance, _eventgroup, subscriber); + } } else { stub_->send_unsubscribe(find_local(_service, _instance), _client, _service, _instance, _eventgroup, false); @@ -493,7 +533,7 @@ bool routing_manager_impl::send(client_t _client, const byte_t *_data, } else if (is_notification && _client) { // Selective notifications! if (_client == get_client()) { #ifdef USE_DLT - uint16_t its_data_size + const uint16_t its_data_size = uint16_t(_size > USHRT_MAX ? USHRT_MAX : _size); tc::trace_header its_header; @@ -509,7 +549,7 @@ bool routing_manager_impl::send(client_t _client, const byte_t *_data, if (its_target) { #ifdef USE_DLT - uint16_t its_data_size + const uint16_t its_data_size = uint16_t(_size > USHRT_MAX ? USHRT_MAX : _size); tc::trace_header its_header; @@ -545,7 +585,7 @@ bool routing_manager_impl::send(client_t _client, const byte_t *_data, its_target = find_or_create_remote_client(its_service, _instance, _reliable, client); if (its_target) { #ifdef USE_DLT - uint16_t its_data_size + const uint16_t its_data_size = uint16_t(_size > USHRT_MAX ? USHRT_MAX : _size); tc::trace_header its_header; @@ -600,7 +640,7 @@ bool routing_manager_impl::send(client_t _client, const byte_t *_data, } #ifdef USE_DLT if (has_sent) { - uint16_t its_data_size + const uint16_t its_data_size = uint16_t(_size > USHRT_MAX ? USHRT_MAX : _size); tc::trace_header its_header; @@ -618,7 +658,7 @@ bool routing_manager_impl::send(client_t _client, const byte_t *_data, (sd_info_ ? sd_info_->get_endpoint(false) : nullptr) : its_info->get_endpoint(_reliable); if (its_target) { #ifdef USE_DLT - uint16_t its_data_size + const uint16_t its_data_size = uint16_t(_size > USHRT_MAX ? USHRT_MAX : _size); tc::trace_header its_header; @@ -671,7 +711,7 @@ bool routing_manager_impl::send_to( if (its_endpoint) { #ifdef USE_DLT - uint16_t its_data_size + const uint16_t its_data_size = uint16_t(_size > USHRT_MAX ? USHRT_MAX : _size); tc::trace_header its_header; @@ -691,7 +731,7 @@ bool routing_manager_impl::send_to(const std::shared_ptr<endpoint_definition> &_ if (its_endpoint) { #ifdef USE_DLT - uint16_t its_data_size + const uint16_t its_data_size = uint16_t(_size > USHRT_MAX ? USHRT_MAX : _size); tc::trace_header its_header; @@ -782,15 +822,23 @@ void routing_manager_impl::notify_one(service_t _service, instance_t _instance, } } -void routing_manager_impl::on_error(const byte_t *_data, length_t _length, endpoint *_receiver) { +void routing_manager_impl::on_availability(service_t _service, instance_t _instance, + bool _is_available, major_version_t _major, minor_version_t _minor) { + host_->on_availability(_service, _instance, _is_available, _major, _minor); +} + +void routing_manager_impl::on_error( + const byte_t *_data, length_t _length, endpoint *_receiver, + const boost::asio::ip::address &_remote_address, + std::uint16_t _remote_port) { instance_t its_instance = 0; if (_length >= VSOMEIP_SERVICE_POS_MAX) { service_t its_service = VSOMEIP_BYTES_TO_WORD( _data[VSOMEIP_SERVICE_POS_MIN], _data[VSOMEIP_SERVICE_POS_MAX]); its_instance = find_instance(its_service, _receiver); } - send_error(return_code_e::E_MALFORMED_MESSAGE, _data, _length, - its_instance, _receiver->is_reliable(), _receiver); + send_error(return_code_e::E_MALFORMED_MESSAGE, _data, _length, its_instance, + _receiver->is_reliable(), _receiver, _remote_address, _remote_port); } void routing_manager_impl::release_port(uint16_t _port, bool _reliable) { @@ -800,13 +848,15 @@ void routing_manager_impl::release_port(uint16_t _port, bool _reliable) { void routing_manager_impl::on_message(const byte_t *_data, length_t _size, endpoint *_receiver, const boost::asio::ip::address &_destination, - client_t _bound_client) { + client_t _bound_client, + const boost::asio::ip::address &_remote_address, + std::uint16_t _remote_port) { #if 0 std::stringstream msg; msg << "rmi::on_message: "; for (uint32_t i = 0; i < _size; ++i) msg << std::hex << std::setw(2) << std::setfill('0') << (int)_data[i] << " "; - VSOMEIP_DEBUG << msg.str(); + VSOMEIP_INFO << msg.str(); #endif (void)_bound_client; service_t its_service; @@ -818,16 +868,15 @@ void routing_manager_impl::on_message(const byte_t *_data, length_t _size, its_method = VSOMEIP_BYTES_TO_WORD(_data[VSOMEIP_METHOD_POS_MIN], _data[VSOMEIP_METHOD_POS_MAX]); if (discovery_ && its_method == sd::method) { - if (configuration_->get_sd_port() == _receiver->get_remote_port()) { - boost::asio::ip::address its_address; - if (_receiver->get_remote_address(its_address)) { - discovery_->on_message(_data, _size, its_address, _destination); + if (configuration_->get_sd_port() == _remote_port) { + if (!_remote_address.is_unspecified()) { + discovery_->on_message(_data, _size, _remote_address, _destination); } else { VSOMEIP_ERROR << "Ignored SD message from unknown address."; } } else { VSOMEIP_ERROR << "Ignored SD message from unknown port (" - << _receiver->get_remote_port() << ")"; + << _remote_port << ")"; } } } else { @@ -843,7 +892,8 @@ void routing_manager_impl::on_message(const byte_t *_data, length_t _size, if(!(_size >= VSOMEIP_MESSAGE_TYPE_POS && utility::is_request_no_return(_data[VSOMEIP_MESSAGE_TYPE_POS]))) { if (return_code != return_code_e::E_OK && return_code != return_code_e::E_NOT_OK) { send_error(return_code, _data, _size, its_instance, - _receiver->is_reliable(), _receiver); + _receiver->is_reliable(), _receiver, + _remote_address, _remote_port); return; } } else if(return_code != return_code_e::E_OK && return_code != return_code_e::E_NOT_OK) { @@ -893,13 +943,20 @@ void routing_manager_impl::on_message(const byte_t *_data, length_t _size, } } #ifdef USE_DLT - uint16_t its_data_size + const uint16_t its_data_size = uint16_t(_size > USHRT_MAX ? USHRT_MAX : _size); tc::trace_header its_header; - if (its_header.prepare(_receiver, false)) - tc_->trace(its_header.data_, VSOMEIP_TRACE_HEADER_SIZE, - _data, its_data_size); + const boost::asio::ip::address_v4 its_remote_address = + _remote_address.is_v4() ? _remote_address.to_v4() : + boost::asio::ip::address_v4::from_string("6.6.6.6"); + tc::protocol_e its_protocol = + _receiver->is_local() ? tc::protocol_e::local : + _receiver->is_reliable() ? tc::protocol_e::tcp : + tc::protocol_e::udp; + its_header.prepare(its_remote_address, _remote_port, its_protocol, false); + tc_->trace(its_header.data_, VSOMEIP_TRACE_HEADER_SIZE, _data, + its_data_size); #endif } @@ -914,7 +971,7 @@ void routing_manager_impl::on_message( << _service << ", " << _instance << "): "; for (uint32_t i = 0; i < _size; ++i) msg << std::hex << std::setw(2) << std::setfill('0') << (int)_data[i] << " "; - VSOMEIP_DEBUG << msg.str(); + VSOMEIP_INFO << msg.str(); #endif client_t its_client; @@ -1031,8 +1088,7 @@ void routing_manager_impl::on_connect(std::shared_ptr<endpoint> _endpoint) { } } for (const auto &s : services_to_report_) { - host_->on_availability(s.service_id_, s.instance_id_, true, s.major_, - s.minor_); + on_availability(s.service_id_, s.instance_id_, true, s.major_, s.minor_); if (s.reliable_) { stub_->on_offer_service(VSOMEIP_ROUTING_CLIENT, s.service_id_, s.instance_id_, s.major_, s.minor_); @@ -1060,7 +1116,7 @@ void routing_manager_impl::on_disconnect(std::shared_ptr<endpoint> _endpoint) { if(!its_info){ return; } - host_->on_availability(its_service.first, its_instance.first, + on_availability(its_service.first, its_instance.first, false, its_info->get_major(), its_info->get_minor()); } } @@ -1072,7 +1128,7 @@ void routing_manager_impl::on_disconnect(std::shared_ptr<endpoint> _endpoint) { if(!its_info){ return; } - host_->on_availability(its_service.first, its_instance.first, + on_availability(its_service.first, its_instance.first, false, its_info->get_major(), its_info->get_minor()); } } @@ -1119,17 +1175,22 @@ void routing_manager_impl::on_stop_offer_service(client_t _client, service_t _se } } } + std::map<event_t, std::shared_ptr<event> > events; { - std::lock_guard<std::mutex> its_lock(events_mutex_); + std::unique_lock<std::mutex> its_lock(events_mutex_); auto its_events_service = events_.find(_service); if (its_events_service != events_.end()) { auto its_events_instance = its_events_service->second.find(_instance); if (its_events_instance != its_events_service->second.end()) { - for (auto &e : its_events_instance->second) - e.second->unset_payload(); + for (auto &e : its_events_instance->second) { + events[e.first] = e.second; + } } } } + for (auto &e : events) { + e.second->unset_payload(); + } { std::lock_guard<std::mutex> its_lock(eventgroup_clients_mutex_); auto its_service = eventgroup_clients_.find(_service); @@ -1236,7 +1297,7 @@ bool routing_manager_impl::deliver_message(const byte_t *_data, length_t _size, if (its_message) { its_message->set_instance(_instance); its_message->set_reliable(_reliable); - host_->on_message(its_message); + host_->on_message(std::move(its_message)); is_delivered = true; } else { VSOMEIP_ERROR << "Routing manager: deliver_message: " @@ -1305,18 +1366,25 @@ std::shared_ptr<endpoint> routing_manager_impl::create_service_discovery_endpoin std::shared_ptr<endpoint> its_service_endpoint = find_server_endpoint(_port, _reliable); if (!its_service_endpoint) { - its_service_endpoint = create_server_endpoint(_port, _reliable, true); - - if (its_service_endpoint) { - sd_info_ = std::make_shared<serviceinfo>(ANY_MAJOR, ANY_MINOR, DEFAULT_TTL, - false); // false, because we do _not_ want to announce it... - sd_info_->set_endpoint(its_service_endpoint, _reliable); - its_service_endpoint->add_default_target(VSOMEIP_SD_SERVICE, - _address, _port); - its_service_endpoint->join(_address); - } else { - VSOMEIP_ERROR << "Service Discovery endpoint could not be created. " - "Please check your network configuration."; + try { + its_service_endpoint = create_server_endpoint(_port, _reliable, + true); + + if (its_service_endpoint) { + sd_info_ = std::make_shared<serviceinfo>(ANY_MAJOR, ANY_MINOR, + DEFAULT_TTL, false); // false, because we do _not_ want to announce it... + sd_info_->set_endpoint(its_service_endpoint, _reliable); + its_service_endpoint->add_default_target(VSOMEIP_SD_SERVICE, + _address, _port); + its_service_endpoint->join(_address); + } else { + VSOMEIP_ERROR<< "Service Discovery endpoint could not be created. " + "Please check your network configuration."; + } + } catch (const std::exception &e) { + host_->on_error(error_code_e::SERVER_ENDPOINT_CREATION_FAILED); + VSOMEIP_ERROR << "Service Discovery endpoint could not be created: " + << e.what(); } } return its_service_endpoint; @@ -1398,7 +1466,7 @@ void routing_manager_impl::init_service_info( if (ILLEGAL_PORT == its_reliable_port && ILLEGAL_PORT == its_unreliable_port) { - VSOMEIP_DEBUG << "Port configuration missing for [" + VSOMEIP_INFO << "Port configuration missing for [" << std::hex << _service << "." << _instance << "]. Service is internal."; } @@ -1427,7 +1495,8 @@ std::shared_ptr<endpoint> routing_manager_impl::create_client_endpoint( boost::asio::ip::tcp::endpoint(_address, _remote_port), io_, configuration_->get_message_size_reliable( - _address.to_string(), _remote_port)); + _address.to_string(), _remote_port), + configuration_->get_buffer_shrink_threshold()); if (configuration_->has_enabled_magic_cookies(_address.to_string(), _remote_port)) { @@ -1465,7 +1534,8 @@ std::shared_ptr<endpoint> routing_manager_impl::create_server_endpoint( shared_from_this(), boost::asio::ip::tcp::endpoint(its_unicast, _port), io_, configuration_->get_message_size_reliable( - its_unicast.to_string(), _port)); + its_unicast.to_string(), _port), + configuration_->get_buffer_shrink_threshold()); if (configuration_->has_enabled_magic_cookies( its_unicast.to_string(), _port) || configuration_->has_enabled_magic_cookies( @@ -1495,7 +1565,7 @@ std::shared_ptr<endpoint> routing_manager_impl::create_server_endpoint( server_endpoints_[_port][_reliable] = its_endpoint; its_endpoint->start(); } - } catch (std::exception &e) { + } catch (const std::exception &e) { host_->on_error(error_code_e::SERVER_ENDPOINT_CREATION_FAILED); VSOMEIP_ERROR << e.what(); } @@ -1887,8 +1957,8 @@ std::chrono::milliseconds routing_manager_impl::add_routing_info( && (major_minor_pair.second <= _minor || _minor == DEFAULT_MINOR || major_minor_pair.second == ANY_MINOR)) { - host_->on_availability(_service, _instance, - true, its_info->get_major(), its_info->get_minor()); + on_availability(_service, _instance, + true, its_info->get_major(), its_info->get_minor()); if (!stub_->contained_in_routing_info( VSOMEIP_ROUTING_CLIENT, _service, _instance, its_info->get_major(), @@ -1916,7 +1986,7 @@ std::chrono::milliseconds routing_manager_impl::add_routing_info( = endpoint_definition::get(_unreliable_address, _unreliable_port, false); remote_service_info_[_service][_instance][false] = endpoint_def; if (!is_reliable_known) { - host_->on_availability(_service, _instance, true, _major, _minor); + on_availability(_service, _instance, true, _major, _minor); stub_->on_offer_service(VSOMEIP_ROUTING_CLIENT, _service, _instance, _major, _minor); } } @@ -1931,7 +2001,7 @@ void routing_manager_impl::del_routing_info(service_t _service, instance_t _inst if(!its_info) return; - host_->on_availability(_service, _instance, false, its_info->get_major(), its_info->get_minor()); + on_availability(_service, _instance, false, its_info->get_major(), its_info->get_minor()); stub_->on_stop_offer_service(VSOMEIP_ROUTING_CLIENT, _service, _instance, its_info->get_major(), its_info->get_minor()); // Implicit unsubscribe { @@ -2022,7 +2092,7 @@ std::chrono::milliseconds routing_manager_impl::update_routing_info(std::chrono: for (auto &s : its_expired_offers) { for (auto &i : s.second) { - VSOMEIP_DEBUG << "update_routing_info: elapsed=" << _elapsed.count() + VSOMEIP_INFO << "update_routing_info: elapsed=" << _elapsed.count() << " : delete service/instance " << std::hex << s.first << "/" << i.first; del_routing_info(s.first, i.first, i.second.first, i.second.second); } @@ -2043,15 +2113,19 @@ void routing_manager_impl::expire_services(const boost::asio::ip::address &_addr } bool is_gone(false); boost::asio::ip::address its_address; - std::shared_ptr<endpoint> its_endpoint = i.second->get_endpoint(true); - if (its_endpoint) { - if (its_endpoint->get_remote_address(its_address)) { + std::shared_ptr<client_endpoint> its_client_endpoint = + std::dynamic_pointer_cast<client_endpoint>( + i.second->get_endpoint(true)); + if (its_client_endpoint) { + if (its_client_endpoint->get_remote_address(its_address)) { is_gone = (its_address == _address); } } else { - its_endpoint = i.second->get_endpoint(false); - if (its_endpoint) { - if (its_endpoint->get_remote_address(its_address)) { + its_client_endpoint = + std::dynamic_pointer_cast<client_endpoint>( + i.second->get_endpoint(false)); + if (its_client_endpoint) { + if (its_client_endpoint->get_remote_address(its_address)) { is_gone = (its_address == _address); } } @@ -2070,7 +2144,7 @@ void routing_manager_impl::expire_services(const boost::asio::ip::address &_addr for (auto &s : its_expired_offers) { for (auto &i : s.second) { - VSOMEIP_DEBUG << "expire_services for address: " << _address.to_string() + VSOMEIP_INFO << "expire_services for address: " << _address.to_string() << " : delete service/instance " << std::hex << s.first << "/" << i.first; del_routing_info(s.first, i.first, i.second.first, i.second.second); } @@ -2175,13 +2249,13 @@ bool routing_manager_impl::on_subscribe_accepted(service_t _service, instance_t } if (client != VSOMEIP_ROUTING_CLIENT) { - VSOMEIP_DEBUG << "Subscription accepted: eventgroup=" << _eventgroup + VSOMEIP_INFO << "Subscription accepted: eventgroup=" << _eventgroup << " : target: " << _target->get_address().to_string() << ":" << std::dec <<_target->get_port() << (_target->is_reliable() ? " reliable" : " unreliable") << " from client: 0x" << std::hex << client << "."; } else { - VSOMEIP_DEBUG << "Subscription accepted: eventgroup: " << _eventgroup + VSOMEIP_INFO << "Subscription accepted: eventgroup: " << _eventgroup << " : target: " << _target->get_address().to_string() << ":" << std::dec <<_target->get_port() << (_target->is_reliable() ? " reliable" : " unreliable") @@ -2267,12 +2341,12 @@ void routing_manager_impl::on_unsubscribe(service_t _service, client_t its_client = find_client(_service, _instance, its_eventgroup, _target); if (its_client != VSOMEIP_ROUTING_CLIENT) { - VSOMEIP_DEBUG << "on_unsubscribe: target: " << _target->get_address().to_string() + VSOMEIP_INFO << "on_unsubscribe: target: " << _target->get_address().to_string() << ":" << std::dec <<_target->get_port() << (_target->is_reliable() ? " reliable" : " unreliable") << " from client: 0x" << std::hex << its_client; } else { - VSOMEIP_DEBUG << "on_unsubscribe: target: " << _target->get_address().to_string() + VSOMEIP_INFO << "on_unsubscribe: target: " << _target->get_address().to_string() << ":" << std::dec <<_target->get_port() << (_target->is_reliable() ? " reliable" : " unreliable"); } @@ -2609,7 +2683,9 @@ return_code_e routing_manager_impl::check_error(const byte_t *_data, length_t _s void routing_manager_impl::send_error(return_code_e _return_code, const byte_t *_data, length_t _size, instance_t _instance, bool _reliable, - endpoint *_receiver) { + endpoint *_receiver, + const boost::asio::ip::address &_remote_address, + std::uint16_t _remote_port) { client_t its_client = 0; service_t its_service = 0; @@ -2646,53 +2722,21 @@ void routing_manager_impl::send_error(return_code_e _return_code, error_message->set_return_code(_return_code); error_message->set_service(its_service); error_message->set_session(its_session); - - std::lock_guard<std::mutex> its_lock(serialize_mutex_); - if (serializer_->serialize(error_message.get())) { - if (_receiver) { - boost::asio::ip::address adr; - uint16_t port; - if (_receiver->is_reliable()) { - auto endpoint = dynamic_cast<tcp_server_endpoint_impl*>(_receiver); - if(!endpoint) { - return; - } - if (!endpoint->get_remote_address(adr)) { - VSOMEIP_ERROR << "routing_manager_impl::send_error: " - "couldn't determine remote address (reliable)"; - return; - } - port = endpoint->get_remote_port(); - if (!port) { - VSOMEIP_ERROR << "routing_manager_impl::send_error: " - "couldn't determine remote port (reliable)"; - return; - } - } else { - auto endpoint = dynamic_cast<udp_server_endpoint_impl*>(_receiver); - if (!endpoint) { - return; - } - if (!endpoint->get_remote_address(adr)) { - VSOMEIP_ERROR << "routing_manager_impl::send_error: " - "couldn't determine remote address (unreliable)"; - return; - } - port = endpoint->get_remote_port(); - if (!port) { - VSOMEIP_ERROR << "routing_manager_impl::send_error: " - "couldn't determine remote port (unreliable)"; - return; - } - } - auto its_endpoint_def = - std::make_shared<endpoint_definition>(adr, port, _receiver->is_reliable()); - its_endpoint_def->set_remote_port(_receiver->get_local_port()); - send_to(its_endpoint_def, serializer_->get_data(), serializer_->get_size(), true); + { + std::lock_guard<std::mutex> its_lock(serialize_mutex_); + if (serializer_->serialize(error_message.get())) { + if (_receiver) { + auto its_endpoint_def = std::make_shared<endpoint_definition>( + _remote_address, _remote_port, + _receiver->is_reliable()); + its_endpoint_def->set_remote_port(_receiver->get_local_port()); + send_to(its_endpoint_def, serializer_->get_data(), + serializer_->get_size(), true); + } + serializer_->reset(); + } else { + VSOMEIP_ERROR<< "Failed to serialize error message."; } - serializer_->reset(); - } else { - VSOMEIP_ERROR << "Failed to serialize error message."; } } @@ -2716,55 +2760,72 @@ void routing_manager_impl::on_identify_response(client_t _client, service_t _ser } void routing_manager_impl::identify_for_subscribe(client_t _client, - service_t _service, instance_t _instance, major_version_t _major) { - if (!has_identified(_client, _service, _instance, false) && - !is_identifying(_client, _service, _instance, false)) { - auto unreliable_endpoint = find_or_create_remote_client(_service, _instance, false, _client); - if (unreliable_endpoint) { - { - std::lock_guard<std::mutex> its_lock(identified_clients_mutex_); - identifying_clients_[_service][_instance][false].insert(_client); - } - auto message = runtime::get()->create_message(false); - 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())) { - unreliable_endpoint->send(serializer_->get_data(), - serializer_->get_size()); - serializer_->reset(); - } - } - } - if (!has_identified(_client, _service, _instance, true) && - !is_identifying(_client, _service, _instance, true)) { - auto reliable_endpoint = find_or_create_remote_client(_service, _instance, true, _client); - if (reliable_endpoint) { - { - std::lock_guard<std::mutex> its_lock(identified_clients_mutex_); - identifying_clients_[_service][_instance][true].insert(_client); + service_t _service, instance_t _instance, major_version_t _major, + subscription_type_e _subscription_type) { + + if (_subscription_type == subscription_type_e::SU_RELIABLE_AND_UNRELIABLE + || _subscription_type == subscription_type_e::SU_PREFER_UNRELIABLE + || _subscription_type == subscription_type_e::SU_UNRELIABLE) { + if (!has_identified(_client, _service, _instance, false) + && !is_identifying(_client, _service, _instance, false)) { + if (!send_identify_message(_client, _service, _instance, _major, + false) && _subscription_type + == subscription_type_e::SU_PREFER_UNRELIABLE) { + send_identify_message(_client, _service, _instance, _major, + true); } - auto message = runtime::get()->create_message(true); - 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())) { - reliable_endpoint->send(serializer_->get_data(), - serializer_->get_size()); - serializer_->reset(); + } + } + + if (_subscription_type == subscription_type_e::SU_RELIABLE_AND_UNRELIABLE + || _subscription_type == subscription_type_e::SU_PREFER_RELIABLE + || _subscription_type == subscription_type_e::SU_RELIABLE) { + if (!has_identified(_client, _service, _instance, true) + && !is_identifying(_client, _service, _instance, true)) { + if (!send_identify_message(_client, _service, _instance, _major, + true) && _subscription_type + == subscription_type_e::SU_PREFER_RELIABLE) { + send_identify_message(_client, _service, _instance, _major, + false); } } } } +bool routing_manager_impl::send_identify_message(client_t _client, + service_t _service, + instance_t _instance, + major_version_t _major, + bool _reliable) { + auto its_endpoint = find_or_create_remote_client(_service, _instance, + _reliable, _client); + if (!its_endpoint) { + return false; + } + { + 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; + } + } + return true; +} + + bool routing_manager_impl::supports_selective(service_t _service, instance_t _instance) { bool supports_selective(false); auto its_service = remote_service_info_.find(_service); @@ -2884,7 +2945,7 @@ routing_manager_impl::expire_subscriptions() { its_instance.first, its_eventgroup.first, true); } - VSOMEIP_DEBUG << "Expired subscription (" + VSOMEIP_INFO << "Expired subscription (" << std::hex << its_service.first << "." << its_instance .first << "." << its_eventgroup.first << " from " @@ -3141,10 +3202,12 @@ void routing_manager_impl::on_pong(client_t _client) { } void routing_manager_impl::on_clientendpoint_error(client_t _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); + 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::confirm_pending_offers(client_t _client) { @@ -3208,6 +3271,7 @@ void routing_manager_impl::remove_specific_client_endpoint(client_t _client, ser if(found_instance != found_service->second.end()) { auto its_client = found_instance->second.find(_client); if (its_client != found_instance->second.end()) { + std::lock_guard<std::recursive_mutex> its_lock(endpoint_mutex_); if (remote_services_.find(_service) != remote_services_.end()) { if (remote_services_[_service].find(_instance) != remote_services_[_service].end()) { auto endpoint = remote_services_[_service][_instance][_client][_reliable]; @@ -3307,6 +3371,26 @@ void routing_manager_impl::remove_identifying_client(service_t _service, instanc } } +void routing_manager_impl::unsubscribe_specific_client_at_sd( + service_t _service, instance_t _instance, client_t _client) { + bool found(false); + { + std::lock_guard<std::mutex> its_lock(specific_endpoint_clients_mutex_); + auto its_service = specific_endpoint_clients_.find(_service); + if (its_service != specific_endpoint_clients_.end()) { + auto its_instance = its_service->second.find(_instance); + if (its_instance != its_service->second.end()) { + if (its_instance->second.find(_client) != its_instance->second.end()) { + found = true; + } + } + } + } + if (found && discovery_) { + discovery_->unsubscribe_client(_service, _instance, _client); + } +} + void routing_manager_impl::send_subscribe(client_t _client, service_t _service, instance_t _instance, eventgroup_t _eventgroup, major_version_t _major, subscription_type_e _subscription_type) { @@ -3377,5 +3461,34 @@ void routing_manager_impl::set_routing_state(routing_state_e _routing_state) { } } +void routing_manager_impl::on_net_if_state_changed(std::string _if, bool _available) { + if (_available != if_state_running_) { + if (_available) { + VSOMEIP_INFO << "Network interface \"" << _if << "\" is up and running."; + start_ip_routing(); +#ifndef WIN32 + if (netlink_connector_) { + netlink_connector_->unregister_net_if_changes_handler(); + } +#endif + } + } +} + +void routing_manager_impl::start_ip_routing() { + std::lock_guard<std::mutex> its_lock(pending_sd_offers_mutex_); + if_state_running_ = true; + + if (discovery_) { + discovery_->start(); + } else { + init_routing_info(); + } + + for (auto its_service : pending_sd_offers_) { + init_service_info(its_service.first, its_service.second, true); + } + pending_sd_offers_.clear(); +} } // namespace vsomeip diff --git a/implementation/routing/src/routing_manager_proxy.cpp b/implementation/routing/src/routing_manager_proxy.cpp index b762a17..f60218d 100644 --- a/implementation/routing/src/routing_manager_proxy.cpp +++ b/implementation/routing/src/routing_manager_proxy.cpp @@ -573,11 +573,11 @@ bool routing_manager_proxy::send(client_t _client, const byte_t *_data, its_target = find_local(_client); if (its_target) { #ifdef USE_DLT - uint16_t its_data_size + const uint16_t its_data_size = uint16_t(_size > USHRT_MAX ? USHRT_MAX : _size); tc::trace_header its_header; - if (its_header.prepare(its_target, true)) + if (its_header.prepare(nullptr, true)) tc_->trace(its_header.data_, VSOMEIP_TRACE_HEADER_SIZE, _data, its_data_size); #endif @@ -610,11 +610,11 @@ bool routing_manager_proxy::send(client_t _client, const byte_t *_data, } #ifdef USE_DLT else if (its_target != sender_) { - uint16_t its_data_size + const uint16_t its_data_size = uint16_t(_size > USHRT_MAX ? USHRT_MAX : _size); tc::trace_header its_header; - if (its_header.prepare(its_target, true)) + if (its_header.prepare(nullptr, true)) tc_->trace(its_header.data_, VSOMEIP_TRACE_HEADER_SIZE, _data, its_data_size); } @@ -680,7 +680,7 @@ void routing_manager_proxy::on_connect(std::shared_ptr<endpoint> _endpoint) { } is_connected_ = true; if (is_connected_ && is_started_) { - VSOMEIP_DEBUG << std::hex << "Client " << client_ + VSOMEIP_INFO << std::hex << "Client " << client_ << " successfully connected to routing ~> registering.."; register_application(); } @@ -693,14 +693,18 @@ void routing_manager_proxy::on_disconnect(std::shared_ptr<endpoint> _endpoint) { } } -void routing_manager_proxy::on_error(const byte_t *_data, length_t _length, - endpoint *_receiver) { +void routing_manager_proxy::on_error( + const byte_t *_data, length_t _length, endpoint *_receiver, + const boost::asio::ip::address &_remote_address, + std::uint16_t _remote_port) { // Implement me when needed (void)(_data); (void)(_length); (void)(_receiver); + (void)(_remote_address); + (void)(_remote_port); } void routing_manager_proxy::release_port(uint16_t _port, bool _reliable) { @@ -711,15 +715,19 @@ void routing_manager_proxy::release_port(uint16_t _port, bool _reliable) { void routing_manager_proxy::on_message(const byte_t *_data, length_t _size, endpoint *_receiver, const boost::asio::ip::address &_destination, - client_t _bound_client) { + client_t _bound_client, + const boost::asio::ip::address &_remote_address, + std::uint16_t _remote_port) { (void)_receiver; (void)_destination; + (void)_remote_address; + (void)_remote_port; #if 0 std::stringstream msg; msg << "rmp::on_message: "; for (int i = 0; i < _size; ++i) msg << std::hex << std::setw(2) << std::setfill('0') << (int)_data[i] << " "; - VSOMEIP_DEBUG << msg.str(); + VSOMEIP_INFO << msg.str(); #endif byte_t its_command; client_t its_client; @@ -758,10 +766,14 @@ void routing_manager_proxy::on_message(const byte_t *_data, length_t _size, bool its_reliable; std::memcpy(&its_reliable, &_data[_size - sizeof(bool)], sizeof(its_reliable)); + // reduce by size of instance, flush and reliable flag + const std::uint32_t its_message_size = its_length - + static_cast<uint32_t>(sizeof(its_instance) + + sizeof(bool) + sizeof(bool)); auto a_deserializer = get_deserializer(); a_deserializer->set_data(&_data[VSOMEIP_COMMAND_PAYLOAD_POS], - its_length); + its_message_size); std::shared_ptr<message> its_message(a_deserializer->deserialize_message()); a_deserializer->reset(); put_deserializer(a_deserializer); @@ -800,7 +812,7 @@ void routing_manager_proxy::on_message(const byte_t *_data, length_t _size, return; } } - host_->on_message(its_message); + host_->on_message(std::move(its_message)); } else { VSOMEIP_ERROR << "Routing proxy: on_message: " << "SomeIP-Header deserialization failed!"; @@ -866,6 +878,7 @@ void routing_manager_proxy::on_message(const byte_t *_data, length_t _size, routing_manager_base::subscribe(its_client, its_service, its_instance, its_eventgroup, its_major, subscription_type_e::SU_RELIABLE_AND_UNRELIABLE); send_subscribe_ack(its_client, its_service, its_instance, its_eventgroup); + send_pending_notify_ones(its_service, its_instance, its_eventgroup, its_client); } } else { // Local & not yet known subscriber ~> set pending until subscriber gets known! @@ -874,8 +887,8 @@ void routing_manager_proxy::on_message(const byte_t *_data, length_t _size, subscription_type_e::SU_RELIABLE_AND_UNRELIABLE}; std::lock_guard<std::mutex> its_lock(pending_ingoing_subscripitons_mutex_); pending_ingoing_subscripitons_[its_client].insert(subscription); - } - VSOMEIP_DEBUG << "SUBSCRIBE(" + } + VSOMEIP_INFO << "SUBSCRIBE(" << std::hex << std::setw(4) << std::setfill('0') << its_client <<"): [" << std::hex << std::setw(4) << std::setfill('0') << its_service << "." << std::hex << std::setw(4) << std::setfill('0') << its_instance << "." @@ -903,7 +916,7 @@ void routing_manager_proxy::on_message(const byte_t *_data, length_t _size, its_instance, its_eventgroup); } } - VSOMEIP_DEBUG << "UNSUBSCRIBE(" + VSOMEIP_INFO << "UNSUBSCRIBE(" << 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 << "." @@ -919,7 +932,7 @@ void routing_manager_proxy::on_message(const byte_t *_data, length_t _size, sizeof(its_eventgroup)); on_subscribe_nack(its_client, its_service, its_instance, its_eventgroup); - VSOMEIP_DEBUG << "SUBSCRIBE NACK(" + VSOMEIP_INFO << "SUBSCRIBE NACK(" << 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 << "." @@ -935,7 +948,7 @@ void routing_manager_proxy::on_message(const byte_t *_data, length_t _size, sizeof(its_eventgroup)); on_subscribe_ack(its_client, its_service, its_instance, its_eventgroup); - VSOMEIP_DEBUG << "SUBSCRIBE ACK(" + VSOMEIP_INFO << "SUBSCRIBE ACK(" << 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 << "." @@ -955,7 +968,7 @@ void routing_manager_proxy::on_routing_info(const byte_t *_data, msg << "rmp::on_routing_info(" << std::hex << client_ << "): "; for (uint32_t i = 0; i < _size; ++i) msg << std::hex << std::setw(2) << std::setfill('0') << (int)_data[i] << " "; - VSOMEIP_DEBUG << msg.str(); + VSOMEIP_INFO << msg.str(); #endif inner_state_type_e its_state(inner_state_type_e::ST_DEREGISTERED); bool restart_sender(_size == 1); // 1 indicates a routing master stop @@ -1158,6 +1171,8 @@ void routing_manager_proxy::on_routing_info(const byte_t *_data, subscription_type_e::SU_RELIABLE_AND_UNRELIABLE); send_subscribe_ack(si.client_id_, si.service_id_, si.instance_id_, si.eventgroup_id_); + send_pending_notify_ones(si.service_id_, + si.instance_id_, si.eventgroup_id_, si.client_id_); } pending_ingoing_subscripitons_.erase(si.client_id_); } @@ -1422,6 +1437,7 @@ void routing_manager_proxy::on_stop_offer_service(service_t _service, minor_version_t _minor) { (void) _major; (void) _minor; + std::map<event_t, std::shared_ptr<event> > events; { std::lock_guard<std::mutex> its_lock(events_mutex_); auto its_events_service = events_.find(_service); @@ -1429,10 +1445,13 @@ void routing_manager_proxy::on_stop_offer_service(service_t _service, auto its_events_instance = its_events_service->second.find(_instance); if (its_events_instance != its_events_service->second.end()) { for (auto &e : its_events_instance->second) - e.second->unset_payload(); + events[e.first] = e.second; } } } + for (auto &e : events) { + e.second->unset_payload(); + } } void routing_manager_proxy::send_pending_commands() { @@ -1486,11 +1505,12 @@ void routing_manager_proxy::init_receiver() { #else boost::asio::local::stream_protocol::endpoint(its_client.str()), #endif - io_, configuration_->get_max_message_size_local()); + io_, configuration_->get_max_message_size_local(), + configuration_->get_buffer_shrink_threshold()); #ifdef WIN32 - VSOMEIP_DEBUG << "Listening at " << port; + VSOMEIP_INFO << "Listening at " << port; #else - VSOMEIP_DEBUG<< "Listening at " << its_client.str(); + VSOMEIP_INFO << "Listening at " << its_client.str(); #endif } catch (const std::exception &e) { host_->on_error(error_code_e::SERVER_ENDPOINT_CREATION_FAILED); diff --git a/implementation/routing/src/routing_manager_stub.cpp b/implementation/routing/src/routing_manager_stub.cpp index 3874a07..a55d61b 100644 --- a/implementation/routing/src/routing_manager_stub.cpp +++ b/implementation/routing/src/routing_manager_stub.cpp @@ -50,7 +50,9 @@ routing_manager_stub::routing_manager_stub( local_receiver_(nullptr), configuration_(_configuration), routingCommandSize_(VSOMEIP_ROUTING_INFO_SIZE_INIT), + is_socket_activated_(false), client_registration_running_(false), + max_local_message_size_(configuration_->get_max_message_size_local()), configured_watchdog_timeout_(configuration_->get_watchdog_timeout()), pinged_clients_timer_(io_) { } @@ -80,7 +82,7 @@ void routing_manager_stub::start() { << configuration_->get_watchdog_timeout() << " : Allowed missing pongs = " << configuration_->get_allowed_missing_pongs() - << "."; + << "."; start_watchdog(); } else { VSOMEIP_INFO << "Watchdog is disabled!"; @@ -140,27 +142,35 @@ void routing_manager_stub::on_disconnect(std::shared_ptr<endpoint> _endpoint) { (void)_endpoint; } -void routing_manager_stub::on_error(const byte_t *_data, length_t _length, - endpoint *_receiver) { +void routing_manager_stub::on_error( + const byte_t *_data, length_t _length, endpoint *_receiver, + const boost::asio::ip::address &_remote_address, + std::uint16_t _remote_port) { // Implement me when needed (void)(_data); (void)(_length); (void)(_receiver); + (void)(_remote_address); + (void)(_remote_port); } void routing_manager_stub::release_port(uint16_t _port, bool _reliable) { - (void)_port; - (void)_reliable; - // intentionally empty + (void)_port; + (void)_reliable; + // intentionally empty } void routing_manager_stub::on_message(const byte_t *_data, length_t _size, endpoint *_receiver, const boost::asio::ip::address &_destination, - client_t _bound_client) { + client_t _bound_client, + const boost::asio::ip::address &_remote_address, + std::uint16_t _remote_port) { (void)_receiver; (void)_destination; + (void)_remote_address; + (void) _remote_port; #if 0 std::stringstream msg; msg << "rms::on_message: "; @@ -312,7 +322,7 @@ void routing_manager_stub::on_message(const byte_t *_data, length_t _size, std::memcpy(&its_eventgroup, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 4], sizeof(its_eventgroup)); host_->on_subscribe_ack(its_client, its_service, its_instance, its_eventgroup); - VSOMEIP_DEBUG << "SUBSCRIBE ACK(" + VSOMEIP_INFO << "SUBSCRIBE ACK(" << 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 << "." @@ -327,14 +337,14 @@ void routing_manager_stub::on_message(const byte_t *_data, length_t _size, std::memcpy(&its_eventgroup, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 4], sizeof(its_eventgroup)); host_->on_subscribe_nack(its_client, its_service, its_instance, its_eventgroup); - VSOMEIP_DEBUG << "SUBSCRIBE NACK(" + VSOMEIP_INFO << "SUBSCRIBE NACK(" << std::hex << std::setw(4) << std::setfill('0') << its_client << "): [" << std::hex << std::setw(4) << std::setfill('0') << its_service << "." << std::hex << std::setw(4) << std::setfill('0') << its_instance << "." << std::hex << std::setw(4) << std::setfill('0') << its_eventgroup << "]"; break; - case VSOMEIP_SEND: + case VSOMEIP_SEND: { its_data = &_data[VSOMEIP_COMMAND_PAYLOAD_POS]; its_service = VSOMEIP_BYTES_TO_WORD( its_data[VSOMEIP_SERVICE_POS_MIN], @@ -366,20 +376,28 @@ void routing_manager_stub::on_message(const byte_t *_data, length_t _size, return; } } - host_->on_message(its_service, its_instance, its_data, its_size, its_reliable); + // reduce by size of instance, flush and reliable flag + const std::uint32_t its_message_size = its_size - + static_cast<std::uint32_t>(sizeof(its_instance) + + sizeof(bool) + sizeof(bool)); + host_->on_message(its_service, its_instance, its_data, its_message_size, its_reliable); break; - - case VSOMEIP_NOTIFY: + } + case VSOMEIP_NOTIFY: { its_data = &_data[VSOMEIP_COMMAND_PAYLOAD_POS]; its_service = VSOMEIP_BYTES_TO_WORD( its_data[VSOMEIP_SERVICE_POS_MIN], its_data[VSOMEIP_SERVICE_POS_MAX]); std::memcpy(&its_instance, &_data[_size - sizeof(instance_t) - sizeof(bool) - sizeof(bool)], sizeof(its_instance)); - host_->on_notification(VSOMEIP_ROUTING_CLIENT, its_service, its_instance, - its_data, its_size); + // reduce by size of instance, flush and reliable flag + const std::uint32_t its_message_size = its_size - + static_cast<uint32_t>(sizeof(its_instance) + + sizeof(bool) + sizeof(bool)); + host_->on_notification(VSOMEIP_ROUTING_CLIENT, its_service, its_instance, its_data, its_message_size); break; - case VSOMEIP_NOTIFY_ONE: + } + case VSOMEIP_NOTIFY_ONE: { its_data = &_data[VSOMEIP_COMMAND_PAYLOAD_POS]; its_service = VSOMEIP_BYTES_TO_WORD( its_data[VSOMEIP_SERVICE_POS_MIN], @@ -388,10 +406,14 @@ void routing_manager_stub::on_message(const byte_t *_data, length_t _size, sizeof(bool) - sizeof(bool) - sizeof(client_t)], sizeof(its_instance)); std::memcpy(&its_target_client, &_data[_size - sizeof(client_t)], sizeof(client_t)); + // reduce by size of instance, flush, reliable flag and target client + const std::uint32_t its_message_size = its_size - + static_cast<uint32_t>(sizeof(its_instance) + + sizeof(bool) + sizeof(bool) + sizeof(client_t)); host_->on_notification(its_target_client, its_service, its_instance, - its_data, its_size, true); + its_data, its_message_size, true); break; - + } case VSOMEIP_REQUEST_SERVICE: std::memcpy(&its_service, &_data[VSOMEIP_COMMAND_PAYLOAD_POS], sizeof(its_service)); @@ -454,7 +476,7 @@ void routing_manager_stub::on_message(const byte_t *_data, length_t _size, host_->register_shadow_event(its_client, its_service, its_instance, its_event, its_eventgroups, is_field, is_provided); - VSOMEIP_DEBUG << "REGISTER EVENT(" + VSOMEIP_INFO << "REGISTER EVENT(" << 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 << "." @@ -480,7 +502,7 @@ void routing_manager_stub::on_message(const byte_t *_data, length_t _size, } host_->unregister_shadow_event(its_client, its_service, its_instance, its_event, is_provided); - VSOMEIP_DEBUG << "UNREGISTER EVENT(" + VSOMEIP_INFO << "UNREGISTER EVENT(" << 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 << "." @@ -506,7 +528,7 @@ void routing_manager_stub::on_message(const byte_t *_data, length_t _size, break; case VSOMEIP_REGISTERED_ACK: - VSOMEIP_DEBUG << "REGISTERED_ACK(" + VSOMEIP_INFO << "REGISTERED_ACK(" << std::hex << std::setw(4) << std::setfill('0') << its_client << ")"; std::lock_guard<std::mutex> its_guard(routing_info_mutex_); broadcast_routing_info(false, its_client); @@ -536,6 +558,8 @@ void routing_manager_stub::on_deregister_application(client_t _client) { for (auto &its_instance : its_service.second) { auto its_version = its_instance.second; routing_info_mutex_.unlock(); + host_->on_availability(its_service.first, its_instance.first, + false, its_version.first, its_version.second); host_->on_stop_offer_service(_client, its_service.first, its_instance.first, its_version.first, its_version.second); @@ -619,29 +643,30 @@ void routing_manager_stub::init_routing_endpoint() { std::make_shared < local_server_endpoint_impl > (shared_from_this(), boost::asio::local::stream_protocol::endpoint(endpoint_path_), - io_, configuration_->get_max_message_size_local(), native_socket_fd); + io_, configuration_->get_max_message_size_local(), native_socket_fd, + configuration_->get_buffer_shrink_threshold()); } catch (const std::exception &e) { VSOMEIP_ERROR << ERROR_INFO[static_cast<int>(error_code_e::SERVER_ENDPOINT_CREATION_FAILED)] << " (" << static_cast<int>(error_code_e::SERVER_ENDPOINT_CREATION_FAILED) << ")"; - VSOMEIP_ERROR << "routing_manager_stub::init_endpoint Client ID: " + VSOMEIP_ERROR << "routing_manager_stub::init_routing_endpoint Client ID: " << std::hex << VSOMEIP_ROUTING_CLIENT << ": " << e.what(); } #endif is_socket_activated_ = true; } else { - #if WIN32 - ::_unlink(endpoint_path_.c_str()); - int port = VSOMEIP_INTERNAL_BASE_PORT; - VSOMEIP_DEBUG << "Routing endpoint at " << port; - #else - if (-1 == ::unlink(endpoint_path_.c_str()) && errno != ENOENT) { - VSOMEIP_ERROR << "routing_manager_stub::init_endpoint unlink failed (" - << endpoint_path_ << "): "<< std::strerror(errno); - } - VSOMEIP_DEBUG << "init_routing_endpoint Routing endpoint at " << endpoint_path_; - - const mode_t previous_mask(::umask(static_cast<mode_t>(configuration_->get_umask()))); - #endif + #if WIN32 + ::_unlink(endpoint_path_.c_str()); + int port = VSOMEIP_INTERNAL_BASE_PORT; + VSOMEIP_INFO << "Routing endpoint at " << port; + #else + if (-1 == ::unlink(endpoint_path_.c_str()) && errno != ENOENT) { + VSOMEIP_ERROR << "routing_manager_stub::init_endpoint unlink failed (" + << endpoint_path_ << "): "<< std::strerror(errno); + } + VSOMEIP_INFO << "init_routing_endpoint Routing endpoint at " << endpoint_path_; + + const mode_t previous_mask(::umask(static_cast<mode_t>(configuration_->get_umask()))); + #endif try { endpoint_ = @@ -652,16 +677,17 @@ void routing_manager_stub::init_routing_endpoint() { #else boost::asio::local::stream_protocol::endpoint(endpoint_path_), #endif - io_, configuration_->get_max_message_size_local()); + io_, configuration_->get_max_message_size_local(), + configuration_->get_buffer_shrink_threshold()); } catch (const std::exception &e) { VSOMEIP_ERROR << ERROR_INFO[static_cast<int>(error_code_e::SERVER_ENDPOINT_CREATION_FAILED)] << " (" << static_cast<int>(error_code_e::SERVER_ENDPOINT_CREATION_FAILED) << ")"; - VSOMEIP_ERROR << "routing_manager_stub::init_endpoint Client ID: " + VSOMEIP_ERROR << "routing_manager_stub::init_routing_endpoint Client ID: " << std::hex << VSOMEIP_ROUTING_CLIENT << ": " << e.what(); } #ifndef WIN32 ::umask(previous_mask); - #endif + #endif is_socket_activated_ = false; } } @@ -813,11 +839,12 @@ void routing_manager_stub::send_routing_info(client_t _client, bool _empty) { msg << "rms::send_routing_info "; for (uint32_t i = 0; i < its_size; ++i) msg << std::hex << std::setw(2) << std::setfill('0') << (int)its_command[i] << " "; - VSOMEIP_DEBUG << msg.str(); + VSOMEIP_INFO << msg.str(); #endif // Send routing info or error! - if(its_command.size() <= VSOMEIP_MAX_LOCAL_MESSAGE_SIZE) { + if(its_command.size() <= max_local_message_size_ + || VSOMEIP_MAX_LOCAL_MESSAGE_SIZE == 0) { its_endpoint->send(&its_command[0], uint32_t(its_size), true); } else { VSOMEIP_ERROR << "Routing info exceeds maximum message size: Can't send!"; @@ -1075,7 +1102,8 @@ void routing_manager_stub::create_local_receiver() { #else boost::asio::local::stream_protocol::endpoint(local_receiver_path_), #endif - io_, configuration_->get_max_message_size_local()); + io_, configuration_->get_max_message_size_local(), + configuration_->get_buffer_shrink_threshold()); } catch (const std::exception &e) { VSOMEIP_ERROR << ERROR_INFO[static_cast<int>(error_code_e::SERVER_ENDPOINT_CREATION_FAILED)] << " (" << static_cast<int>(error_code_e::SERVER_ENDPOINT_CREATION_FAILED) << ")"; @@ -1235,6 +1263,11 @@ void routing_manager_stub::remove_from_pinged_clients(client_t _client) { std::placeholders::_1)); } +bool routing_manager_stub::is_registered(client_t _client) const { + std::lock_guard<std::mutex> its_lock(routing_info_mutex_); + 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_); VSOMEIP_INFO << "Application/Client " diff --git a/implementation/runtime/include/application_impl.hpp b/implementation/runtime/include/application_impl.hpp index 88d00bc..0f5582f 100644 --- a/implementation/runtime/include/application_impl.hpp +++ b/implementation/runtime/include/application_impl.hpp @@ -146,7 +146,7 @@ public: VSOMEIP_EXPORT void on_state(state_type_e _state); VSOMEIP_EXPORT void on_availability(service_t _service, instance_t _instance, bool _is_available, major_version_t _major, minor_version_t _minor); - VSOMEIP_EXPORT void on_message(std::shared_ptr<message> _message); + VSOMEIP_EXPORT void on_message(const std::shared_ptr<message> &&_message); VSOMEIP_EXPORT void on_error(error_code_e _error); VSOMEIP_EXPORT bool on_subscription(service_t _service, instance_t _instance, eventgroup_t _eventgroup, client_t _client, bool _subscribed); @@ -290,7 +290,6 @@ private: std::mutex dispatcher_mutex_; // Condition to wakeup the dispatcher thread mutable std::condition_variable dispatcher_condition_; - boost::asio::steady_timer dispatcher_timer_; std::size_t max_dispatchers_; std::size_t max_dispatch_time_; diff --git a/implementation/runtime/include/runtime_impl.hpp b/implementation/runtime/include/runtime_impl.hpp index e761d8a..20c7c49 100644 --- a/implementation/runtime/include/runtime_impl.hpp +++ b/implementation/runtime/include/runtime_impl.hpp @@ -8,6 +8,7 @@ #include <vsomeip/runtime.hpp> #include <map> +#include <mutex> namespace vsomeip { @@ -39,11 +40,16 @@ public: std::shared_ptr<application> get_application( const std::string &_name) const; + void remove_application( const std::string &_name); + private: static std::shared_ptr<runtime> the_runtime_; static std::map<std::string, std::string> properties_; std::map<std::string, std::weak_ptr<application>> applications_; + + mutable std::mutex applications_mutex_; + static uint32_t postfix_id; }; } // namespace vsomeip diff --git a/implementation/runtime/src/application_impl.cpp b/implementation/runtime/src/application_impl.cpp index ccf4e05..f2fd422 100644 --- a/implementation/runtime/src/application_impl.cpp +++ b/implementation/runtime/src/application_impl.cpp @@ -43,7 +43,6 @@ application_impl::application_impl(const std::string &_name) catched_signal_(false), #endif is_dispatching_(false), - dispatcher_timer_(io_), max_dispatchers_(VSOMEIP_MAX_DISPATCHERS), max_dispatch_time_(VSOMEIP_MAX_DISPATCH_TIME), logger_(logger::get()), @@ -54,7 +53,7 @@ application_impl::application_impl(const std::string &_name) } application_impl::~application_impl() { - + runtime_->remove_application(name_); } void application_impl::set_configuration( @@ -182,7 +181,7 @@ bool application_impl::init() { its_trace_connector->set_sd_enabled(enable_sd_tracing); #endif - VSOMEIP_DEBUG << "Application(" << (name_ != "" ? name_ : "unnamed") + VSOMEIP_INFO << "Application(" << (name_ != "" ? name_ : "unnamed") << ", " << std::hex << client_ << ") is initialized (" << std::dec << max_dispatchers_ << ", " << std::dec << max_dispatch_time_ << ")."; @@ -217,6 +216,7 @@ bool application_impl::init() { } void application_impl::start() { + const size_t io_thread_count = configuration_->get_io_thread_count(name_); { std::lock_guard<std::mutex> its_lock(start_stop_mutex_); if (io_.stopped()) { @@ -240,7 +240,8 @@ void application_impl::start() { } stopped_ = false; stopped_called_ = false; - VSOMEIP_INFO << "Starting vsomeip application \"" << name_ << "\"."; + VSOMEIP_INFO << "Starting vsomeip application \"" << name_ << "\" using " + << std::dec << io_thread_count << " threads"; is_dispatching_ = true; @@ -258,7 +259,7 @@ void application_impl::start() { if (routing_) routing_->start(); - for (int i = 0; i < 3; i++) { + for (size_t i = 0; i < io_thread_count - 1; i++) { std::shared_ptr<std::thread> its_thread = std::make_shared<std::thread>([this, i] { io_.run(); @@ -271,6 +272,8 @@ void application_impl::start() { app_counter__++; app_counter_mutex__.unlock(); + io_.run(); + if (stop_thread_.joinable()) { stop_thread_.join(); } @@ -1012,7 +1015,7 @@ void application_impl::on_availability(service_t _service, instance_t _instance, } } -void application_impl::on_message(std::shared_ptr<message> _message) { +void application_impl::on_message(const std::shared_ptr<message> &&_message) { service_t its_service = _message->get_service(); instance_t its_instance = _message->get_instance(); method_t its_method = _message->get_method(); @@ -1105,7 +1108,7 @@ void application_impl::on_message(std::shared_ptr<message> _message) { auto handler = its_handler.handler_; std::shared_ptr<sync_handler> its_sync_handler = std::make_shared<sync_handler>([handler, _message]() { - handler(_message); + handler(std::move(_message)); }); handlers_.push_back(its_sync_handler); } @@ -1143,6 +1146,13 @@ void application_impl::main_dispatch() { its_lock.lock(); remove_elapsed_dispatchers(); + + if(!is_dispatching_) { + its_lock.unlock(); +#ifdef WIN32 + return; +#endif + } } } } @@ -1179,10 +1189,11 @@ void application_impl::dispatch() { void application_impl::invoke_handler(std::shared_ptr<sync_handler> &_handler) { std::thread::id its_id = std::this_thread::get_id(); - dispatcher_timer_.expires_from_now(std::chrono::milliseconds(max_dispatch_time_)); - dispatcher_timer_.async_wait([this, its_id](const boost::system::error_code &_error) { + boost::asio::steady_timer its_dispatcher_timer(io_); + its_dispatcher_timer.expires_from_now(std::chrono::milliseconds(max_dispatch_time_)); + its_dispatcher_timer.async_wait([this, its_id](const boost::system::error_code &_error) { if (!_error) { - VSOMEIP_DEBUG << "Blocking call detected. Client=" << std::hex << get_client(); + VSOMEIP_INFO << "Blocking call detected. Client=" << std::hex << get_client(); std::lock_guard<std::mutex> its_lock(dispatcher_mutex_); blocked_dispatchers_.insert(its_id); @@ -1200,7 +1211,7 @@ void application_impl::invoke_handler(std::shared_ptr<sync_handler> &_handler) { }); _handler->handler_(); - dispatcher_timer_.cancel(); + its_dispatcher_timer.cancel(); { std::lock_guard<std::mutex> its_lock(dispatcher_mutex_); blocked_dispatchers_.erase(its_id); @@ -1325,7 +1336,7 @@ void application_impl::send_back_cached_event(service_t _service, its_message->set_instance(_instance); its_message->set_payload(its_event->get_payload()); its_message->set_initial(true); - on_message(its_message); + on_message(std::move(its_message)); } } @@ -1342,7 +1353,7 @@ void application_impl::send_back_cached_eventgroup(service_t _service, its_message->set_instance(_instance); its_message->set_payload(its_event->get_payload()); its_message->set_initial(true); - on_message(its_message); + on_message(std::move(its_message)); } } } diff --git a/implementation/runtime/src/runtime_impl.cpp b/implementation/runtime/src/runtime_impl.cpp index cf8c6e6..194368f 100644 --- a/implementation/runtime/src/runtime_impl.cpp +++ b/implementation/runtime/src/runtime_impl.cpp @@ -14,6 +14,7 @@ namespace vsomeip { std::map<std::string, std::string> runtime_impl::properties_; std::shared_ptr<runtime> runtime_impl::the_runtime_ = std::make_shared<runtime_impl>(); +uint32_t runtime_impl::postfix_id = 0; std::string runtime_impl::get_property(const std::string &_name) { auto found_property = properties_.find(_name); @@ -35,8 +36,14 @@ runtime_impl::~runtime_impl() { std::shared_ptr<application> runtime_impl::create_application( const std::string &_name) { - std::shared_ptr<application> application = std::make_shared<application_impl>(_name); - applications_[_name] = application; + std::lock_guard<std::mutex> its_lock(applications_mutex_); + std::string its_name_ = _name; + auto found_application = applications_.find(_name); + if( found_application != applications_.end()) { + its_name_ += "_" + std::to_string(postfix_id++); + } + std::shared_ptr<application> application = std::make_shared<application_impl>(its_name_); + applications_[its_name_] = application; return application; } @@ -105,10 +112,20 @@ std::shared_ptr<payload> runtime_impl::create_payload( std::shared_ptr<application> runtime_impl::get_application( const std::string &_name) const { + std::lock_guard<std::mutex> its_lock(applications_mutex_); auto found_application = applications_.find(_name); if(found_application != applications_.end()) return found_application->second.lock(); return nullptr; } +void runtime_impl::remove_application( + const std::string &_name) { + std::lock_guard<std::mutex> its_lock(applications_mutex_); + auto found_application = applications_.find(_name); + if(found_application != applications_.end()) { + applications_.erase(_name); + } +} + } // namespace vsomeip diff --git a/implementation/service_discovery/include/deserializer.hpp b/implementation/service_discovery/include/deserializer.hpp index 085bc7c..ba9a82f 100755 --- a/implementation/service_discovery/include/deserializer.hpp +++ b/implementation/service_discovery/include/deserializer.hpp @@ -15,8 +15,9 @@ class message_impl; class deserializer: public vsomeip::deserializer {
public:
- deserializer();
- deserializer(uint8_t *_data, std::size_t _length);
+ deserializer(std::uint32_t _shrink_buffer_threshold);
+ deserializer(uint8_t *_data, std::size_t _length,
+ std::uint32_t _shrink_buffer_threshold);
deserializer(const deserializer &_other);
virtual ~deserializer();
diff --git a/implementation/service_discovery/include/service_discovery.hpp b/implementation/service_discovery/include/service_discovery.hpp index 14c95bc..d3a62fc 100644 --- a/implementation/service_discovery/include/service_discovery.hpp +++ b/implementation/service_discovery/include/service_discovery.hpp @@ -43,6 +43,8 @@ public: virtual void unsubscribe(service_t _service, instance_t _instance, eventgroup_t _eventgroup, client_t _client) = 0; virtual void unsubscribe_all(service_t _service, instance_t _instance) = 0; + virtual void unsubscribe_client(service_t _service, instance_t _instance, + client_t _client) = 0; virtual bool send(bool _is_announcing, bool _is_find = false) = 0; diff --git a/implementation/service_discovery/include/service_discovery_impl.hpp b/implementation/service_discovery/include/service_discovery_impl.hpp index f2a9e3c..e367c0b 100644 --- a/implementation/service_discovery/include/service_discovery_impl.hpp +++ b/implementation/service_discovery/include/service_discovery_impl.hpp @@ -20,6 +20,7 @@ #include "ip_option_impl.hpp" #include "ipv4_option_impl.hpp" #include "ipv6_option_impl.hpp" +#include "deserializer.hpp" namespace vsomeip { @@ -71,6 +72,8 @@ public: void unsubscribe(service_t _service, instance_t _instance, eventgroup_t _eventgroup, client_t _client); void unsubscribe_all(service_t _service, instance_t _instance); + void unsubscribe_client(service_t _service, instance_t _instance, + client_t _client); bool send(bool _is_announcing, bool _is_find); @@ -100,7 +103,7 @@ private: const boost::asio::ip::address &_address, uint16_t _port, bool _is_reliable); void insert_find_entries(std::shared_ptr<message_impl> &_message, - requests_t &_requests, uint32_t _start, uint32_t &_size, bool &_done); + uint32_t _start, uint32_t &_size, bool &_done); void insert_offer_entries(std::shared_ptr<message_impl> &_message, const services_t &_services, uint32_t &_start, uint32_t _size, bool &_done, bool _ignore_phase); @@ -172,7 +175,6 @@ private: std::chrono::milliseconds stop_ttl_timer(); void check_ttl(const boost::system::error_code &_error); - boost::asio::ip::address get_current_remote_address() const; void start_subscription_expiration_timer(); void stop_subscription_expiration_timer(); @@ -317,6 +319,10 @@ private: boost::asio::steady_timer main_phase_timer_; bool is_suspended_; + + std::string sd_multicast_; + + boost::asio::ip::address current_remote_address_; }; } // namespace sd diff --git a/implementation/service_discovery/src/deserializer.cpp b/implementation/service_discovery/src/deserializer.cpp index 744c463..351676f 100644 --- a/implementation/service_discovery/src/deserializer.cpp +++ b/implementation/service_discovery/src/deserializer.cpp @@ -9,12 +9,13 @@ namespace vsomeip {
namespace sd {
-deserializer::deserializer()
- : vsomeip::deserializer() {
+deserializer::deserializer(std::uint32_t _shrink_buffer_threshold)
+ : vsomeip::deserializer(_shrink_buffer_threshold) {
}
-deserializer::deserializer(uint8_t *_data, std::size_t _length)
- : vsomeip::deserializer(_data, _length) {
+deserializer::deserializer(uint8_t *_data, std::size_t _length,
+ std::uint32_t _shrink_buffer_threshold)
+ : vsomeip::deserializer(_data, _length, _shrink_buffer_threshold) {
}
deserializer::deserializer(const deserializer &_other)
diff --git a/implementation/service_discovery/src/service_discovery_impl.cpp b/implementation/service_discovery/src/service_discovery_impl.cpp index 94a03b4..e33027a 100644 --- a/implementation/service_discovery/src/service_discovery_impl.cpp +++ b/implementation/service_discovery/src/service_discovery_impl.cpp @@ -25,6 +25,7 @@ #include "../../configuration/include/configuration.hpp" #include "../../configuration/include/internal.hpp" #include "../../endpoints/include/endpoint.hpp" +#include "../../endpoints/include/client_endpoint.hpp" #include "../../endpoints/include/endpoint_definition.hpp" #include "../../endpoints/include/tcp_server_endpoint_impl.hpp" #include "../../endpoints/include/udp_server_endpoint_impl.hpp" @@ -41,8 +42,12 @@ service_discovery_impl::service_discovery_impl(service_discovery_host *_host) host_(_host), port_(VSOMEIP_SD_DEFAULT_PORT), reliable_(false), - serializer_(std::make_shared<serializer>()), - deserializer_(std::make_shared<deserializer>()), + serializer_( + std::make_shared<serializer>( + host_->get_configuration()->get_buffer_shrink_threshold())), + deserializer_( + std::make_shared<deserializer>( + host_->get_configuration()->get_buffer_shrink_threshold())), ttl_timer_(_host->get_io()), smallest_ttl_(DEFAULT_TTL), ttl_(VSOMEIP_SD_DEFAULT_TTL), @@ -55,7 +60,7 @@ service_discovery_impl::service_discovery_impl(service_discovery_host *_host) cyclic_offer_delay_(VSOMEIP_SD_DEFAULT_CYCLIC_OFFER_DELAY), offer_debounce_timer_(_host->get_io()), main_phase_timer_(_host->get_io()), - is_suspended_(false) { + is_suspended_(true) { std::chrono::seconds smallest_ttl(DEFAULT_TTL); smallest_ttl_ = std::chrono::duration_cast<std::chrono::milliseconds>(smallest_ttl); @@ -81,6 +86,7 @@ void service_discovery_impl::init() { host_->get_configuration(); if (its_configuration) { unicast_ = its_configuration->get_unicast_address(); + sd_multicast_ = its_configuration->get_sd_multicast(); port_ = its_configuration->get_sd_port(); reliable_ = (its_configuration->get_sd_protocol() @@ -88,14 +94,6 @@ void service_discovery_impl::init() { max_message_size_ = (reliable_ ? VSOMEIP_MAX_TCP_SD_PAYLOAD : VSOMEIP_MAX_UDP_SD_PAYLOAD); - serializer_->create_data( - reliable_ ? - VSOMEIP_MAX_TCP_MESSAGE_SIZE : - VSOMEIP_MAX_UDP_MESSAGE_SIZE); - - endpoint_ = host_->create_service_discovery_endpoint( - its_configuration->get_sd_multicast(), port_, reliable_); - ttl_ = its_configuration->get_sd_ttl(); // generate random initial delay based on initial delay min and max @@ -135,6 +133,26 @@ void service_discovery_impl::init() { } void service_discovery_impl::start() { + if (!endpoint_) { + endpoint_ = host_->create_service_discovery_endpoint( + sd_multicast_, port_, reliable_); + if (!endpoint_) { + VSOMEIP_ERROR << "Couldn't start service discovery"; + return; + } + // Send out pending find services messages if have any + bool send_find(false); + { + std::lock_guard<std::mutex> its_lock(requested_mutex_); + if (requested_.size()) { + send_find = true; + } + } + if (send_find) { + send(false, true); + } + } + is_suspended_ = false; start_main_phase_timer(); start_offer_debounce_timer(true); @@ -174,13 +192,14 @@ void service_discovery_impl::request_service(service_t _service, > (_major, _minor, _ttl); } } - if (is_new_request) { + if (is_new_request && !is_suspended_) { send(false, true); } } void service_discovery_impl::release_service(service_t _service, instance_t _instance) { + std::lock_guard<std::mutex> its_lock(requested_mutex_); auto find_service = requested_.find(_service); if (find_service != requested_.end()) { find_service->second.erase(_instance); @@ -189,6 +208,7 @@ void service_discovery_impl::release_service(service_t _service, std::shared_ptr<request> service_discovery_impl::find_request(service_t _service, instance_t _instance) { + std::lock_guard<std::mutex> its_lock(requested_mutex_); auto find_service = requested_.find(_service); if (find_service != requested_.end()) { auto find_instance = find_service->second.find(_instance); @@ -309,23 +329,44 @@ void service_discovery_impl::get_subscription_endpoints( _unreliable = host_->find_or_create_remote_client(_service, _instance, false, _client); if (_unreliable) { - *_has_address = _unreliable->get_remote_address(*_address); + std::shared_ptr<client_endpoint> its_client_endpoint = + std::dynamic_pointer_cast<client_endpoint>(_unreliable); + if (its_client_endpoint) { + *_has_address = its_client_endpoint->get_remote_address( + *_address); + } } if (_reliable) { - *_has_address = *_has_address - || _reliable->get_remote_address(*_address); + std::shared_ptr<client_endpoint> its_client_endpoint = + std::dynamic_pointer_cast<client_endpoint>(_reliable); + if (its_client_endpoint) { + *_has_address = *_has_address + || its_client_endpoint->get_remote_address( + *_address); + } } break; case subscription_type_e::SU_PREFER_UNRELIABLE: _unreliable = host_->find_or_create_remote_client(_service, _instance, false, _client); if (_unreliable) { - *_has_address = _unreliable->get_remote_address(*_address); + std::shared_ptr<client_endpoint> its_client_endpoint = + std::dynamic_pointer_cast<client_endpoint>(_unreliable); + if (its_client_endpoint) { + *_has_address = its_client_endpoint->get_remote_address( + *_address); + } } else { _reliable = host_->find_or_create_remote_client(_service, _instance, true, _client); if (_reliable) { - *_has_address = _reliable->get_remote_address(*_address); + std::shared_ptr<client_endpoint> its_client_endpoint = + std::dynamic_pointer_cast<client_endpoint>( + _reliable); + if (its_client_endpoint) { + *_has_address = its_client_endpoint->get_remote_address( + *_address); + } } } break; @@ -333,12 +374,23 @@ void service_discovery_impl::get_subscription_endpoints( _reliable = host_->find_or_create_remote_client(_service, _instance, true, _client); if (_reliable) { - *_has_address = _reliable->get_remote_address(*_address); + std::shared_ptr<client_endpoint> its_client_endpoint = + std::dynamic_pointer_cast<client_endpoint>(_reliable); + if (its_client_endpoint) { + *_has_address = its_client_endpoint->get_remote_address( + *_address); + } } else { - _unreliable = host_->find_or_create_remote_client(_service, - _instance, false, _client); + _unreliable = host_->find_or_create_remote_client(_service, + _instance, false, _client); if (_unreliable) { - *_has_address = _unreliable->get_remote_address(*_address); + std::shared_ptr<client_endpoint> its_client_endpoint = + std::dynamic_pointer_cast<client_endpoint>( + _unreliable); + if (its_client_endpoint) { + *_has_address = its_client_endpoint->get_remote_address( + *_address); + } } } break; @@ -347,14 +399,24 @@ void service_discovery_impl::get_subscription_endpoints( _instance, false, _client); if (_unreliable) { - *_has_address = _unreliable->get_remote_address(*_address); + std::shared_ptr<client_endpoint> its_client_endpoint = + std::dynamic_pointer_cast<client_endpoint>(_unreliable); + if (its_client_endpoint) { + *_has_address = its_client_endpoint->get_remote_address( + *_address); + } } break; case subscription_type_e::SU_RELIABLE: _reliable = host_->find_or_create_remote_client(_service, _instance, - true, _client); + true, _client); if (_reliable) { - *_has_address = _reliable->get_remote_address(*_address); + std::shared_ptr<client_endpoint> its_client_endpoint = + std::dynamic_pointer_cast<client_endpoint>(_reliable); + if (its_client_endpoint) { + *_has_address = its_client_endpoint->get_remote_address( + *_address); + } } } } @@ -384,11 +446,25 @@ void service_discovery_impl::unsubscribe(service_t _service, found_eventgroup->second.erase(_client); auto endpoint = its_subscription->get_endpoint(false); if (endpoint) { - has_address = endpoint->get_remote_address(its_address); + std::shared_ptr<client_endpoint> its_client_endpoint = + std::dynamic_pointer_cast<client_endpoint>( + endpoint); + if (its_client_endpoint) { + has_address = + its_client_endpoint->get_remote_address( + its_address); + } } else { endpoint = its_subscription->get_endpoint(true); if (endpoint) { - has_address = endpoint->get_remote_address(its_address); + std::shared_ptr<client_endpoint> its_client_endpoint = + std::dynamic_pointer_cast< + client_endpoint>(endpoint); + if (its_client_endpoint) { + has_address = + its_client_endpoint->get_remote_address( + its_address); + } } else { return; } @@ -422,6 +498,70 @@ void service_discovery_impl::unsubscribe_all(service_t _service, instance_t _ins } } +void service_discovery_impl::unsubscribe_client(service_t _service, + instance_t _instance, + client_t _client) { + std::shared_ptr<runtime> its_runtime = runtime_.lock(); + if (!its_runtime) { + return; + } + std::shared_ptr < message_impl > its_message = its_runtime->create_message(); + boost::asio::ip::address its_address; + bool has_address(false); + { + std::lock_guard<std::mutex> its_lock(subscribed_mutex_); + std::shared_ptr < subscription > its_subscription; + auto found_service = subscribed_.find(_service); + if (found_service != subscribed_.end()) { + auto found_instance = found_service->second.find(_instance); + if (found_instance != found_service->second.end()) { + for (auto &found_eventgroup : found_instance->second) { + auto found_client = found_eventgroup.second.find(_client); + if (found_client != found_eventgroup.second.end()) { + its_subscription = found_client->second; + its_subscription->set_ttl(0); + found_eventgroup.second.erase(_client); + if (!has_address) { + auto endpoint = its_subscription->get_endpoint( + false); + if (endpoint) { + std::shared_ptr<client_endpoint> its_client_endpoint = + std::dynamic_pointer_cast< + client_endpoint>(endpoint); + if (its_client_endpoint) { + has_address = + its_client_endpoint->get_remote_address( + its_address); + } + } else { + endpoint = its_subscription->get_endpoint(true); + if (endpoint) { + std::shared_ptr<client_endpoint> its_client_endpoint = + std::dynamic_pointer_cast< + client_endpoint>(endpoint); + if (its_client_endpoint) { + has_address = + its_client_endpoint->get_remote_address( + its_address); + } + } else { + return; + } + } + } + insert_subscription(its_message, _service, _instance, + found_eventgroup.first, its_subscription, true, + true); + } + } + } + } + } + if (has_address && 0 < its_message->get_entries().size()) { + serialize_and_send(its_message, its_address); + } +} + std::pair<session_t, bool> service_discovery_impl::get_session( const boost::asio::ip::address &_address) { std::pair<session_t, bool> its_session; @@ -628,14 +768,14 @@ void service_discovery_impl::insert_option( } void service_discovery_impl::insert_find_entries( - std::shared_ptr<message_impl> &_message, requests_t &_requests, + std::shared_ptr<message_impl> &_message, uint32_t _start, uint32_t &_size, bool &_done) { std::lock_guard<std::mutex> its_lock(requested_mutex_); uint32_t its_size(0); uint32_t i = 0; _done = true; - for (auto its_service : _requests) { + for (auto its_service : requested_) { for (auto its_instance : its_service.second) { auto its_request = its_instance.second; uint8_t its_sent_counter = its_request->get_sent_counter(); @@ -838,7 +978,7 @@ bool service_discovery_impl::send(bool _is_announcing, bool _is_find) { its_message = its_runtime->create_message(); its_messages.push_back(its_message); - insert_find_entries(its_message, requested_, its_start, its_size, is_done); + insert_find_entries(its_message, its_start, its_size, is_done); its_start += its_size / VSOMEIP_SOMEIP_SD_ENTRY_SIZE; }; its_remaining -= its_size; @@ -868,14 +1008,16 @@ void service_discovery_impl::on_message(const byte_t *_data, length_t _length, msg << "sdi::on_message: "; for (length_t i = 0; i < _length; ++i) msg << std::hex << std::setw(2) << std::setfill('0') << (int)_data[i] << " "; - VSOMEIP_DEBUG << msg.str(); + VSOMEIP_INFO << msg.str(); #endif if(is_suspended_) { return; } + current_remote_address_ = _sender; deserializer_->set_data(_data, _length); std::shared_ptr < message_impl > its_message(deserializer_->deserialize_sd_message()); + deserializer_->reset(); if (its_message) { // ignore all SD messages with source address equal to node's unicast address if (!check_source_address(_sender)) { @@ -1195,13 +1337,12 @@ void service_discovery_impl::send_unicast_offer_service( uint32_t its_size(max_message_size_); insert_offer_service(its_message, _service, _instance, _info, its_size); - const boost::asio::ip::address its_address(get_current_remote_address()); - if (its_address.is_unspecified()) { + if (current_remote_address_.is_unspecified()) { VSOMEIP_ERROR << "service_discovery_impl::" "send_unicast_offer_service current remote address " "is unspecified, won't send offer."; } else { - serialize_and_send(its_message, its_address); + serialize_and_send(its_message, current_remote_address_); } } } @@ -1891,14 +2032,13 @@ bool service_discovery_impl::is_tcp_connected(service_t _service, std::shared_ptr<serviceinfo> its_info = found_instance->second; if(its_info) { //get reliable server endpoint - auto its_reliable_endpoint = its_info->get_endpoint(true); - if(its_reliable_endpoint) { - std::shared_ptr<tcp_server_endpoint_impl> its_ptr(std::static_pointer_cast<tcp_server_endpoint_impl>(its_reliable_endpoint)); - if( !its_ptr->is_established(its_endpoint)) { - } - else { - is_connected = true; - } + auto its_reliable_server_endpoint = + std::dynamic_pointer_cast<tcp_server_endpoint_impl>( + its_info->get_endpoint(true)); + if (its_reliable_server_endpoint + && its_reliable_server_endpoint->is_established( + its_endpoint)) { + is_connected = true; } } } @@ -1947,24 +2087,6 @@ void service_discovery_impl::check_ttl(const boost::system::error_code &_error) } } -boost::asio::ip::address service_discovery_impl::get_current_remote_address() const { - boost::asio::ip::address its_address; - if (reliable_) { - auto endpoint = std::dynamic_pointer_cast<tcp_server_endpoint_impl>(endpoint_); - if (endpoint && !endpoint->get_remote_address(its_address)) { - VSOMEIP_ERROR << "service_discovery_impl::get_current_remote_address: " - "couldn't determine remote address (reliable)"; - } - } else { - auto endpoint = std::dynamic_pointer_cast<udp_server_endpoint_impl>(endpoint_); - if (endpoint && !endpoint->get_remote_address(its_address)) { - VSOMEIP_ERROR << "service_discovery_impl::get_current_remote_address: " - "couldn't determine remote address (unreliable)"; - } - } - return its_address; -} - bool service_discovery_impl::check_static_header_fields( const std::shared_ptr<const message> &_message) const { if(_message->get_protocol_version() != protocol_version) { @@ -2031,7 +2153,14 @@ void service_discovery_impl::send_subscriptions(service_t _service, instance_t _ found_client->second->set_endpoint(its_unreliable, false); } if (endpoint) { - endpoint->get_remote_address(its_address); + if (!has_address) { + VSOMEIP_WARNING << "service_discovery_impl::" + "send_subscriptions couldn't determine " + "address for service.instance: " + << std::hex << std::setw(4) << std::setfill('0') + << _service << "." << _instance; + continue; + } std::shared_ptr<message_impl> its_message = its_runtime->create_message(); @@ -2119,7 +2248,7 @@ bool service_discovery_impl::check_ipv4_address( } else { #if 0 - VSOMEIP_DEBUG << "First 3 triples of subscribers endpoint IP address are valid!"; + VSOMEIP_INFO << "First 3 triples of subscribers endpoint IP address are valid!"; #endif } } @@ -2418,16 +2547,18 @@ bool service_discovery_impl::send_stop_offer( std::shared_ptr<serviceinfo> _info) { std::shared_ptr < runtime > its_runtime = runtime_.lock(); if (its_runtime) { - std::vector<std::shared_ptr<message_impl>> its_messages; - std::shared_ptr<message_impl> its_message; - its_message = its_runtime->create_message(); - its_messages.push_back(its_message); + if (_info->get_endpoint(false) || _info->get_endpoint(true)) { + std::vector<std::shared_ptr<message_impl>> its_messages; + std::shared_ptr<message_impl> its_message; + its_message = its_runtime->create_message(); + its_messages.push_back(its_message); - uint32_t its_size(max_message_size_); - insert_offer_service(its_message, _service, _instance, _info, its_size); + uint32_t its_size(max_message_size_); + insert_offer_service(its_message, _service, _instance, _info, its_size); - // Serialize and send - return serialize_and_send_messages(its_messages); + // Serialize and send + return serialize_and_send_messages(its_messages); + } } return false; } diff --git a/implementation/tracing/include/trace_header.hpp b/implementation/tracing/include/trace_header.hpp index 9e86d84..47b2e22 100644 --- a/implementation/tracing/include/trace_header.hpp +++ b/implementation/tracing/include/trace_header.hpp @@ -10,6 +10,8 @@ #include <vsomeip/primitive_types.hpp> +#include <boost/asio/ip/address_v4.hpp> + #define VSOMEIP_TRACE_HEADER_SIZE 8 namespace vsomeip { @@ -28,6 +30,8 @@ enum class protocol_e : uint8_t { struct trace_header { bool prepare(const std::shared_ptr<endpoint> &_endpoint, bool _is_sending); bool prepare(const endpoint* _endpoint, bool _is_sending); + void prepare(const boost::asio::ip::address_v4 &_address, + std::uint16_t _port, protocol_e _protocol, bool _is_sending); byte_t data_[VSOMEIP_TRACE_HEADER_SIZE]; }; diff --git a/implementation/tracing/src/trace_header.cpp b/implementation/tracing/src/trace_header.cpp index 2f293ee..7e4c700 100644 --- a/implementation/tracing/src/trace_header.cpp +++ b/implementation/tracing/src/trace_header.cpp @@ -7,6 +7,7 @@ #include "../include/trace_header.hpp" #include "../../endpoints/include/endpoint.hpp" +#include "../../endpoints/include/client_endpoint.hpp" #include "../../utility/include/byteorder.hpp" namespace vsomeip { @@ -17,39 +18,49 @@ bool trace_header::prepare(const std::shared_ptr<endpoint> &_endpoint, bool _is_ } bool trace_header::prepare(const endpoint *_endpoint, bool _is_sending) { - boost::asio::ip::address its_address; - if (_endpoint && _endpoint->get_remote_address(its_address)) { - if (its_address.is_v6()) - return false; - - unsigned long its_address_as_long = its_address.to_v4().to_ulong(); - - data_[0] = VSOMEIP_LONG_BYTE0(its_address_as_long); - data_[1] = VSOMEIP_LONG_BYTE1(its_address_as_long); - data_[2] = VSOMEIP_LONG_BYTE2(its_address_as_long); - data_[3] = VSOMEIP_LONG_BYTE3(its_address_as_long); - - unsigned short its_port = _endpoint->get_remote_port(); - data_[4] = VSOMEIP_WORD_BYTE0(its_port); - data_[5] = VSOMEIP_WORD_BYTE1(its_port); - - if (_endpoint->is_local()) { - data_[6] = static_cast<byte_t>(protocol_e::local); - } else { - if (_endpoint->is_reliable()) { - data_[6] = static_cast<byte_t>(protocol_e::tcp); + if (_endpoint) { + const client_endpoint* its_client_endpoint = + dynamic_cast<const client_endpoint*>(_endpoint); + if (its_client_endpoint) { + + boost::asio::ip::address its_address; + its_client_endpoint->get_remote_address(its_address); + if (its_address.is_v6()) { + return false; + } + + unsigned short its_port = its_client_endpoint->get_remote_port(); + protocol_e its_protocol(protocol_e::unknown); + if (_endpoint->is_local()) { + its_protocol = protocol_e::local; } else { - data_[6] = static_cast<byte_t>(protocol_e::udp); + if (_endpoint->is_reliable()) { + its_protocol = protocol_e::tcp; + } else { + its_protocol = protocol_e::udp; + } } + prepare(its_address.to_v4(), its_port, its_protocol, _is_sending); + return true; } - - data_[7] = static_cast<byte_t>(_is_sending); - - } else { - std::memset(data_, 0, VSOMEIP_TRACE_HEADER_SIZE); } + std::memset(data_, 0, VSOMEIP_TRACE_HEADER_SIZE); return true; } +void trace_header::prepare(const boost::asio::ip::address_v4 &_address, + std::uint16_t _port, protocol_e _protocol, + bool _is_sending) { + unsigned long its_address_as_long = _address.to_ulong(); + data_[0] = VSOMEIP_LONG_BYTE0(its_address_as_long); + data_[1] = VSOMEIP_LONG_BYTE1(its_address_as_long); + data_[2] = VSOMEIP_LONG_BYTE2(its_address_as_long); + data_[3] = VSOMEIP_LONG_BYTE3(its_address_as_long); + data_[4] = VSOMEIP_WORD_BYTE0(_port); + data_[5] = VSOMEIP_WORD_BYTE1(_port); + data_[6] = static_cast<byte_t>(_protocol); + data_[7] = static_cast<byte_t>(_is_sending); +} + } // namespace tc } // namespace vsomeip diff --git a/implementation/utility/include/utility.hpp b/implementation/utility/include/utility.hpp index 7e69401..2f8fc0f 100644 --- a/implementation/utility/include/utility.hpp +++ b/implementation/utility/include/utility.hpp @@ -104,6 +104,10 @@ public: } static uint16_t its_configuration_refs__; + +private: + static bool is_bigger_last_assigned_client_id(client_t _client); + static void set_client_id_lowbyte(client_t _client); }; } // namespace vsomeip diff --git a/implementation/utility/src/utility.cpp b/implementation/utility/src/utility.cpp index d91dd56..51785ff 100644 --- a/implementation/utility/src/utility.cpp +++ b/implementation/utility/src/utility.cpp @@ -148,7 +148,7 @@ bool utility::auto_configuration_init(const std::shared_ptr<configuration> &_con if (configuration_data_mutex) { if (GetLastError() == ERROR_ALREADY_EXISTS) { - VSOMEIP_DEBUG << "utility::auto_configuration_init: use existing shared memory"; + VSOMEIP_INFO << "utility::auto_configuration_init: use existing shared memory"; // mapping already exists, wait for mutex release and map in DWORD waitResult = WaitForSingleObject(configuration_data_mutex, INFINITE); @@ -190,7 +190,7 @@ bool utility::auto_configuration_init(const std::shared_ptr<configuration> &_con } } else { - VSOMEIP_DEBUG << "utility::auto_configuration_init: create new shared memory"; + VSOMEIP_INFO << "utility::auto_configuration_init: create new shared memory"; // create and init new mapping its_descriptor = CreateFileMapping( @@ -360,11 +360,11 @@ bool utility::auto_configuration_init(const std::shared_ptr<configuration> &_con pthread_mutex_lock(&the_configuration_data__->mutex_); its_configuration_refs__++; pthread_mutex_unlock(&the_configuration_data__->mutex_); + } - if (-1 == ::close(its_descriptor)) { - VSOMEIP_ERROR << "utility::auto_configuration_init: " - "close failed: " << std::strerror(errno); - } + if (-1 == ::close(its_descriptor)) { + VSOMEIP_ERROR << "utility::auto_configuration_init: " + "close failed: " << std::strerror(errno); } } } @@ -413,7 +413,7 @@ void utility::auto_configuration_exit(client_t _client) { VSOMEIP_ERROR << "utility::auto_configuration_exit: " "munmap failed: " << std::strerror(errno); } else { - VSOMEIP_DEBUG << "utility::auto_configuration_exit: " + VSOMEIP_INFO << "utility::auto_configuration_exit: " "munmap succeeded."; the_configuration_data__ = nullptr; if (unlink_shm) { @@ -430,10 +430,7 @@ bool utility::is_used_client_id(client_t _client) { for (int i = 0; i < the_configuration_data__->max_used_client_ids_index_; i++) { - if (the_configuration_data__->used_client_ids_[i] == _client - || _client - < (the_configuration_data__->client_base_ - + the_configuration_data__->max_assigned_client_id_low_byte_)) { + if (the_configuration_data__->used_client_ids_[i] == _client) { return true; } } @@ -477,7 +474,7 @@ client_t utility::request_client_id(const std::shared_ptr<configuration> &_confi #else pthread_mutex_unlock(&the_configuration_data__->mutex_); #endif - return VSOMEIP_DIAGNOSIS_ADDRESS; + return ILLEGAL_CLIENT; } } else if (its_name == "" && the_configuration_data__->routing_manager_host_ == 0x0000) { set_client_as_manager_host = true; @@ -497,27 +494,63 @@ client_t utility::request_client_id(const std::shared_ptr<configuration> &_confi return ILLEGAL_CLIENT; } - bool configured_and_not_used(false); - if (_client != ILLEGAL_CLIENT && !is_used_client_id(_client)) { - configured_and_not_used = true; - } - - if (_client == ILLEGAL_CLIENT || is_used_client_id(_client)) { - _client = the_configuration_data__->client_base_; + bool use_autoconfig = true; + if (_name != "" && _client != ILLEGAL_CLIENT) { // preconfigured client id + // check if application name has preconfigured client id in json + const client_t its_preconfigured_client_id = _config->get_id(_name); + if (its_preconfigured_client_id) { + // preconfigured client id for application name present in json + if (its_preconfigured_client_id == _client) { + // preconfigured client id for application name present in json + // and requested + if (!is_used_client_id(_client)) { + use_autoconfig = false; + } + } else { + // preconfigured client id for application name present in + // json, but different client id requested + if (!is_used_client_id(its_preconfigured_client_id)) { + // assign preconfigured client id if not already used + _client = its_preconfigured_client_id; + use_autoconfig = false; + } else if (!is_used_client_id(_client)) { + // if preconfigured client id is already used and + // requested is unused assign requested + use_autoconfig = false; + } + } + } } - while (is_used_client_id(_client)) { - if ((_client & 0x00FF) + 1 > VSOMEIP_MAX_CLIENTS) { + if (use_autoconfig) { + if (_client == ILLEGAL_CLIENT || is_used_client_id(_client)) { _client = the_configuration_data__->client_base_; - the_configuration_data__->max_assigned_client_id_low_byte_ = 0; - } else { - _client++; } - } - if (!configured_and_not_used) { - the_configuration_data__->max_assigned_client_id_low_byte_ = - static_cast<unsigned char>((_client & 0x00FF) - % VSOMEIP_MAX_CLIENTS); + int increase_count = 0; + while (is_used_client_id(_client) + || !is_bigger_last_assigned_client_id(_client) + || _config->is_configured_client_id(_client)) { + if ((_client & 0xFF) + 1 > VSOMEIP_MAX_CLIENTS) { + _client = the_configuration_data__->client_base_; + the_configuration_data__->max_assigned_client_id_low_byte_ = 0; + } else { + _client++; + increase_count++; + if (increase_count > VSOMEIP_MAX_CLIENTS) { + VSOMEIP_ERROR << "Max amount of possible concurrent active" + << " vsomeip applications reached."; +#ifdef WIN32 + BOOL releaseResult = ReleaseMutex(configuration_data_mutex); + assert(releaseResult); + (void)releaseResult; +#else + pthread_mutex_unlock(&the_configuration_data__->mutex_); +#endif + return ILLEGAL_CLIENT; + } + } + } + set_client_id_lowbyte(_client); } if (set_client_as_manager_host) { @@ -538,7 +571,7 @@ client_t utility::request_client_id(const std::shared_ptr<configuration> &_confi #endif return _client; } - return VSOMEIP_DIAGNOSIS_ADDRESS; + return ILLEGAL_CLIENT; } void utility::release_client_id(client_t _client) { @@ -550,12 +583,13 @@ void utility::release_client_id(client_t _client) { pthread_mutex_lock(&the_configuration_data__->mutex_); #endif int i = 0; - while (the_configuration_data__->used_client_ids_[i] != _client && - i < the_configuration_data__->max_used_client_ids_index_) { - i++; + for (; i < the_configuration_data__->max_used_client_ids_index_; i++) { + if (the_configuration_data__->used_client_ids_[i] == _client) { + break; + } } - if (i <= the_configuration_data__->max_used_client_ids_index_) { + if (i < the_configuration_data__->max_used_client_ids_index_) { the_configuration_data__->max_used_client_ids_index_--; for (; i < the_configuration_data__->max_used_client_ids_index_; i++) { the_configuration_data__->used_client_ids_[i] @@ -614,4 +648,17 @@ void utility::set_routing_manager_host(client_t _client) { #endif } +bool utility::is_bigger_last_assigned_client_id(client_t _client) { + return _client + > ((the_configuration_data__->client_base_ & 0xFF00) + + the_configuration_data__->max_assigned_client_id_low_byte_); +} + +void utility::set_client_id_lowbyte(client_t _client) { + const unsigned char its_low_byte = + static_cast<unsigned char>(_client & 0xFF); + the_configuration_data__->max_assigned_client_id_low_byte_ = its_low_byte + % VSOMEIP_MAX_CLIENTS; +} + } // namespace vsomeip diff --git a/interface/vsomeip/defines.hpp b/interface/vsomeip/defines.hpp index 2323c19..d75b028 100644 --- a/interface/vsomeip/defines.hpp +++ b/interface/vsomeip/defines.hpp @@ -8,8 +8,10 @@ #define VSOMEIP_PROTOCOL_VERSION 0x1 -#define VSOMEIP_MAX_LOCAL_MESSAGE_SIZE 32768 -#define VSOMEIP_MAX_TCP_MESSAGE_SIZE 4095 +// 0 = unlimited, if not specified otherwise via configuration file +#define VSOMEIP_MAX_LOCAL_MESSAGE_SIZE 0 +// 0 = unlimited, if not specified otherwise via configuration file +#define VSOMEIP_MAX_TCP_MESSAGE_SIZE 0 #define VSOMEIP_MAX_UDP_MESSAGE_SIZE 1416 #define VSOMEIP_PACKET_SIZE VSOMEIP_MAX_UDP_MESSAGE_SIZE diff --git a/interface/vsomeip/runtime.hpp b/interface/vsomeip/runtime.hpp index 14ecb60..00dd069 100644 --- a/interface/vsomeip/runtime.hpp +++ b/interface/vsomeip/runtime.hpp @@ -50,6 +50,8 @@ public: virtual std::shared_ptr<application> get_application( const std::string &_name) const = 0; + + virtual void remove_application( const std::string &_name) = 0; }; } // namespace vsomeip diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index e84e1a4..ed4e983 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -186,6 +186,7 @@ if(NOT ${TESTS_BAT}) ${Boost_LIBRARIES} ${DL_LIBRARY} ${CMAKE_THREAD_LIBS_INIT} + ${TEST_LINK_LIBRARIES} ) set(TEST_MAGIC_COOKIES_SERVICE ${TEST_MAGIC_COOKIES_NAME}_service) @@ -195,6 +196,7 @@ if(NOT ${TESTS_BAT}) ${Boost_LIBRARIES} ${DL_LIBRARY} ${CMAKE_THREAD_LIBS_INIT} + ${TEST_LINK_LIBRARIES} ) # Copy config file for client into $BUILDDIR/test @@ -665,6 +667,15 @@ if(NOT ${TESTS_BAT}) ${PROJECT_BINARY_DIR}/test/${TEST_EXTERNAL_LOCAL_PAYLOAD_CLIENT_LOCAL_AND_EXTERNAL_STARTER} ${TEST_PAYLOAD_CLIENT} ) + + ############################################################################## + set(TEST_LOCAL_PAYLOAD_HUGE_NAME local_payload_test_huge_payload) + # Copy bashscript to start client and server $BUILDDIR/test + set(TEST_LOCAL_PAYLOAD_HUGE_STARTER ${TEST_LOCAL_PAYLOAD_HUGE_NAME}_starter.sh) + copy_to_builddir(${PROJECT_SOURCE_DIR}/test/payload_tests/${TEST_LOCAL_PAYLOAD_HUGE_STARTER} + ${PROJECT_BINARY_DIR}/test/${TEST_LOCAL_PAYLOAD_HUGE_STARTER} + ${TEST_PAYLOAD_CLIENT} + ) endif() ############################################################################## @@ -700,6 +711,22 @@ if(NOT ${TESTS_BAT}) ) # Copy config file for client and service into $BUILDDIR/test + set(TEST_LOCAL_BIG_PAYLOAD_CONFIG_FILE_RANDOM ${TEST_BIG_PAYLOAD_NAME}_local_random.json) + copy_to_builddir( + ${PROJECT_SOURCE_DIR}/test/big_payload_tests/${TEST_LOCAL_BIG_PAYLOAD_CONFIG_FILE_RANDOM} + ${PROJECT_BINARY_DIR}/test/${TEST_LOCAL_BIG_PAYLOAD_CONFIG_FILE_RANDOM} + ${TEST_BIG_PAYLOAD_SERVICE} + ) + + # Copy config file for client and service into $BUILDDIR/test + set(TEST_LOCAL_BIG_PAYLOAD_CONFIG_FILE_LIMITED ${TEST_BIG_PAYLOAD_NAME}_local_limited.json) + copy_to_builddir( + ${PROJECT_SOURCE_DIR}/test/big_payload_tests/${TEST_LOCAL_BIG_PAYLOAD_CONFIG_FILE_LIMITED} + ${PROJECT_BINARY_DIR}/test/${TEST_LOCAL_BIG_PAYLOAD_CONFIG_FILE_LIMITED} + ${TEST_BIG_PAYLOAD_SERVICE} + ) + + # Copy config file for client and service into $BUILDDIR/test set(TEST_EXTERNAL_BIG_PAYLOAD_CLIENT_CONFIG_FILE ${TEST_BIG_PAYLOAD_NAME}_tcp_client.json) configure_file( ${PROJECT_SOURCE_DIR}/test/big_payload_tests/conf/${TEST_EXTERNAL_BIG_PAYLOAD_CLIENT_CONFIG_FILE}.in @@ -723,6 +750,30 @@ if(NOT ${TESTS_BAT}) ${TEST_BIG_PAYLOAD_SERVICE} ) + # Copy config file for client and service into $BUILDDIR/test + set(TEST_EXTERNAL_BIG_PAYLOAD_CLIENT_CONFIG_FILE_RANDOM ${TEST_BIG_PAYLOAD_NAME}_tcp_client_random.json) + configure_file( + ${PROJECT_SOURCE_DIR}/test/big_payload_tests/conf/${TEST_EXTERNAL_BIG_PAYLOAD_CLIENT_CONFIG_FILE_RANDOM}.in + ${PROJECT_SOURCE_DIR}/test/big_payload_tests/${TEST_EXTERNAL_BIG_PAYLOAD_CLIENT_CONFIG_FILE_RANDOM} + @ONLY) + copy_to_builddir( + ${PROJECT_SOURCE_DIR}/test/big_payload_tests/${TEST_EXTERNAL_BIG_PAYLOAD_CLIENT_CONFIG_FILE_RANDOM} + ${PROJECT_BINARY_DIR}/test/${TEST_EXTERNAL_BIG_PAYLOAD_CLIENT_CONFIG_FILE_RANDOM} + ${TEST_BIG_PAYLOAD_CLIENT} + ) + + # Copy config file for client and service into $BUILDDIR/test + set(TEST_EXTERNAL_BIG_PAYLOAD_SERVICE_CONFIG_FILE_RANDOM ${TEST_BIG_PAYLOAD_NAME}_tcp_service_random.json) + configure_file( + ${PROJECT_SOURCE_DIR}/test/big_payload_tests/conf/${TEST_EXTERNAL_BIG_PAYLOAD_SERVICE_CONFIG_FILE_RANDOM}.in + ${PROJECT_SOURCE_DIR}/test/big_payload_tests/${TEST_EXTERNAL_BIG_PAYLOAD_SERVICE_CONFIG_FILE_RANDOM} + @ONLY) + copy_to_builddir( + ${PROJECT_SOURCE_DIR}/test/big_payload_tests/${TEST_EXTERNAL_BIG_PAYLOAD_SERVICE_CONFIG_FILE_RANDOM} + ${PROJECT_BINARY_DIR}/test/${TEST_EXTERNAL_BIG_PAYLOAD_SERVICE_CONFIG_FILE_RANDOM} + ${TEST_BIG_PAYLOAD_SERVICE} + ) + # Copy bashscript to start client local to $BUILDDIR/test set(TEST_LOCAL_BIG_PAYLOAD_CLIENT_START_SCRIPT ${TEST_BIG_PAYLOAD_NAME}_client_local_start.sh) copy_to_builddir(${PROJECT_SOURCE_DIR}/test/big_payload_tests/${TEST_LOCAL_BIG_PAYLOAD_CLIENT_START_SCRIPT} @@ -739,6 +790,8 @@ if(NOT ${TESTS_BAT}) # Copy bashscript to start client and server $BUILDDIR/test set(TEST_LOCAL_BIG_PAYLOAD_NAME big_payload_test_local) + set(TEST_LOCAL_BIG_PAYLOAD_NAME_RANDOM big_payload_test_local_random) + set(TEST_LOCAL_BIG_PAYLOAD_NAME_LIMITED big_payload_test_local_limited) set(TEST_LOCAL_BIG_PAYLOAD_STARTER ${TEST_LOCAL_BIG_PAYLOAD_NAME}_starter.sh) copy_to_builddir(${PROJECT_SOURCE_DIR}/test/big_payload_tests/${TEST_LOCAL_BIG_PAYLOAD_STARTER} ${PROJECT_BINARY_DIR}/test/${TEST_LOCAL_BIG_PAYLOAD_STARTER} @@ -747,6 +800,8 @@ if(NOT ${TESTS_BAT}) # Copy bashscript to start client for external test into $BUILDDIR/test set(TEST_EXTERNAL_BIG_PAYLOAD_NAME big_payload_test_external) + set(TEST_EXTERNAL_BIG_PAYLOAD_NAME_RANDOM big_payload_test_external_random) + set(TEST_EXTERNAL_BIG_PAYLOAD_NAME_LIMITED big_payload_test_external_limited) set(TEST_EXTERNAL_BIG_PAYLOAD_STARTER ${TEST_EXTERNAL_BIG_PAYLOAD_NAME}_starter.sh) copy_to_builddir(${PROJECT_SOURCE_DIR}/test/big_payload_tests/${TEST_EXTERNAL_BIG_PAYLOAD_STARTER} ${PROJECT_BINARY_DIR}/test/${TEST_EXTERNAL_BIG_PAYLOAD_STARTER} @@ -783,6 +838,18 @@ if(NOT ${TESTS_BAT}) ${TEST_LINK_LIBRARIES} ) + set(TEST_CLIENT_ID_UTILITY ${TEST_CLIENT_ID_NAME}_utility) + add_executable(${TEST_CLIENT_ID_UTILITY} + client_id_tests/${TEST_CLIENT_ID_UTILITY}.cpp + ${PROJECT_SOURCE_DIR}/implementation/utility/src/utility.cpp) + target_link_libraries(${TEST_CLIENT_ID_UTILITY} + vsomeip + vsomeip-cfg + ${Boost_LIBRARIES} + ${DL_LIBRARY} + ${TEST_LINK_LIBRARIES} + ) + # Copy config files for test into $BUILDDIR/test set(TEST_CLIENT_ID_DIFF_IDS_DIFF_PORTS_MASTER_CONFIG_FILE ${TEST_CLIENT_ID_NAME}_diff_client_ids_diff_ports_master.json) @@ -904,6 +971,13 @@ if(NOT ${TESTS_BAT}) ${TEST_CLIENT_ID_SERVICE} ) + set(TEST_CLIENT_ID_UTILITY_CONFIG_FILE ${TEST_CLIENT_ID_NAME}_utility.json) + copy_to_builddir( + ${PROJECT_SOURCE_DIR}/test/client_id_tests/${TEST_CLIENT_ID_UTILITY_CONFIG_FILE} + ${PROJECT_BINARY_DIR}/test/${TEST_CLIENT_ID_UTILITY_CONFIG_FILE} + ${TEST_CLIENT_ID_UTILITY} + ) + # copy starter scripts into builddir set(TEST_CLIENT_ID_MASTER_STARTER ${TEST_CLIENT_ID_NAME}_master_starter.sh) copy_to_builddir(${PROJECT_SOURCE_DIR}/test/client_id_tests/${TEST_CLIENT_ID_MASTER_STARTER} @@ -1569,6 +1643,7 @@ if(NOT ${TESTS_BAT}) add_dependencies(${TEST_BIG_PAYLOAD_SERVICE} gtest) add_dependencies(${TEST_BIG_PAYLOAD_CLIENT} gtest) add_dependencies(${TEST_CLIENT_ID_SERVICE} gtest) + add_dependencies(${TEST_CLIENT_ID_UTILITY} gtest) add_dependencies(${TEST_SUBSCRIBE_NOTIFY_SERVICE} gtest) add_dependencies(${TEST_SUBSCRIBE_NOTIFY_ONE_SERVICE} gtest) add_dependencies(${TEST_CPU_LOAD_SERVICE} gtest) @@ -1607,6 +1682,7 @@ if(NOT ${TESTS_BAT}) add_dependencies(build_tests ${TEST_BIG_PAYLOAD_SERVICE}) add_dependencies(build_tests ${TEST_BIG_PAYLOAD_CLIENT}) add_dependencies(build_tests ${TEST_CLIENT_ID_SERVICE}) + add_dependencies(build_tests ${TEST_CLIENT_ID_UTILITY}) add_dependencies(build_tests ${TEST_SUBSCRIBE_NOTIFY_SERVICE}) add_dependencies(build_tests ${TEST_SUBSCRIBE_NOTIFY_ONE_SERVICE}) add_dependencies(build_tests ${TEST_CPU_LOAD_SERVICE}) @@ -1674,6 +1750,10 @@ if(NOT ${TESTS_BAT}) add_test(NAME ${TEST_LOCAL_PAYLOAD_NAME} COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_LOCAL_PAYLOAD_STARTER} ) + add_test(NAME ${TEST_LOCAL_PAYLOAD_HUGE_NAME} + COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_LOCAL_PAYLOAD_HUGE_STARTER} + ) + set_tests_properties(${TEST_LOCAL_PAYLOAD_HUGE_NAME} PROPERTIES TIMEOUT 240) add_test(NAME ${TEST_EXTERNAL_LOCAL_PAYLOAD_CLIENT_LOCAL_NAME} COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_EXTERNAL_LOCAL_PAYLOAD_CLIENT_LOCAL_STARTER} ) @@ -1691,11 +1771,32 @@ if(NOT ${TESTS_BAT}) COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_LOCAL_BIG_PAYLOAD_STARTER} ) set_tests_properties(${TEST_LOCAL_BIG_PAYLOAD_NAME} PROPERTIES TIMEOUT 60) + + add_test(NAME ${TEST_LOCAL_BIG_PAYLOAD_NAME_RANDOM} + COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_LOCAL_BIG_PAYLOAD_STARTER} RANDOM + ) + set_tests_properties(${TEST_LOCAL_BIG_PAYLOAD_NAME_RANDOM} PROPERTIES TIMEOUT 60) + + add_test(NAME ${TEST_LOCAL_BIG_PAYLOAD_NAME_LIMITED} + COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_LOCAL_BIG_PAYLOAD_STARTER} LIMITED + ) + set_tests_properties(${TEST_LOCAL_BIG_PAYLOAD_NAME_LIMITED} PROPERTIES TIMEOUT 60) + add_test(NAME ${TEST_EXTERNAL_BIG_PAYLOAD_NAME} COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_EXTERNAL_BIG_PAYLOAD_STARTER} ) set_tests_properties(${TEST_EXTERNAL_BIG_PAYLOAD_NAME} PROPERTIES TIMEOUT 60) + add_test(NAME ${TEST_EXTERNAL_BIG_PAYLOAD_NAME_RANDOM} + COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_EXTERNAL_BIG_PAYLOAD_STARTER} RANDOM + ) + set_tests_properties(${TEST_EXTERNAL_BIG_PAYLOAD_NAME_RANDOM} PROPERTIES TIMEOUT 60) + + add_test(NAME ${TEST_EXTERNAL_BIG_PAYLOAD_NAME_LIMITED} + COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_EXTERNAL_BIG_PAYLOAD_STARTER} LIMITED + ) + set_tests_properties(${TEST_EXTERNAL_BIG_PAYLOAD_NAME_LIMITED} PROPERTIES TIMEOUT 60) + # client id tests add_test(NAME ${TEST_CLIENT_ID_NAME}_diff_client_ids_diff_ports COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_CLIENT_ID_MASTER_STARTER} ${TEST_CLIENT_ID_DIFF_IDS_DIFF_PORTS_MASTER_CONFIG_FILE}) @@ -1709,6 +1810,13 @@ if(NOT ${TESTS_BAT}) COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_CLIENT_ID_MASTER_STARTER} ${TEST_CLIENT_ID_DIFF_IDS_PARTIAL_SAME_PORTS_MASTER_CONFIG_FILE}) set_tests_properties(${TEST_CLIENT_ID_NAME}_diff_client_ids_partial_same_ports PROPERTIES TIMEOUT 60) + add_test(NAME ${TEST_CLIENT_ID_UTILITY} + COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_CLIENT_ID_UTILITY}) + set_property(TEST ${TEST_CLIENT_ID_UTILITY} + APPEND PROPERTY ENVIRONMENT + "VSOMEIP_CONFIGURATION=${TEST_CLIENT_ID_UTILITY_CONFIG_FILE}") + set_tests_properties(${TEST_CLIENT_ID_UTILITY} PROPERTIES TIMEOUT 60) + # subscribe notify tests add_test(NAME ${TEST_SUBSCRIBE_NOTIFY_NAME}_diff_client_ids_diff_ports_udp COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_SUBSCRIBE_NOTIFY_MASTER_STARTER} UDP ${TEST_SUBSCRIBE_NOTIFY_DIFF_IDS_DIFF_PORTS_MASTER_CONFIG_FILE}) diff --git a/test/application_tests/application_test.cpp b/test/application_tests/application_test.cpp index 6832c1f..c6c1b03 100644 --- a/test/application_tests/application_test.cpp +++ b/test/application_tests/application_test.cpp @@ -6,6 +6,7 @@ #include <thread> #include <mutex> #include <condition_variable> +#include <future> #include <gtest/gtest.h> @@ -25,8 +26,8 @@ protected: void SetUp() { app_ = runtime::get()->create_application("application_test"); if (!app_->init()) { - VSOMEIP_ERROR << "Couldn't initialize application"; - EXPECT_TRUE(false); + ADD_FAILURE() << "Couldn't initialize application"; + return; } app_->register_state_handler( @@ -47,9 +48,12 @@ protected: */ TEST_F(someip_application_test, start_stop_application) { + std::promise<bool> its_promise; std::thread t([&](){ + its_promise.set_value(true); app_->start(); }); + EXPECT_TRUE(its_promise.get_future().get()); std::this_thread::sleep_for(std::chrono::milliseconds(100)); app_->stop(); t.join(); @@ -61,9 +65,12 @@ TEST_F(someip_application_test, start_stop_application) TEST_F(someip_application_test, start_stop_application_multiple) { for (int i = 0; i < 10; ++i) { + std::promise<bool> its_promise; std::thread t([&]() { + its_promise.set_value(true); app_->start(); }); + EXPECT_TRUE(its_promise.get_future().get()); std::this_thread::sleep_for(std::chrono::milliseconds(100)); app_->stop(); t.join(); @@ -76,9 +83,12 @@ TEST_F(someip_application_test, start_stop_application_multiple) TEST_F(someip_application_test, start_stop_application_multiple_offer_service) { for (int i = 0; i < 10; ++i) { + std::promise<bool> its_promise; std::thread t([&]() { + its_promise.set_value(true); app_->start(); }); + EXPECT_TRUE(its_promise.get_future().get()); std::this_thread::sleep_for(std::chrono::milliseconds(100)); app_->offer_service(vsomeip_test::TEST_SERVICE_SERVICE_ID, vsomeip_test::TEST_SERVICE_INSTANCE_ID); std::this_thread::sleep_for(std::chrono::milliseconds(100)); @@ -94,10 +104,13 @@ TEST_F(someip_application_test, start_stop_application_multiple_offer_service) */ TEST_F(someip_application_test, restart_without_stopping) { + std::promise<bool> its_promise; std::thread t([&]() { + its_promise.set_value(true); app_->start(); }); + EXPECT_TRUE(its_promise.get_future().get()); std::this_thread::sleep_for(std::chrono::milliseconds(100)); VSOMEIP_WARNING << "An error message should appear now"; // should print error @@ -111,10 +124,13 @@ TEST_F(someip_application_test, restart_without_stopping) */ TEST_F(someip_application_test, stop_application_twice) { + std::promise<bool> its_promise; std::thread t([&]() { + its_promise.set_value(true); app_->start(); }); + EXPECT_TRUE(its_promise.get_future().get()); std::this_thread::sleep_for(std::chrono::milliseconds(100)); app_->stop(); @@ -131,8 +147,8 @@ protected: app_ = runtime::get()->create_application("application_test"); if (!app_->init()) { - VSOMEIP_ERROR << "Couldn't initialize application"; - EXPECT_TRUE(false); + ADD_FAILURE() << "Couldn't initialize application"; + return; } app_->register_message_handler(vsomeip_test::TEST_SERVICE_SERVICE_ID, diff --git a/test/application_tests/application_test_client.cpp b/test/application_tests/application_test_client.cpp index a227799..ba39417 100644 --- a/test/application_tests/application_test_client.cpp +++ b/test/application_tests/application_test_client.cpp @@ -11,6 +11,7 @@ #include <thread> #include <map> #include <algorithm> +#include <future> #include <gtest/gtest.h> @@ -33,7 +34,10 @@ public: received_responses_(0), sent_requests_(0), stop_called_(false) { - app_->init(); + if (!app_->init()) { + ADD_FAILURE() << "Couldn't initialize application"; + return; + } app_->register_state_handler( std::bind(&application_test_client::on_state, this, std::placeholders::_1)); @@ -51,9 +55,13 @@ public: std::placeholders::_3)); app_->request_service(service_info_.service_id, service_info_.instance_id); + std::promise<bool> its_promise; application_thread_ = std::thread([&](){ + its_promise.set_value(true); app_->start(); }); + EXPECT_TRUE(its_promise.get_future().get()); + std::this_thread::sleep_for(std::chrono::milliseconds(100)); } ~application_test_client() { @@ -155,9 +163,6 @@ public: << " responses. Delta: " << sent_requests_ - received_responses_; std::uint32_t counter(0); if (check) { - if (sent_requests_ == 0 || received_responses_ == 0) { - EXPECT_EQ(0, 1); - } while(sent_requests_ < received_responses_) { std::this_thread::sleep_for(std::chrono::milliseconds(100)); if(++counter > 50) { diff --git a/test/application_tests/application_test_daemon.cpp b/test/application_tests/application_test_daemon.cpp index 6e2c7cb..c244e5a 100644 --- a/test/application_tests/application_test_daemon.cpp +++ b/test/application_tests/application_test_daemon.cpp @@ -4,6 +4,7 @@ // file, You can obtain one at http://mozilla.org/MPL/2.0/. #include <gtest/gtest.h> +#include <future> #include <vsomeip/vsomeip.hpp> #include "../../implementation/logging/include/logger.hpp" @@ -12,10 +13,17 @@ class application_test_daemon { public: application_test_daemon() : app_(vsomeip::runtime::get()->create_application("daemon")) { - app_->init(); + if (!app_->init()) { + ADD_FAILURE() << "Couldn't initialize application"; + return; + } + std::promise<bool> its_promise; application_thread_ = std::thread([&](){ + its_promise.set_value(true); app_->start(); }); + EXPECT_TRUE(its_promise.get_future().get()); + std::this_thread::sleep_for(std::chrono::milliseconds(100)); VSOMEIP_INFO << "Daemon starting"; } diff --git a/test/application_tests/application_test_service.cpp b/test/application_tests/application_test_service.cpp index a1c654e..d21ca68 100644 --- a/test/application_tests/application_test_service.cpp +++ b/test/application_tests/application_test_service.cpp @@ -11,6 +11,7 @@ #include <thread> #include <map> #include <algorithm> +#include <future> #include <gtest/gtest.h> @@ -31,7 +32,10 @@ public: wait_until_registered_(true), offer_thread_(std::bind(&application_test_service::run, this)), stop_called_(false) { - app_->init(); + if (!app_->init()) { + ADD_FAILURE() << "Couldn't initialize application"; + return; + } app_->register_state_handler( std::bind(&application_test_service::on_state, this, std::placeholders::_1)); @@ -45,9 +49,13 @@ public: service_info_.instance_id, service_info_.shutdown_method_id, std::bind(&application_test_service::on_shutdown_method_called, this, std::placeholders::_1)); + std::promise<bool> its_promise; application_thread_ = std::thread([&](){ + its_promise.set_value(true); app_->start(); }); + EXPECT_TRUE(its_promise.get_future().get()); + std::this_thread::sleep_for(std::chrono::milliseconds(100)); } ~application_test_service() { diff --git a/test/big_payload_tests/big_payload_test_client.cpp b/test/big_payload_tests/big_payload_test_client.cpp index a18dd0c..bc472df 100644 --- a/test/big_payload_tests/big_payload_test_client.cpp +++ b/test/big_payload_tests/big_payload_test_client.cpp @@ -6,24 +6,39 @@ #include "big_payload_test_client.hpp" #include "big_payload_test_globals.hpp" -big_payload_test_client::big_payload_test_client(bool _use_tcp) : - app_(vsomeip::runtime::get()->create_application()), - request_(vsomeip::runtime::get()->create_request(_use_tcp)), - running_(true), - blocked_(false), - is_available_(false), - number_of_messages_to_send_(vsomeip_test::NUMBER_OF_MESSAGES_TO_SEND), - number_of_sent_messages_(0), - number_of_acknowledged_messages_(0), - sender_(std::bind(&big_payload_test_client::run, this)) -{ +big_payload_test_client::big_payload_test_client( + bool _use_tcp, big_payload_test::test_mode _test_mode) : + app_(vsomeip::runtime::get()->create_application("big_payload_test_client")), + request_(vsomeip::runtime::get()->create_request(_use_tcp)), + running_(true), + blocked_(false), + is_available_(false), + test_mode_(_test_mode), + number_of_messages_to_send_( + test_mode_ == big_payload_test::test_mode::RANDOM ? + big_payload_test::BIG_PAYLOAD_TEST_NUMBER_MESSAGES_RANDOM : + big_payload_test::BIG_PAYLOAD_TEST_NUMBER_MESSAGES), + number_of_sent_messages_(0), + number_of_acknowledged_messages_(0), + sender_(std::bind(&big_payload_test_client::run, this)) { + switch (test_mode_) { + case big_payload_test::test_mode::RANDOM: + service_id_ = big_payload_test::TEST_SERVICE_SERVICE_ID_RANDOM; + break; + case big_payload_test::test_mode::LIMITED: + service_id_ = big_payload_test::TEST_SERVICE_SERVICE_ID_LIMITED; + break; + default: + service_id_ = big_payload_test::TEST_SERVICE_SERVICE_ID; + break; + } } -void big_payload_test_client::init() +bool big_payload_test_client::init() { if (!app_->init()) { - VSOMEIP_ERROR << "Couldn't initialize application"; - EXPECT_TRUE(false); + ADD_FAILURE() << "Couldn't initialize application"; + return false; } app_->register_state_handler( @@ -31,15 +46,16 @@ void big_payload_test_client::init() std::placeholders::_1)); app_->register_message_handler(vsomeip::ANY_SERVICE, - vsomeip_test::TEST_SERVICE_INSTANCE_ID, vsomeip::ANY_METHOD, + vsomeip::ANY_INSTANCE, vsomeip::ANY_METHOD, std::bind(&big_payload_test_client::on_message, this, std::placeholders::_1)); - app_->register_availability_handler(vsomeip_test::TEST_SERVICE_SERVICE_ID, - vsomeip_test::TEST_SERVICE_INSTANCE_ID, + app_->register_availability_handler(service_id_, + big_payload_test::TEST_SERVICE_INSTANCE_ID, std::bind(&big_payload_test_client::on_availability, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); + return true; } void big_payload_test_client::start() @@ -51,27 +67,28 @@ void big_payload_test_client::start() void big_payload_test_client::stop() { VSOMEIP_INFO << "Stopping..."; - app_->unregister_availability_handler(vsomeip_test::TEST_SERVICE_SERVICE_ID, - vsomeip_test::TEST_SERVICE_INSTANCE_ID); - app_->unregister_state_handler(); - app_->unregister_message_handler(vsomeip::ANY_SERVICE, - vsomeip_test::TEST_SERVICE_INSTANCE_ID, vsomeip::ANY_METHOD); + if (test_mode_ == big_payload_test::test_mode::LIMITED) { + std::this_thread::sleep_for(std::chrono::milliseconds(3000)); + ASSERT_EQ(number_of_acknowledged_messages_, number_of_messages_to_send_ / 4); + } app_->clear_all_handler(); app_->stop(); } void big_payload_test_client::join_sender_thread(){ sender_.join(); - - ASSERT_EQ(number_of_sent_messages_, number_of_acknowledged_messages_); + if (test_mode_ == big_payload_test::test_mode::LIMITED) { + ASSERT_EQ(number_of_acknowledged_messages_, number_of_messages_to_send_ / 4); + } else { + ASSERT_EQ(number_of_sent_messages_, number_of_acknowledged_messages_); + } } void big_payload_test_client::on_state(vsomeip::state_type_e _state) { - if(_state == vsomeip::state_type_e::ST_REGISTERED) - { - app_->request_service(vsomeip_test::TEST_SERVICE_SERVICE_ID, - vsomeip_test::TEST_SERVICE_INSTANCE_ID, false); + if (_state == vsomeip::state_type_e::ST_REGISTERED) { + app_->request_service(service_id_, + big_payload_test::TEST_SERVICE_INSTANCE_ID, false); } } @@ -82,8 +99,8 @@ void big_payload_test_client::on_availability(vsomeip::service_t _service, << _service << "." << _instance << "] is " << (_is_available ? "available." : "NOT available."); - if(vsomeip_test::TEST_SERVICE_SERVICE_ID == _service - && vsomeip_test::TEST_SERVICE_INSTANCE_ID == _instance) + if(service_id_ == _service + && big_payload_test::TEST_SERVICE_INSTANCE_ID == _instance) { if(is_available_ && !_is_available) { @@ -107,8 +124,15 @@ void big_payload_test_client::on_message(const std::shared_ptr<vsomeip::message> << _response->get_client() << "/" << std::setw(4) << std::setfill('0') << std::hex << _response->get_session() << "] size: " << std::dec << _response->get_payload()->get_length(); - - ASSERT_EQ(_response->get_payload()->get_length(), big_payload_test::BIG_PAYLOAD_SIZE); + static vsomeip::session_t last_session(0); + ASSERT_GT(_response->get_session(), last_session); + last_session = _response->get_session(); + + if(test_mode_ == big_payload_test::test_mode::RANDOM) { + ASSERT_LT(_response->get_payload()->get_length(), big_payload_test::BIG_PAYLOAD_SIZE_RANDOM); + } else { + ASSERT_EQ(_response->get_payload()->get_length(), big_payload_test::BIG_PAYLOAD_SIZE); + } bool check(true); vsomeip::length_t len = _response->get_payload()->get_length(); @@ -120,7 +144,13 @@ void big_payload_test_client::on_message(const std::shared_ptr<vsomeip::message> GTEST_FATAL_FAILURE_("wrong data transmitted"); } number_of_acknowledged_messages_++; - send(); + if (test_mode_ == big_payload_test::test_mode::LIMITED) { + if (number_of_acknowledged_messages_ == number_of_messages_to_send_ / 4) { + send(); + } + } else if ( number_of_acknowledged_messages_ == number_of_messages_to_send_) { + send(); + } } void big_payload_test_client::send() @@ -138,20 +168,37 @@ void big_payload_test_client::run() condition_.wait(its_lock); } blocked_ = false; - request_->set_service(vsomeip_test::TEST_SERVICE_SERVICE_ID); - request_->set_instance(vsomeip_test::TEST_SERVICE_INSTANCE_ID); - request_->set_method(vsomeip_test::TEST_SERVICE_METHOD_ID); - - std::shared_ptr< vsomeip::payload > its_payload = vsomeip::runtime::get()->create_payload(); - std::vector< vsomeip::byte_t > its_payload_data; - for (unsigned int i = 0; i < big_payload_test::BIG_PAYLOAD_SIZE; ++i) { - its_payload_data.push_back(big_payload_test::DATA_CLIENT_TO_SERVICE); - } - its_payload->set_data(its_payload_data); - request_->set_payload(its_payload); + + request_->set_service(service_id_); + request_->set_instance(big_payload_test::TEST_SERVICE_INSTANCE_ID); + request_->set_method(big_payload_test::TEST_SERVICE_METHOD_ID); + + std::srand(static_cast<unsigned int>(std::time(0))); + + std::shared_ptr<vsomeip::payload> its_payload = + vsomeip::runtime::get()->create_payload(); + std::vector<vsomeip::byte_t> its_payload_data; for (unsigned int i = 0; i < number_of_messages_to_send_; i++) { + if (test_mode_ == big_payload_test::test_mode::RANDOM) { + unsigned int datasize(std::rand() % big_payload_test::BIG_PAYLOAD_SIZE_RANDOM); + its_payload_data.assign(datasize, big_payload_test::DATA_CLIENT_TO_SERVICE); + } else if (test_mode_ == big_payload_test::test_mode::LIMITED) { + if (i % 2) { + // try to sent a too big payload for half of the messages + its_payload_data.assign(big_payload_test::BIG_PAYLOAD_SIZE + 3, + big_payload_test::DATA_CLIENT_TO_SERVICE); + } else { + its_payload_data.assign(big_payload_test::BIG_PAYLOAD_SIZE, + big_payload_test::DATA_CLIENT_TO_SERVICE); + } + } else { + its_payload_data.assign(big_payload_test::BIG_PAYLOAD_SIZE, + big_payload_test::DATA_CLIENT_TO_SERVICE); + } + its_payload->set_data(its_payload_data); + request_->set_payload(its_payload); app_->send(request_, true); VSOMEIP_INFO << "Client/Session [" << std::setw(4) << std::setfill('0') << std::hex << request_->get_client() << "/" << std::setw(4) @@ -159,30 +206,50 @@ void big_payload_test_client::run() << "] sent a request to Service [" << std::setw(4) << std::setfill('0') << std::hex << request_->get_service() << "." << std::setw(4) << std::setfill('0') << std::hex - << request_->get_instance() << "]"; + << request_->get_instance() << "] size: " << std::dec << + request_->get_payload()->get_length(); number_of_sent_messages_++; - while(!blocked_) { - condition_.wait(its_lock); + } + while(!blocked_) { + if (std::cv_status::timeout + == condition_.wait_for(its_lock, std::chrono::seconds(120))) { + GTEST_FATAL_FAILURE_("Didn't receive all replies within time"); + } else { + if (test_mode_ == big_payload_test::LIMITED) { + ASSERT_EQ(number_of_messages_to_send_ / 4, + number_of_acknowledged_messages_); + } else { + ASSERT_EQ(number_of_sent_messages_, + number_of_acknowledged_messages_); + } } - blocked_ = false; } - ASSERT_EQ(number_of_sent_messages_, number_of_acknowledged_messages_); stop(); } +static big_payload_test::test_mode test_mode(big_payload_test::test_mode::UNKNOWN); + TEST(someip_big_payload_test, send_ten_messages_to_service) { bool use_tcp = true; - big_payload_test_client test_client_(use_tcp); - test_client_.init(); - test_client_.start(); - test_client_.join_sender_thread(); + big_payload_test_client test_client_(use_tcp, test_mode); + if (test_client_.init()) { + test_client_.start(); + test_client_.join_sender_thread(); + } } #ifndef WIN32 int main(int argc, char** argv) { ::testing::InitGoogleTest(&argc, argv); + if (argc > 1) { + if (std::string("RANDOM") == std::string(argv[1])) { + test_mode = big_payload_test::test_mode::RANDOM; + } else if (std::string("LIMITED") == std::string(argv[1])) { + test_mode = big_payload_test::test_mode::LIMITED; + } + } return RUN_ALL_TESTS(); } #endif diff --git a/test/big_payload_tests/big_payload_test_client.hpp b/test/big_payload_tests/big_payload_test_client.hpp index 3524123..30bf8c7 100644 --- a/test/big_payload_tests/big_payload_test_client.hpp +++ b/test/big_payload_tests/big_payload_test_client.hpp @@ -14,14 +14,16 @@ #include <mutex> #include <condition_variable> #include <functional> +#include <atomic> -#include "../someip_test_globals.hpp" +#include "big_payload_test_globals.hpp" +#include "../../implementation/logging/include/logger.hpp" class big_payload_test_client { public: - big_payload_test_client(bool _use_tcp); - void init(); + big_payload_test_client(bool _use_tcp, big_payload_test::test_mode _random_mode); + bool init(); void start(); void stop(); void join_sender_thread(); @@ -40,10 +42,12 @@ private: bool running_; bool blocked_; bool is_available_; + big_payload_test::test_mode test_mode_; std::uint32_t number_of_messages_to_send_; std::uint32_t number_of_sent_messages_; - std::uint32_t number_of_acknowledged_messages_; + std::atomic<std::uint32_t> number_of_acknowledged_messages_; std::thread sender_; + vsomeip::service_t service_id_; }; #endif /* BIGPAYLOADTESTCLIENT_HPP_ */ diff --git a/test/big_payload_tests/big_payload_test_external_starter.sh b/test/big_payload_tests/big_payload_test_external_starter.sh index 6550adc..7de3342 100755 --- a/test/big_payload_tests/big_payload_test_external_starter.sh +++ b/test/big_payload_tests/big_payload_test_external_starter.sh @@ -10,18 +10,38 @@ # the testcase simply executes this script. This script then runs client # and service and checks that both exit successfully. +if [[ $# -gt 0 && $1 != "RANDOM" && $1 != "LIMITED" ]] +then + echo "The only allowed parameter to this script is RANDOM or LIMITED." + echo "Like $0 RANDOM" + exit 1 +fi + FAIL=0 # Start the client -export VSOMEIP_CONFIGURATION=big_payload_test_tcp_client.json -export VSOMEIP_APPLICATION_NAME=big_payload_test_client -./big_payload_test_client & +if [[ $# -gt 0 && $1 == "RANDOM" ]] +then + export VSOMEIP_CONFIGURATION=big_payload_test_tcp_client_random.json +else + export VSOMEIP_CONFIGURATION=big_payload_test_tcp_client.json +fi +./big_payload_test_client $1 & +BIG_PAYLOAD_TEST_PID=$! +if [ ! -z "$USE_LXC_TEST" ]; then + echo "starting big payload test on slave LXC" + if [[ $# -gt 0 ]]; then + ssh -tt -i $SANDBOX_ROOT_DIR/commonapi_main/lxc-config/.ssh/mgc_lxc/rsa_key_file.pub -o StrictHostKeyChecking=no root@$LXC_TEST_SLAVE_IP "bash -ci \"set -m; cd \\\$SANDBOX_ROOT_DIR/ctarget/vsomeip/test; ./big_payload_test_service_external_start.sh $1\"" & + else + ssh -tt -i $SANDBOX_ROOT_DIR/commonapi_main/lxc-config/.ssh/mgc_lxc/rsa_key_file.pub -o StrictHostKeyChecking=no root@$LXC_TEST_SLAVE_IP 'bash -ci "set -m; cd \$SANDBOX_ROOT_DIR/ctarget/vsomeip/test; ./big_payload_test_service_external_start.sh"' & + fi +else cat <<End-of-message ******************************************************************************* ******************************************************************************* ** Please now run: -** big_payload_test_service_external_start.sh +** big_payload_test_service_external_start.sh $1 ** from an external host to successfully complete this test. ** ** You probably will need to adapt the 'unicast' settings in @@ -30,6 +50,7 @@ cat <<End-of-message ******************************************************************************* ******************************************************************************* End-of-message +fi # Wait until client and service are finished for job in $(jobs -p) diff --git a/test/big_payload_tests/big_payload_test_globals.hpp b/test/big_payload_tests/big_payload_test_globals.hpp index 28a6205..01fe949 100644 --- a/test/big_payload_tests/big_payload_test_globals.hpp +++ b/test/big_payload_tests/big_payload_test_globals.hpp @@ -10,8 +10,25 @@ namespace big_payload_test { constexpr std::uint32_t BIG_PAYLOAD_SIZE = 1024*600; + constexpr std::uint32_t BIG_PAYLOAD_SIZE_RANDOM = 1024*1024*10; constexpr vsomeip::byte_t DATA_SERVICE_TO_CLIENT = 0xAA; constexpr vsomeip::byte_t DATA_CLIENT_TO_SERVICE = 0xFF; + + constexpr std::uint32_t BIG_PAYLOAD_TEST_NUMBER_MESSAGES = 10; + constexpr std::uint32_t BIG_PAYLOAD_TEST_NUMBER_MESSAGES_RANDOM = 50; + + constexpr vsomeip::service_t TEST_SERVICE_SERVICE_ID = 0x1234; + constexpr vsomeip::service_t TEST_SERVICE_SERVICE_ID_LIMITED = 0x1235; + constexpr vsomeip::service_t TEST_SERVICE_SERVICE_ID_RANDOM = 0x1236; + + constexpr vsomeip::service_t TEST_SERVICE_INSTANCE_ID = 0x1; + constexpr vsomeip::method_t TEST_SERVICE_METHOD_ID = 0x8421; + + enum test_mode { + RANDOM, + LIMITED, + UNKNOWN + }; } #endif /* BIG_PAYLOAD_TEST_GLOBALS_HPP_ */ diff --git a/test/big_payload_tests/big_payload_test_local_limited.json b/test/big_payload_tests/big_payload_test_local_limited.json new file mode 100644 index 0000000..a711df1 --- /dev/null +++ b/test/big_payload_tests/big_payload_test_local_limited.json @@ -0,0 +1,42 @@ +{ + "unicast":"127.0.0.1", + "logging": + { + "level":"error", + "console":"true", + "file": + { + "enable":"false", + "path":"/tmp/vsomeip.log" + }, + "dlt":"false" + }, + "applications": + [ + { + "name":"big_payload_test_service", + "id":"0x1277" + }, + { + "name":"big_payload_test_client", + "id":"0x1344" + } + ], + "services": + [ + { + "service":"0x1234", + "instance":"0x5678" + } + ], + "max-payload-size-local" : "614400", + "routing":"big_payload_test_service", + "service-discovery": + { + "enable":"true", + "multicast":"224.244.224.245", + "port":"30490", + "protocol":"udp" + } +} + diff --git a/test/big_payload_tests/big_payload_test_local_random.json b/test/big_payload_tests/big_payload_test_local_random.json new file mode 100644 index 0000000..b49683e --- /dev/null +++ b/test/big_payload_tests/big_payload_test_local_random.json @@ -0,0 +1,44 @@ +{ + "unicast":"127.0.0.1", + "logging": + { + "level":"debug", + "console":"true", + "file": + { + "enable":"false", + "path":"/tmp/vsomeip.log" + }, + "dlt":"false" + }, + "applications": + [ + { + "name":"big_payload_test_service", + "id":"0x1277", + "max_dispatch_time" : "5000" + }, + { + "name":"big_payload_test_client", + "id":"0x1344", + "max_dispatch_time" : "5000" + } + ], + "services": + [ + { + "service":"0x1234", + "instance":"0x5678" + } + ], + "buffer-shrink-threshold" : "2", + "routing":"big_payload_test_service", + "service-discovery": + { + "enable":"true", + "multicast":"224.244.224.245", + "port":"30490", + "protocol":"udp" + } +} + diff --git a/test/big_payload_tests/big_payload_test_local_starter.sh b/test/big_payload_tests/big_payload_test_local_starter.sh index d32b6a0..792e840 100755 --- a/test/big_payload_tests/big_payload_test_local_starter.sh +++ b/test/big_payload_tests/big_payload_test_local_starter.sh @@ -10,16 +10,28 @@ # the testcase simply executes this script. This script then runs client # and service and checks that both exit successfully. +if [[ $# -gt 0 && $1 != "RANDOM" && $1 != "LIMITED" ]] +then + echo "The only allowed parameter to this script is RANDOM or LIMITED." + echo "Like $0 RANDOM" + exit 1 +fi + + FAIL=0 # Start the service -export VSOMEIP_APPLICATION_NAME=big_payload_test_service -export VSOMEIP_CONFIGURATION=big_payload_test_local.json -./big_payload_test_service & +if [[ $# -gt 0 && $1 == "RANDOM" ]]; then + export VSOMEIP_CONFIGURATION=big_payload_test_local_random.json +elif [[ $# -gt 0 && $1 == "LIMITED" ]]; then + export VSOMEIP_CONFIGURATION=big_payload_test_local_limited.json +else + export VSOMEIP_CONFIGURATION=big_payload_test_local.json +fi +./big_payload_test_service $1 & # Start the client -export VSOMEIP_APPLICATION_NAME=big_payload_test_client -./big_payload_test_client & +./big_payload_test_client $1 & # Wait until client and service are finished for job in $(jobs -p) diff --git a/test/big_payload_tests/big_payload_test_service.cpp b/test/big_payload_tests/big_payload_test_service.cpp index 37f3d7f..6f0e056 100644 --- a/test/big_payload_tests/big_payload_test_service.cpp +++ b/test/big_payload_tests/big_payload_test_service.cpp @@ -7,31 +7,48 @@ #include "big_payload_test_globals.hpp" -big_payload_test_service::big_payload_test_service() : - app_(vsomeip::runtime::get()->create_application()), +big_payload_test_service::big_payload_test_service(big_payload_test::test_mode _test_mode) : + app_(vsomeip::runtime::get()->create_application("big_payload_test_service")), is_registered_(false), blocked_(false), + test_mode_(_test_mode), number_of_received_messages_(0), offer_thread_(std::bind(&big_payload_test_service::run, this)) { + switch (test_mode_) { + case big_payload_test::test_mode::RANDOM: + expected_messages_ = big_payload_test::BIG_PAYLOAD_TEST_NUMBER_MESSAGES_RANDOM; + service_id_ = big_payload_test::TEST_SERVICE_SERVICE_ID_RANDOM; + break; + case big_payload_test::test_mode::LIMITED: + expected_messages_ = big_payload_test::BIG_PAYLOAD_TEST_NUMBER_MESSAGES / 2; + service_id_ = big_payload_test::TEST_SERVICE_SERVICE_ID_LIMITED; + break; + default: + expected_messages_ = big_payload_test::BIG_PAYLOAD_TEST_NUMBER_MESSAGES; + service_id_ = big_payload_test::TEST_SERVICE_SERVICE_ID; + break; + } } -void big_payload_test_service::init() +bool big_payload_test_service::init() { std::lock_guard<std::mutex> its_lock(mutex_); - + std::srand(static_cast<unsigned int>(std::time(0))); if (!app_->init()) { - VSOMEIP_ERROR << "Couldn't initialize application"; - EXPECT_TRUE(false); + 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, + app_->register_message_handler(vsomeip::ANY_SERVICE, + big_payload_test::TEST_SERVICE_INSTANCE_ID, + big_payload_test::TEST_SERVICE_METHOD_ID, std::bind(&big_payload_test_service::on_message, this, std::placeholders::_1)); app_->register_state_handler( std::bind(&big_payload_test_service::on_state, this, std::placeholders::_1)); + return true; } void big_payload_test_service::start() @@ -43,6 +60,7 @@ void big_payload_test_service::start() void big_payload_test_service::stop() { VSOMEIP_INFO << "Stopping..."; + stop_offer(); app_->clear_all_handler(); app_->stop(); } @@ -52,14 +70,14 @@ void big_payload_test_service::join_offer_thread() offer_thread_.join(); } -void big_payload_test_service::offer() -{ - app_->offer_service(vsomeip_test::TEST_SERVICE_SERVICE_ID, vsomeip_test::TEST_SERVICE_INSTANCE_ID); +void big_payload_test_service::offer() { + app_->offer_service(service_id_, + big_payload_test::TEST_SERVICE_INSTANCE_ID); } -void big_payload_test_service::stop_offer() -{ - app_->stop_offer_service(vsomeip_test::TEST_SERVICE_SERVICE_ID, vsomeip_test::TEST_SERVICE_INSTANCE_ID); +void big_payload_test_service::stop_offer() { + app_->stop_offer_service(service_id_, + big_payload_test::TEST_SERVICE_INSTANCE_ID); } void big_payload_test_service::on_state(vsomeip::state_type_e _state) @@ -93,7 +111,14 @@ void big_payload_test_service::on_message(const std::shared_ptr<vsomeip::message << _request->get_session() << "] size: " << std::dec << _request->get_payload()->get_length(); - ASSERT_EQ(_request->get_payload()->get_length(), big_payload_test::BIG_PAYLOAD_SIZE); + static vsomeip::session_t last_session(0); + ASSERT_GT(_request->get_session(), last_session); + last_session = _request->get_session(); + if (test_mode_ == big_payload_test::test_mode::RANDOM) { + ASSERT_LT(_request->get_payload()->get_length(), big_payload_test::BIG_PAYLOAD_SIZE_RANDOM); + } else { + ASSERT_EQ(_request->get_payload()->get_length(), big_payload_test::BIG_PAYLOAD_SIZE); + } bool check(true); vsomeip::length_t len = _request->get_payload()->get_length(); vsomeip::byte_t* datap = _request->get_payload()->get_data(); @@ -113,16 +138,33 @@ void big_payload_test_service::on_message(const std::shared_ptr<vsomeip::message std::shared_ptr<vsomeip::payload> its_payload = vsomeip::runtime::get() ->create_payload(); std::vector<vsomeip::byte_t> its_payload_data; - for (unsigned int i = 0; i < big_payload_test::BIG_PAYLOAD_SIZE; ++i) { - its_payload_data.push_back(big_payload_test::DATA_SERVICE_TO_CLIENT); + if (test_mode_ == big_payload_test::test_mode::RANDOM) { + its_payload_data.assign(std::rand() % big_payload_test::BIG_PAYLOAD_SIZE_RANDOM, + big_payload_test::DATA_SERVICE_TO_CLIENT); + } else if (test_mode_ == big_payload_test::test_mode::LIMITED) { + if (number_of_received_messages_ % 2) { + // try to send to big response for half of the received messsages. + // this way the client will only get replies for a fourth of his sent + // requests as he tries to sent to big data for every second request + // as well + its_payload_data.assign(big_payload_test::BIG_PAYLOAD_SIZE + 3, + big_payload_test::DATA_SERVICE_TO_CLIENT); + } else { + its_payload_data.assign(big_payload_test::BIG_PAYLOAD_SIZE, + big_payload_test::DATA_SERVICE_TO_CLIENT); + } + } else { + its_payload_data.assign(big_payload_test::BIG_PAYLOAD_SIZE, + big_payload_test::DATA_SERVICE_TO_CLIENT); } + its_payload->set_data(its_payload_data); its_response->set_payload(its_payload); app_->send(its_response, true); - if(number_of_received_messages_ == vsomeip_test::NUMBER_OF_MESSAGES_TO_SEND) { - ASSERT_EQ(vsomeip_test::NUMBER_OF_MESSAGES_TO_SEND, number_of_received_messages_); + if(number_of_received_messages_ == expected_messages_) { + ASSERT_EQ(expected_messages_, number_of_received_messages_); std::lock_guard<std::mutex> its_lock(mutex_); blocked_ = true; condition_.notify_one(); @@ -131,34 +173,50 @@ void big_payload_test_service::on_message(const std::shared_ptr<vsomeip::message void big_payload_test_service::run() { - std::unique_lock<std::mutex> its_lock(mutex_); - while (!blocked_) { - condition_.wait(its_lock); - } + { + std::unique_lock<std::mutex> its_lock(mutex_); + while (!blocked_) { + condition_.wait(its_lock); + } - offer(); + offer(); - // wait for shutdown - blocked_ = false; - while (!blocked_) { - condition_.wait(its_lock); + // wait for shutdown + blocked_ = false; + while (!blocked_) { + condition_.wait(its_lock); + } } std::this_thread::sleep_for(std::chrono::seconds(3)); - app_->stop(); + if (test_mode_ == big_payload_test::test_mode::LIMITED) { + ASSERT_EQ(number_of_received_messages_, expected_messages_); + } + stop(); } +static big_payload_test::test_mode test_mode(big_payload_test::test_mode::UNKNOWN); + + TEST(someip_big_payload_test, receive_ten_messages_and_send_reply) { - big_payload_test_service test_service; - test_service.init(); - test_service.start(); - test_service.join_offer_thread(); + big_payload_test_service test_service(test_mode); + if (test_service.init()) { + test_service.start(); + test_service.join_offer_thread(); + } } #ifndef WIN32 int main(int argc, char** argv) { ::testing::InitGoogleTest(&argc, argv); + if (argc > 1) { + if (std::string("RANDOM") == std::string(argv[1])) { + test_mode = big_payload_test::test_mode::RANDOM; + } else if (std::string("LIMITED") == std::string(argv[1])) { + test_mode = big_payload_test::test_mode::LIMITED; + } + } return RUN_ALL_TESTS(); } #endif diff --git a/test/big_payload_tests/big_payload_test_service.hpp b/test/big_payload_tests/big_payload_test_service.hpp index 58d070d..0862370 100644 --- a/test/big_payload_tests/big_payload_test_service.hpp +++ b/test/big_payload_tests/big_payload_test_service.hpp @@ -14,13 +14,15 @@ #include <condition_variable> #include <functional> -#include "../someip_test_globals.hpp" +#include "big_payload_test_globals.hpp" +#include "../../implementation/logging/include/logger.hpp" + class big_payload_test_service { public: - big_payload_test_service(); - void init(); + big_payload_test_service(big_payload_test::test_mode _test_mode); + bool init(); void start(); void stop(); void offer(); @@ -36,8 +38,11 @@ private: std::mutex mutex_; std::condition_variable condition_; bool blocked_; + big_payload_test::test_mode test_mode_; std::uint32_t number_of_received_messages_; std::thread offer_thread_; + std::uint32_t expected_messages_; + vsomeip::service_t service_id_; }; #endif /* BIGPAYLOADTESTSERVICE_HPP_ */ diff --git a/test/big_payload_tests/big_payload_test_service_external_start.sh b/test/big_payload_tests/big_payload_test_service_external_start.sh index 361f106..8fd7120 100755 --- a/test/big_payload_tests/big_payload_test_service_external_start.sh +++ b/test/big_payload_tests/big_payload_test_service_external_start.sh @@ -4,7 +4,18 @@ # 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/. +if [[ $# -gt 0 && $1 != "RANDOM" && $1 != "LIMITED" ]] +then + echo "The only allowed parameter to this script is RANDOM or LIMITED." + echo "Like $0 RANDOM" + exit 1 +fi + # Start the service -export VSOMEIP_APPLICATION_NAME=big_payload_test_service -export VSOMEIP_CONFIGURATION=big_payload_test_tcp_service.json -./big_payload_test_service +if [[ $# -gt 0 && $1 == "RANDOM" ]] +then + export VSOMEIP_CONFIGURATION=big_payload_test_tcp_service_random.json +else + export VSOMEIP_CONFIGURATION=big_payload_test_tcp_service.json +fi +./big_payload_test_service $1 diff --git a/test/big_payload_tests/conf/big_payload_test_tcp_client_random.json.in b/test/big_payload_tests/conf/big_payload_test_tcp_client_random.json.in new file mode 100644 index 0000000..cc93b48 --- /dev/null +++ b/test/big_payload_tests/conf/big_payload_test_tcp_client_random.json.in @@ -0,0 +1,31 @@ +{ + "unicast":"@TEST_IP_MASTER@", + "netmask":"255.255.255.0", + "logging": + { + "level":"info", + "console":"true", + "file": + { + "enable":"true", + "path":"/var/log/vsomeip.log" + }, + "dlt":"true" + }, + "applications": + [ + { + "name":"big_payload_test_client", + "id":"0x1343" + } + ], + "buffer-shrink-threshold" : "2", + "routing":"big_payload_test_client", + "service-discovery": + { + "enable":"true", + "multicast":"224.244.224.245", + "port":"30490", + "protocol":"udp" + } +} diff --git a/test/big_payload_tests/conf/big_payload_test_tcp_service.json.in b/test/big_payload_tests/conf/big_payload_test_tcp_service.json.in index a932d82..c17c688 100644 --- a/test/big_payload_tests/conf/big_payload_test_tcp_service.json.in +++ b/test/big_payload_tests/conf/big_payload_test_tcp_service.json.in @@ -22,7 +22,25 @@ [ { "service":"0x1234", - "instance":"0x5678", + "instance":"0x01", + "reliable": + { + "port":"30509", + "enable-magic-cookies":"false" + } + }, + { + "service":"0x1235", + "instance":"0x01", + "reliable": + { + "port":"30509", + "enable-magic-cookies":"false" + } + }, + { + "service":"0x1236", + "instance":"0x01", "reliable": { "port":"30509", diff --git a/test/big_payload_tests/conf/big_payload_test_tcp_service_random.json.in b/test/big_payload_tests/conf/big_payload_test_tcp_service_random.json.in new file mode 100644 index 0000000..e607018 --- /dev/null +++ b/test/big_payload_tests/conf/big_payload_test_tcp_service_random.json.in @@ -0,0 +1,60 @@ +{ + "unicast":"@TEST_IP_SLAVE@", + "logging": + { + "level":"debug", + "console":"true", + "file": + { + "enable":"false", + "path":"/tmp/vsomeip.log" + }, + "dlt":"false" + }, + "applications": + [ + { + "name":"big_payload_test_service", + "id":"0x1277" + } + ], + "services": + [ + { + "service":"0x1234", + "instance":"0x01", + "reliable": + { + "port":"30509", + "enable-magic-cookies":"false" + } + }, + { + "service":"0x1235", + "instance":"0x01", + "reliable": + { + "port":"30509", + "enable-magic-cookies":"false" + } + }, + { + "service":"0x1236", + "instance":"0x01", + "reliable": + { + "port":"30509", + "enable-magic-cookies":"false" + } + } + ], + "buffer-shrink-threshold" : "2", + "routing":"big_payload_test_service", + "service-discovery": + { + "enable":"true", + "multicast":"224.244.224.245", + "port":"30490", + "protocol":"udp" + } +} diff --git a/test/client_id_tests/client_id_test_master_starter.sh b/test/client_id_tests/client_id_test_master_starter.sh index 6b4e53b..ef74c72 100755 --- a/test/client_id_tests/client_id_test_master_starter.sh +++ b/test/client_id_tests/client_id_test_master_starter.sh @@ -26,17 +26,24 @@ FAIL=0 export VSOMEIP_APPLICATION_NAME=client_id_test_service_one export VSOMEIP_CONFIGURATION=$1 ./client_id_test_service 1 & +CLIENT_ID_PIDS[1]=$! export VSOMEIP_APPLICATION_NAME=client_id_test_service_two export VSOMEIP_CONFIGURATION=$1 ./client_id_test_service 2 & +CLIENT_ID_PIDS[2]=$! export VSOMEIP_APPLICATION_NAME=client_id_test_service_three export VSOMEIP_CONFIGURATION=$1 ./client_id_test_service 3 & +CLIENT_ID_PIDS[3]=$! sleep 1 +if [ ! -z "$USE_LXC_TEST" ]; then + echo "starting client id test on slave LXC" + ssh -tt -i $SANDBOX_ROOT_DIR/commonapi_main/lxc-config/.ssh/mgc_lxc/rsa_key_file.pub -o StrictHostKeyChecking=no root@$LXC_TEST_SLAVE_IP "bash -ci \"set -m; cd \\\$SANDBOX_ROOT_DIR/ctarget/vsomeip/test; ./client_id_test_slave_starter.sh $CLIENT_JSON_FILE\"" & +else cat <<End-of-message ******************************************************************************* ******************************************************************************* @@ -50,13 +57,16 @@ cat <<End-of-message ******************************************************************************* ******************************************************************************* End-of-message +fi # Wait until client and service are finished -for job in $(jobs -p) +for client_pid in "${CLIENT_ID_PIDS[@]}" do - # Fail gets incremented if either client or service exit - # with a non-zero exit code - wait $job || ((FAIL+=1)) + if [ -n "$client_pid" ]; then + # Fail gets incremented if either client or service exit + # with a non-zero exit code + wait "$client_pid" || ((FAIL+=1)) + fi done # Check if both exited successfully diff --git a/test/client_id_tests/client_id_test_service.cpp b/test/client_id_tests/client_id_test_service.cpp index 6572d74..7e1d66d 100644 --- a/test/client_id_tests/client_id_test_service.cpp +++ b/test/client_id_tests/client_id_test_service.cpp @@ -30,8 +30,8 @@ public: stopped_(false), stop_thread_(std::bind(&client_id_test_service::wait_for_stop, this)) { if (!app_->init()) { - VSOMEIP_ERROR << "Couldn't initialize application"; - EXPECT_TRUE(false); + ADD_FAILURE() << "Couldn't initialize application"; + return; } app_->register_state_handler( std::bind(&client_id_test_service::on_state, this, diff --git a/test/client_id_tests/client_id_test_utility.cpp b/test/client_id_tests/client_id_test_utility.cpp new file mode 100644 index 0000000..610a087 --- /dev/null +++ b/test/client_id_tests/client_id_test_utility.cpp @@ -0,0 +1,447 @@ +// Copyright (C) 2014-2016 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#include <gtest/gtest.h> + +#include <unistd.h> // for access() +#include <sstream> + +#include "../../implementation/utility/include/utility.hpp" +#include "../../implementation/configuration/include/configuration.hpp" +#include <vsomeip/constants.hpp> + + +using namespace vsomeip; + +static const std::string APPLICATION_NAME_ROUTING_MANAGER = "vsomeipd"; + +static const std::string APPLICATION_NAME_NOT_PREDEFINED = "test-application-name"; + +static const std::string APPLICATION_IN_NAME = "client_id_test_utility_service_in"; +static const vsomeip::client_t APPLICATION_IN_CLIENT_ID = 0x6311; + +static const std::string APPLICATION_IN_NAME_TWO = "client_id_test_utility_service_in_two"; +static const vsomeip::client_t APPLICATION_IN_CLIENT_ID_TWO = 0x6312; + +static const std::string APPLICATION_OUT_LOW_NAME = "client_id_test_utility_service_out_low"; +static const vsomeip::client_t APPLICATION_OUT_LOW_CLIENT_ID = 0x6011; + +static const std::string APPLICATION_OUT_HIGH_NAME = "client_id_test_utility_service_out_high"; +static const vsomeip::client_t APPLICATION_OUT_HIGH_CLIENT_ID = 0x6411; + + + +class client_id_utility_test: public ::testing::Test { +public: + client_id_utility_test() : + configuration_(vsomeip::configuration::get()), + client_id_routing_manager_(0x0) { + } +protected: + virtual void SetUp() { + ASSERT_FALSE(file_exist(std::string("/dev/shm").append(VSOMEIP_SHM_NAME))); + ASSERT_TRUE(static_cast<bool>(configuration_)); + configuration_->load(APPLICATION_NAME_ROUTING_MANAGER); + + utility::auto_configuration_init(configuration_); + EXPECT_TRUE(file_exist(std::string("/dev/shm").append(VSOMEIP_SHM_NAME))); + + client_id_routing_manager_ = utility::request_client_id( + configuration_, APPLICATION_NAME_ROUTING_MANAGER, 0x0); + EXPECT_EQ(0x6301, client_id_routing_manager_); + EXPECT_TRUE(utility::is_routing_manager_host(client_id_routing_manager_)); + } + + virtual void TearDown() { + utility::auto_configuration_exit(client_id_routing_manager_); + EXPECT_FALSE(file_exist(std::string("/dev/shm").append(VSOMEIP_SHM_NAME))); + } + + bool file_exist(const std::string &_path) { + const int ret = ::access(_path.c_str(), F_OK); + if (ret == -1 && errno == ENOENT) { + return false; + } else if (ret == -1) { + std::stringstream its_stream; + its_stream << "file_exists (" << _path << "): "; + std::perror(its_stream.str().c_str()); + return false; + } else { + return true; + } + } + +protected: + std::shared_ptr<configuration> configuration_; + vsomeip::client_t client_id_routing_manager_; +}; + +TEST_F(client_id_utility_test, request_release_client_id) { + client_t its_client_id = utility::request_client_id(configuration_, + APPLICATION_NAME_NOT_PREDEFINED, 0x0); + EXPECT_EQ(0x6302, its_client_id); + + utility::release_client_id(its_client_id); +} + +TEST_F(client_id_utility_test, request_client_id_twice) { + client_t its_client_id = utility::request_client_id(configuration_, + APPLICATION_NAME_NOT_PREDEFINED, 0x0); + EXPECT_EQ(0x6302, its_client_id); + + client_t its_client_id_2 = utility::request_client_id(configuration_, + APPLICATION_NAME_NOT_PREDEFINED, 0x0); + EXPECT_EQ(0x6303, its_client_id_2); + + utility::release_client_id(its_client_id); + utility::release_client_id(its_client_id_2); +} + +TEST_F(client_id_utility_test, release_unknown_client_id) { + client_t its_client_id = utility::request_client_id(configuration_, + APPLICATION_NAME_NOT_PREDEFINED, 0x0); + EXPECT_EQ(0x6302, its_client_id); + + utility::release_client_id(0x4711); + utility::release_client_id(its_client_id); + + client_t its_client_id_2 = utility::request_client_id(configuration_, + APPLICATION_NAME_NOT_PREDEFINED, 0x0); + EXPECT_EQ(0x6303, its_client_id_2); + utility::release_client_id(its_client_id_2); +} + +TEST_F(client_id_utility_test, release_client_id_twice) +{ + client_t its_client_id = utility::request_client_id(configuration_, + APPLICATION_NAME_NOT_PREDEFINED, 0x0); + EXPECT_EQ(0x6302, its_client_id); + + utility::release_client_id(its_client_id); + utility::release_client_id(its_client_id); + + client_t its_client_id_2 = utility::request_client_id(configuration_, + APPLICATION_NAME_NOT_PREDEFINED, 0x0); + EXPECT_EQ(0x6303, its_client_id_2); + utility::release_client_id(its_client_id_2); +} + +TEST_F(client_id_utility_test, ensure_preconfigured_client_ids_not_used_for_autoconfig) +{ + const std::uint8_t limit = APPLICATION_IN_CLIENT_ID & 0xFF; + std::vector<client_t> its_client_ids; + for (int i = 0; i < limit + 10; i++ ) { + client_t its_client_id = utility::request_client_id(configuration_, + APPLICATION_NAME_NOT_PREDEFINED, 0x0); + EXPECT_NE(ILLEGAL_CLIENT, its_client_id); + if (its_client_id != ILLEGAL_CLIENT) { + its_client_ids.push_back(its_client_id); + EXPECT_NE(APPLICATION_IN_CLIENT_ID, its_client_id); + } else { + ADD_FAILURE() << "Received ILLEGAL_CLIENT " + << static_cast<std::uint32_t>(i); + } + } + + // release all + for (const client_t c : its_client_ids) { + utility::release_client_id(c); + } +} + +TEST_F(client_id_utility_test, + ensure_preconfigured_client_ids_in_diagnosis_range_dont_influence_autoconfig_client_ids) +{ + client_t its_client_id = utility::request_client_id(configuration_, + APPLICATION_NAME_NOT_PREDEFINED, 0x0); + EXPECT_EQ(0x6302, its_client_id); + + client_t its_client_id2 = utility::request_client_id(configuration_, + APPLICATION_IN_NAME, APPLICATION_IN_CLIENT_ID); + EXPECT_EQ(APPLICATION_IN_CLIENT_ID, its_client_id2); + + client_t its_client_id3 = utility::request_client_id(configuration_, + APPLICATION_IN_NAME_TWO, APPLICATION_IN_CLIENT_ID_TWO); + EXPECT_EQ(APPLICATION_IN_CLIENT_ID_TWO, its_client_id3); + + + client_t its_client_id4 = utility::request_client_id(configuration_, + APPLICATION_NAME_NOT_PREDEFINED, 0x0); + EXPECT_EQ(0x6303, its_client_id4); + + client_t its_client_id5 = utility::request_client_id(configuration_, + APPLICATION_NAME_NOT_PREDEFINED, 0x0); + EXPECT_EQ(0x6304, its_client_id5); + + utility::release_client_id(its_client_id); + utility::release_client_id(its_client_id2); + utility::release_client_id(its_client_id3); + utility::release_client_id(its_client_id4); + utility::release_client_id(its_client_id5); +} + +TEST_F(client_id_utility_test, + request_predefined_client_id_in_diagnosis_range) { + client_t its_client_id = utility::request_client_id(configuration_, + APPLICATION_IN_NAME, APPLICATION_IN_CLIENT_ID); + EXPECT_EQ(APPLICATION_IN_CLIENT_ID, its_client_id); + + utility::release_client_id(its_client_id); +} + +TEST_F(client_id_utility_test, + request_predefined_client_id_in_diagnosis_range_twice) { + client_t its_client_id = utility::request_client_id(configuration_, + APPLICATION_IN_NAME, APPLICATION_IN_CLIENT_ID); + EXPECT_EQ(APPLICATION_IN_CLIENT_ID, its_client_id); + + client_t its_client_id_2 = utility::request_client_id(configuration_, + APPLICATION_IN_NAME, APPLICATION_IN_CLIENT_ID); + EXPECT_EQ(0x6302, its_client_id_2); + + utility::release_client_id(its_client_id); + utility::release_client_id(its_client_id_2); +} + +TEST_F(client_id_utility_test, + request_different_client_id_with_predefined_app_name_in_diagnosis_range) { + client_t its_client_id = utility::request_client_id(configuration_, + APPLICATION_IN_NAME, APPLICATION_IN_CLIENT_ID + 1u); + // has to get predefined client id although other was requested + EXPECT_EQ(APPLICATION_IN_CLIENT_ID, its_client_id); + + // predefined in json is now already used and requested should be assigned + client_t its_client_id_2 = utility::request_client_id(configuration_, + APPLICATION_IN_NAME, APPLICATION_IN_CLIENT_ID + 1u); + EXPECT_EQ(APPLICATION_IN_CLIENT_ID + 1u, its_client_id_2); + + client_t its_client_id_3 = utility::request_client_id(configuration_, + APPLICATION_IN_NAME, APPLICATION_IN_CLIENT_ID); + EXPECT_EQ(0x6302, its_client_id_3); + + utility::release_client_id(its_client_id); + utility::release_client_id(its_client_id_2); + utility::release_client_id(its_client_id_3); +} + +TEST_F(client_id_utility_test, + request_predefined_client_id_outside_diagnosis_range_low) { + client_t its_client_id = utility::request_client_id(configuration_, + APPLICATION_OUT_LOW_NAME, APPLICATION_OUT_LOW_CLIENT_ID); + EXPECT_EQ(APPLICATION_OUT_LOW_CLIENT_ID, its_client_id); + + utility::release_client_id(its_client_id); +} + +TEST_F(client_id_utility_test, + request_predefined_client_id_outside_diagnosis_range_low_twice) { + client_t its_client_id = utility::request_client_id(configuration_, + APPLICATION_OUT_LOW_NAME, APPLICATION_OUT_LOW_CLIENT_ID); + EXPECT_EQ(APPLICATION_OUT_LOW_CLIENT_ID, its_client_id); + + client_t its_client_id_2 = utility::request_client_id(configuration_, + APPLICATION_OUT_LOW_NAME, APPLICATION_OUT_LOW_CLIENT_ID); + EXPECT_EQ(0x6302, its_client_id_2); + + utility::release_client_id(its_client_id); + utility::release_client_id(its_client_id_2); +} + +TEST_F(client_id_utility_test, + request_different_client_id_with_predefined_app_name_outside_diagnosis_range_low) { + client_t its_client_id = utility::request_client_id(configuration_, + APPLICATION_OUT_LOW_NAME, APPLICATION_OUT_LOW_CLIENT_ID + 1u); + // has to get predefined client id although other was requested + EXPECT_EQ(APPLICATION_OUT_LOW_CLIENT_ID, its_client_id); + + // predefined in json is now already used and requested should be assigned + client_t its_client_id_2 = utility::request_client_id(configuration_, + APPLICATION_OUT_LOW_NAME, APPLICATION_OUT_LOW_CLIENT_ID + 1u); + EXPECT_EQ(APPLICATION_OUT_LOW_CLIENT_ID + 1u, its_client_id_2); + + client_t its_client_id_3 = utility::request_client_id(configuration_, + APPLICATION_OUT_LOW_NAME, APPLICATION_OUT_LOW_CLIENT_ID); + EXPECT_EQ(0x6302, its_client_id_3); + + utility::release_client_id(its_client_id); + utility::release_client_id(its_client_id_2); + utility::release_client_id(its_client_id_3); +} + +TEST_F(client_id_utility_test, + request_predefined_client_id_outside_diagnosis_range_high) { + client_t its_client_id = utility::request_client_id(configuration_, + APPLICATION_OUT_HIGH_NAME, APPLICATION_OUT_HIGH_CLIENT_ID); + EXPECT_EQ(APPLICATION_OUT_HIGH_CLIENT_ID, its_client_id); + + utility::release_client_id(its_client_id); +} + +TEST_F(client_id_utility_test, + request_predefined_client_id_outside_diagnosis_range_high_twice) { + client_t its_client_id = utility::request_client_id(configuration_, + APPLICATION_OUT_HIGH_NAME, APPLICATION_OUT_HIGH_CLIENT_ID); + EXPECT_EQ(APPLICATION_OUT_HIGH_CLIENT_ID, its_client_id); + + client_t its_client_id_2 = utility::request_client_id(configuration_, + APPLICATION_OUT_HIGH_NAME, APPLICATION_OUT_HIGH_CLIENT_ID); + EXPECT_EQ(0x6302, its_client_id_2); + + utility::release_client_id(its_client_id); + utility::release_client_id(its_client_id_2); +} + +TEST_F(client_id_utility_test, + request_different_client_id_with_predefined_app_name_outside_diagnosis_range_high) { + client_t its_client_id = utility::request_client_id(configuration_, + APPLICATION_OUT_HIGH_NAME, APPLICATION_OUT_HIGH_CLIENT_ID + 1u); + // has to get predefined client id although other was requested + EXPECT_EQ(APPLICATION_OUT_HIGH_CLIENT_ID, its_client_id); + + // predefined in json is now already used and requested should be assigned + client_t its_client_id_2 = utility::request_client_id(configuration_, + APPLICATION_OUT_HIGH_NAME, APPLICATION_OUT_HIGH_CLIENT_ID + 1u); + EXPECT_EQ(APPLICATION_OUT_HIGH_CLIENT_ID + 1u, its_client_id_2); + + client_t its_client_id_3 = utility::request_client_id(configuration_, + APPLICATION_OUT_HIGH_NAME, APPLICATION_OUT_HIGH_CLIENT_ID); + EXPECT_EQ(0x6302, its_client_id_3); + + utility::release_client_id(its_client_id); + utility::release_client_id(its_client_id_2); + utility::release_client_id(its_client_id_3); +} + + +TEST_F(client_id_utility_test, exhaust_client_id_range_sequential) { + std::vector<client_t> its_client_ids; + + // -1 for the routing manager, -2 as two predefined client IDs are present + // in the json file which aren't assigned via autoconfiguration + std::uint8_t max_allowed_clients = 0xFF - 3; + // acquire maximum amount of client IDs + for (std::uint8_t i = 0; i < max_allowed_clients; i++) { + client_t its_client_id = utility::request_client_id(configuration_, + APPLICATION_NAME_NOT_PREDEFINED, 0x0); + EXPECT_NE(ILLEGAL_CLIENT, its_client_id); + if (its_client_id != ILLEGAL_CLIENT) { + its_client_ids.push_back(its_client_id); + } else { + ADD_FAILURE() << "Received ILLEGAL_CLIENT " + << static_cast<std::uint32_t>(i); + } + } + + // check limit is reached + client_t its_illegal_client_id = utility::request_client_id(configuration_, + APPLICATION_NAME_NOT_PREDEFINED, 0x0); + EXPECT_EQ(ILLEGAL_CLIENT, its_illegal_client_id); + + // release all + for (const client_t c : its_client_ids) { + utility::release_client_id(c); + } + its_client_ids.clear(); + its_illegal_client_id = 0xFFFF; + + // One more time! + + // acquire maximum amount of client IDs + for (std::uint8_t i = 0; i < max_allowed_clients; i++) { + client_t its_client_id = utility::request_client_id(configuration_, + APPLICATION_NAME_NOT_PREDEFINED, 0x0); + EXPECT_NE(ILLEGAL_CLIENT, its_client_id); + if (its_client_id != ILLEGAL_CLIENT) { + its_client_ids.push_back(its_client_id); + } else { + ADD_FAILURE() << "Received ILLEGAL_CLIENT " + << static_cast<std::uint32_t>(i); + } + } + + // check limit is reached + its_illegal_client_id = utility::request_client_id(configuration_, + APPLICATION_NAME_NOT_PREDEFINED, 0x0); + EXPECT_EQ(ILLEGAL_CLIENT, its_illegal_client_id); + + // release all + for (const client_t c : its_client_ids) { + utility::release_client_id(c); + } + } + +TEST_F(client_id_utility_test, exhaust_client_id_range_fragmented) { + std::vector<client_t> its_client_ids; + + // -1 for the routing manager, -2 as two predefined client IDs are present + // in the json file which aren't assigned via autoconfiguration + std::uint8_t max_allowed_clients = 0xFF - 3; + // acquire maximum amount of client IDs + for (std::uint8_t i = 0; i < max_allowed_clients; i++) { + client_t its_client_id = utility::request_client_id(configuration_, + APPLICATION_NAME_NOT_PREDEFINED, 0x0); + EXPECT_NE(ILLEGAL_CLIENT, its_client_id); + if (its_client_id != ILLEGAL_CLIENT) { + its_client_ids.push_back(its_client_id); + } else { + ADD_FAILURE() << "Received ILLEGAL_CLIENT " + << static_cast<std::uint32_t>(i); + } + } + + // check limit is reached + client_t its_illegal_client_id = utility::request_client_id(configuration_, + APPLICATION_NAME_NOT_PREDEFINED, 0x0); + EXPECT_EQ(ILLEGAL_CLIENT, its_illegal_client_id); + + // release every second requested client ID + std::vector<client_t> its_released_client_ids; + for (size_t i = 0; i < its_client_ids.size(); i++ ) { + if (i % 2) { + its_released_client_ids.push_back(its_client_ids[i]); + utility::release_client_id(its_client_ids[i]); + } + } + for (const client_t c : its_released_client_ids) { + for (auto it = its_client_ids.begin(); it != its_client_ids.end(); ) { + if (*it == c) { + it = its_client_ids.erase(it); + } else { + ++it; + } + } + } + + // acquire client IDs up to the maximum allowed amount again + for (std::uint8_t i = 0; i < its_released_client_ids.size(); i++) { + client_t its_client_id = utility::request_client_id(configuration_, + APPLICATION_NAME_NOT_PREDEFINED, 0x0); + EXPECT_NE(ILLEGAL_CLIENT, its_client_id); + if (its_client_id != ILLEGAL_CLIENT) { + its_client_ids.push_back(its_client_id); + } else { + ADD_FAILURE() << "Received ILLEGAL_CLIENT " + << static_cast<std::uint32_t>(i); + } + } + + // check limit is reached + its_illegal_client_id = 0xFFFF; + its_illegal_client_id = utility::request_client_id(configuration_, + APPLICATION_NAME_NOT_PREDEFINED, 0x0); + EXPECT_EQ(ILLEGAL_CLIENT, its_illegal_client_id); + + // release all + for (const client_t c : its_client_ids) { + utility::release_client_id(c); + } +} + +#ifndef WIN32 +int main(int argc, char** argv) { + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} +#endif diff --git a/test/client_id_tests/client_id_test_utility.json b/test/client_id_tests/client_id_test_utility.json new file mode 100644 index 0000000..ea0aaa0 --- /dev/null +++ b/test/client_id_tests/client_id_test_utility.json @@ -0,0 +1,38 @@ +{ + "unicast":"127.0.0.1", + "logging": + { + "level":"warning", + "console":"true", + "file": + { + "enable":"false", + "path":"/tmp/vsomeip.log" + }, + + "dlt":"false" + }, + "diagnosis" : "0x63", + "applications": + [ + { + "name":"client_id_test_utility_service_in", + "id":"0x6311" + }, + { + "name":"client_id_test_utility_service_in_two", + "id":"0x6312" + }, + { + "name":"client_id_test_utility_service_out_low", + "id":"0x6011" + }, + + { + "name":"client_id_test_utility_service_out_high", + "id":"0x6411" + } + ], + + "routing":"vsomeipd" +}
\ No newline at end of file diff --git a/test/cpu_load_tests/cpu_load_test_client.cpp b/test/cpu_load_tests/cpu_load_test_client.cpp index dd732e3..5935774 100644 --- a/test/cpu_load_tests/cpu_load_test_client.cpp +++ b/test/cpu_load_tests/cpu_load_test_client.cpp @@ -53,8 +53,8 @@ public: wait_for_all_msg_acknowledged_(true), sender_(std::bind(&cpu_load_test_client::run, this)) { if (!app_->init()) { - VSOMEIP_ERROR << "Couldn't initialize application"; - EXPECT_TRUE(false); + ADD_FAILURE() << "Couldn't initialize application"; + return; } app_->register_state_handler( diff --git a/test/cpu_load_tests/cpu_load_test_master_starter.sh b/test/cpu_load_tests/cpu_load_test_master_starter.sh index bc135fc..ddcfa3d 100755 --- a/test/cpu_load_tests/cpu_load_test_master_starter.sh +++ b/test/cpu_load_tests/cpu_load_test_master_starter.sh @@ -14,9 +14,13 @@ FAIL=0 export VSOMEIP_CONFIGURATION=cpu_load_test_client_master.json ./cpu_load_test_client --protocol UDP --calls 1000 & - +TEST_CLIENT_PID=$! sleep 1 +if [ ! -z "$USE_LXC_TEST" ]; then + echo "starting cpu load test on slave LXC" + ssh -tt -i $SANDBOX_ROOT_DIR/commonapi_main/lxc-config/.ssh/mgc_lxc/rsa_key_file.pub -o StrictHostKeyChecking=no root@$LXC_TEST_SLAVE_IP 'bash -ci "set -m; cd \$SANDBOX_ROOT_DIR/ctarget/vsomeip/test; ./cpu_load_test_slave_starter.sh"' & +else cat <<End-of-message ******************************************************************************* ******************************************************************************* @@ -32,19 +36,18 @@ cat <<End-of-message ******************************************************************************* ******************************************************************************* End-of-message +fi + +# Fail gets incremented if either client or service exit +# with a non-zero exit code +wait $TEST_CLIENT_PID || FAIL=$(($FAIL+1)) -for job in $(jobs -p) -do - # Fail gets incremented if either client or service exit - # with a non-zero exit code - wait $job || FAIL=$(($FAIL+1)) -done sleep 4 cat <<End-of-message ******************************************************************************* ******************************************************************************* -** Now switching roles and running service on this host +** Now switching roles and running service on this host (master) ******************************************************************************* ******************************************************************************* End-of-message @@ -53,6 +56,7 @@ export VSOMEIP_CONFIGURATION=cpu_load_test_service_master.json ./cpu_load_test_service & sleep 1 +# now we can wait to all jobs to finish for job in $(jobs -p) do # Fail gets incremented if either client or service exit diff --git a/test/cpu_load_tests/cpu_load_test_service.cpp b/test/cpu_load_tests/cpu_load_test_service.cpp index 67b4ef9..f8fbde3 100644 --- a/test/cpu_load_tests/cpu_load_test_service.cpp +++ b/test/cpu_load_tests/cpu_load_test_service.cpp @@ -36,13 +36,13 @@ public: { } - void init() + bool init() { std::lock_guard<std::mutex> its_lock(mutex_); if (!app_->init()) { - VSOMEIP_ERROR << "Couldn't initialize application"; - EXPECT_TRUE(false); + ADD_FAILURE() << "Couldn't initialize application"; + return false; } app_->register_message_handler(cpu_load_test::service_id, cpu_load_test::instance_id, cpu_load_test::method_id, @@ -64,6 +64,7 @@ public: app_->register_state_handler( std::bind(&cpu_load_test_service::on_state, this, std::placeholders::_1)); + return true; } void start() @@ -189,9 +190,10 @@ private: TEST(someip_payload_test, send_response_for_every_request) { cpu_load_test_service test_service; - test_service.init(); - test_service.start(); - test_service.join_offer_thread(); + if (test_service.init()) { + test_service.start(); + test_service.join_offer_thread(); + } } #ifndef WIN32 diff --git a/test/cpu_load_tests/cpu_load_test_slave_starter.sh b/test/cpu_load_tests/cpu_load_test_slave_starter.sh index e6731b7..9c68c48 100755 --- a/test/cpu_load_tests/cpu_load_test_slave_starter.sh +++ b/test/cpu_load_tests/cpu_load_test_slave_starter.sh @@ -26,7 +26,7 @@ done cat <<End-of-message ******************************************************************************* ******************************************************************************* -** Now switching roles and running client on this host +** Now switching roles and running client on this host (slave) ******************************************************************************* ******************************************************************************* End-of-message diff --git a/test/header_factory_tests/header_factory_test_client.cpp b/test/header_factory_tests/header_factory_test_client.cpp index 2e08cbc..3870c17 100644 --- a/test/header_factory_tests/header_factory_test_client.cpp +++ b/test/header_factory_tests/header_factory_test_client.cpp @@ -18,11 +18,11 @@ header_factory_test_client::header_factory_test_client(bool _use_tcp) : { } -void header_factory_test_client::init() +bool header_factory_test_client::init() { if (!app_->init()) { - VSOMEIP_ERROR << "Couldn't initialize application"; - EXPECT_TRUE(false); + ADD_FAILURE() << "Couldn't initialize application"; + return false; } app_->register_state_handler( @@ -39,6 +39,7 @@ void header_factory_test_client::init() std::bind(&header_factory_test_client::on_availability, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); + return true; } void header_factory_test_client::start() @@ -155,9 +156,10 @@ TEST(someip_header_factory_test, send_message_ten_times_test) { bool use_tcp = false; header_factory_test_client test_client_(use_tcp); - test_client_.init(); - test_client_.start(); - test_client_.join_sender_thread(); + if (test_client_.init()) { + test_client_.start(); + test_client_.join_sender_thread(); + } } #ifndef WIN32 diff --git a/test/header_factory_tests/header_factory_test_client.hpp b/test/header_factory_tests/header_factory_test_client.hpp index 1b96edd..911c754 100644 --- a/test/header_factory_tests/header_factory_test_client.hpp +++ b/test/header_factory_tests/header_factory_test_client.hpp @@ -21,7 +21,7 @@ class header_factory_test_client { public: header_factory_test_client(bool _use_tcp); - void init(); + bool init(); void start(); void stop(); void join_sender_thread(); diff --git a/test/header_factory_tests/header_factory_test_service.cpp b/test/header_factory_tests/header_factory_test_service.cpp index 0ff516f..9a06762 100644 --- a/test/header_factory_tests/header_factory_test_service.cpp +++ b/test/header_factory_tests/header_factory_test_service.cpp @@ -17,13 +17,13 @@ header_factory_test_service::header_factory_test_service(bool _use_static_routin { } -void header_factory_test_service::init() +bool header_factory_test_service::init() { std::lock_guard<std::mutex> its_lock(mutex_); if (!app_->init()) { - VSOMEIP_ERROR << "Couldn't initialize application"; - EXPECT_TRUE(false); + 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, @@ -35,6 +35,7 @@ void header_factory_test_service::init() std::placeholders::_1)); VSOMEIP_INFO << "Static routing " << (use_static_routing_ ? "ON" : "OFF"); + return true; } void header_factory_test_service::start() @@ -153,9 +154,10 @@ TEST(someip_header_factory_test, reveice_message_ten_times_test) { bool use_static_routing = true; header_factory_test_service test_service(use_static_routing); - test_service.init(); - test_service.start(); - test_service.join_offer_thread(); + if (test_service.init()) { + test_service.start(); + test_service.join_offer_thread(); + } } #ifndef WIN32 diff --git a/test/header_factory_tests/header_factory_test_service.hpp b/test/header_factory_tests/header_factory_test_service.hpp index b58a29b..a28d040 100644 --- a/test/header_factory_tests/header_factory_test_service.hpp +++ b/test/header_factory_tests/header_factory_test_service.hpp @@ -20,7 +20,7 @@ class header_factory_test_service { public: header_factory_test_service(bool _use_static_routing); - void init(); + bool init(); void start(); void stop(); void offer(); diff --git a/test/initial_event_tests/initial_event_test_availability_checker.cpp b/test/initial_event_tests/initial_event_test_availability_checker.cpp index 34c20c1..69ae6ee 100644 --- a/test/initial_event_tests/initial_event_test_availability_checker.cpp +++ b/test/initial_event_tests/initial_event_test_availability_checker.cpp @@ -32,8 +32,8 @@ public: wait_for_stop_(true), stop_thread_(std::bind(&initial_event_test_availability_checker::wait_for_stop, this)) { if (!app_->init()) { - VSOMEIP_ERROR << "Couldn't initialize application"; - EXPECT_TRUE(false); + ADD_FAILURE() << "Couldn't initialize application"; + return; } app_->register_state_handler( std::bind(&initial_event_test_availability_checker::on_state, this, diff --git a/test/initial_event_tests/initial_event_test_client.cpp b/test/initial_event_tests/initial_event_test_client.cpp index d525632..caa79cb 100644 --- a/test/initial_event_tests/initial_event_test_client.cpp +++ b/test/initial_event_tests/initial_event_test_client.cpp @@ -34,8 +34,8 @@ public: wait_for_stop_(true), stop_thread_(std::bind(&initial_event_test_client::wait_for_stop, this)) { if (!app_->init()) { - VSOMEIP_ERROR << "Couldn't initialize application"; - EXPECT_TRUE(false); + ADD_FAILURE() << "Couldn't initialize application"; + return; } app_->register_state_handler( std::bind(&initial_event_test_client::on_state, this, diff --git a/test/initial_event_tests/initial_event_test_master_starter.sh b/test/initial_event_tests/initial_event_test_master_starter.sh index 3273817..471b973 100755 --- a/test/initial_event_tests/initial_event_test_master_starter.sh +++ b/test/initial_event_tests/initial_event_test_master_starter.sh @@ -46,6 +46,11 @@ then fi print_starter_message () { + +if [ ! -z "$USE_LXC_TEST" ]; then + echo "starting initial event test on slave LXC with params $PASSED_SUBSCRIPTION_TYPE $CLIENT_JSON_FILE $PASSED_SAME_SERVICE_ID_FLAG" + ssh -tt -i $SANDBOX_ROOT_DIR/commonapi_main/lxc-config/.ssh/mgc_lxc/rsa_key_file.pub -o StrictHostKeyChecking=no root@$LXC_TEST_SLAVE_IP "bash -ci \"set -m; cd \\\$SANDBOX_ROOT_DIR/ctarget/vsomeip/test; ./initial_event_test_slave_starter.sh $PASSED_SUBSCRIPTION_TYPE $CLIENT_JSON_FILE $PASSED_SAME_SERVICE_ID_FLAG\"" & +else cat <<End-of-message ******************************************************************************* ******************************************************************************* @@ -59,6 +64,7 @@ cat <<End-of-message ******************************************************************************* ******************************************************************************* End-of-message +fi } # replace master with slave to be able display the correct json file to be used diff --git a/test/initial_event_tests/initial_event_test_service.cpp b/test/initial_event_tests/initial_event_test_service.cpp index f02a493..5823a09 100644 --- a/test/initial_event_tests/initial_event_test_service.cpp +++ b/test/initial_event_tests/initial_event_test_service.cpp @@ -28,8 +28,8 @@ public: wait_until_registered_(true), offer_thread_(std::bind(&initial_event_test_service::run, this)) { if (!app_->init()) { - VSOMEIP_ERROR << "Couldn't initialize application"; - EXPECT_TRUE(false); + ADD_FAILURE() << "Couldn't initialize application"; + return; } app_->register_state_handler( std::bind(&initial_event_test_service::on_state, this, diff --git a/test/initial_event_tests/initial_event_test_stop_service.cpp b/test/initial_event_tests/initial_event_test_stop_service.cpp index cd8a34a..a17e0d8 100644 --- a/test/initial_event_tests/initial_event_test_stop_service.cpp +++ b/test/initial_event_tests/initial_event_test_stop_service.cpp @@ -34,8 +34,8 @@ public: stop_thread_(std::bind(&initial_event_test_stop_service::wait_for_stop, this)), called_other_node_(false) { if (!app_->init()) { - VSOMEIP_ERROR << "Couldn't initialize application"; - EXPECT_TRUE(false); + ADD_FAILURE() << "Couldn't initialize application"; + return; } app_->register_state_handler( std::bind(&initial_event_test_stop_service::on_state, this, diff --git a/test/magic_cookies_tests/magic_cookies_test_client.cpp b/test/magic_cookies_tests/magic_cookies_test_client.cpp index 35eba2e..8be1eaf 100644 --- a/test/magic_cookies_tests/magic_cookies_test_client.cpp +++ b/test/magic_cookies_tests/magic_cookies_test_client.cpp @@ -9,6 +9,8 @@ #include <memory> #include <thread> +#include <gtest/gtest.h> + #include <vsomeip/vsomeip.hpp> #include "../someip_test_globals.hpp" @@ -21,13 +23,18 @@ public: : app_(new vsomeip::application_impl("")), is_available_(false), is_blocked_(false), + sent_messages_good_(8), + sent_messages_bad_(7), + received_responses_(0), + received_errors_(0), + wait_for_replies_(true), runner_(std::bind(&magic_cookies_test_client::run, this)) { } void init() { VSOMEIP_INFO << "Initializing..."; if (!app_->init()) { - VSOMEIP_ERROR << "Couldn't initialize application"; + ADD_FAILURE() << "Couldn't initialize application"; exit(EXIT_FAILURE); } @@ -99,6 +106,7 @@ public: << "/" << std::setw(4) << std::setfill('0') << std::hex << _response->get_session() << "]"; + received_responses_++; } else if (_response->get_return_code() == vsomeip::return_code_e::E_MALFORMED_MESSAGE) { VSOMEIP_INFO << "Received an error message from Service [" << std::setw(4) << std::setfill('0') << std::hex << _response->get_service() @@ -109,6 +117,13 @@ public: << "/" << std::setw(4) << std::setfill('0') << std::hex << _response->get_session() << "]"; + received_errors_++; + } + if (received_errors_ == sent_messages_bad_ + && received_responses_ == sent_messages_good_) { + std::lock_guard<std::mutex> its_lock(mutex_); + wait_for_replies_ = false; + condition_.notify_one(); } } @@ -118,7 +133,13 @@ public: void run() { std::unique_lock< std::mutex > its_lock(mutex_); - while (!is_blocked_) condition_.wait(its_lock); + while (!is_blocked_) { + if (std::cv_status::timeout == + condition_.wait_for(its_lock, std::chrono::milliseconds(5000))) { + GTEST_NONFATAL_FAILURE_("Service didn't become available within 5s."); + break; + } + } VSOMEIP_INFO << "Running..."; vsomeip::routing_manager *its_routing = app_->get_routing_manager(); @@ -171,7 +192,15 @@ public: its_good_payload_data[11] = 0x0F; its_routing->send(0x1343, its_good_payload_data, sizeof(its_good_payload_data), vsomeip_test::TEST_SERVICE_INSTANCE_ID, true, true); - std::this_thread::sleep_for(std::chrono::milliseconds(2000)); + while (wait_for_replies_) { + if(std::cv_status::timeout == + condition_.wait_for(its_lock, std::chrono::milliseconds(5000))) { + GTEST_NONFATAL_FAILURE_("Didn't receive all replies/errors in time"); + break; + } + } + EXPECT_EQ(sent_messages_good_, received_responses_); + EXPECT_EQ(sent_messages_bad_, received_errors_); stop(); } @@ -181,16 +210,25 @@ private: std::condition_variable condition_; bool is_available_; bool is_blocked_; + const std::uint32_t sent_messages_good_; + const std::uint32_t sent_messages_bad_; + std::atomic<std::uint32_t> received_responses_; + std::atomic<std::uint32_t> received_errors_; + bool wait_for_replies_; std::thread runner_; }; - -int main() { +TEST(someip_magic_cookies_test, send_good_and_bad_messages) +{ magic_cookies_test_client its_client; its_client.init(); its_client.start(); its_client.join(); - return 0; +} + +int main(int argc, char** argv) { + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); } diff --git a/test/magic_cookies_tests/magic_cookies_test_service.cpp b/test/magic_cookies_tests/magic_cookies_test_service.cpp index 1a186b0..a69084d 100644 --- a/test/magic_cookies_tests/magic_cookies_test_service.cpp +++ b/test/magic_cookies_tests/magic_cookies_test_service.cpp @@ -10,6 +10,8 @@ #include <sstream> #include <thread> +#include <gtest/gtest.h> + #include <vsomeip/vsomeip.hpp> #include "../someip_test_globals.hpp" @@ -31,7 +33,7 @@ public: std::lock_guard<std::mutex> its_lock(mutex_); if (!app_->init()) { - VSOMEIP_ERROR << "Couldn't initialize application"; + ADD_FAILURE() << "Couldn't initialize application"; exit(EXIT_FAILURE); } app_->register_message_handler( @@ -112,7 +114,11 @@ public: if (use_static_routing_) { offer(); while (!blocked_) { - condition_.wait(its_lock); + if(std::cv_status::timeout == + condition_.wait_for(its_lock, std::chrono::seconds(55))) { + GTEST_NONFATAL_FAILURE_("Didn't receive all requests within time"); + break; + } } std::this_thread::sleep_for(std::chrono::milliseconds(5)); app_->clear_all_handler(); @@ -140,20 +146,22 @@ private: std::thread offer_thread_; }; -int main(int argc, char **argv) { - bool use_static_routing(false); +static bool use_static_routing = false; - std::string static_routing_enable("--static-routing"); +TEST(someip_magic_cookies_test, reply_to_good_messages) +{ + magic_cookies_test_service its_sample(use_static_routing); + its_sample.init(); + its_sample.start(); +} +int main(int argc, char** argv) { + ::testing::InitGoogleTest(&argc, argv); + std::string static_routing_enable("--static-routing"); for (int i = 1; i < argc; i++) { if (static_routing_enable == argv[i]) { use_static_routing = true; } } - - magic_cookies_test_service its_sample(use_static_routing); - its_sample.init(); - its_sample.start(); - - return 0; + return RUN_ALL_TESTS(); } diff --git a/test/magic_cookies_tests/magic_cookies_test_starter.sh b/test/magic_cookies_tests/magic_cookies_test_starter.sh index 57efc67..aba3b0b 100755 --- a/test/magic_cookies_tests/magic_cookies_test_starter.sh +++ b/test/magic_cookies_tests/magic_cookies_test_starter.sh @@ -12,6 +12,13 @@ # Display a message to show the user that he must now call the external service # to finish the test successfully + +FAIL=0 + +if [ ! -z "$USE_LXC_TEST" ]; then + echo "starting magic cookies test on slave LXC" + ssh -tt -i $SANDBOX_ROOT_DIR/commonapi_main/lxc-config/.ssh/mgc_lxc/rsa_key_file.pub -o StrictHostKeyChecking=no root@$LXC_TEST_SLAVE_IP "bash -ci \"set -m; cd \\\$SANDBOX_ROOT_DIR/ctarget/vsomeip/test; ./magic_cookies_test_client_start.sh\"" & +else cat <<End-of-message ******************************************************************************* ******************************************************************************* @@ -26,10 +33,25 @@ cat <<End-of-message ******************************************************************************* ******************************************************************************* End-of-message +fi # Start the client for magic-cookies test export VSOMEIP_APPLICATION_NAME=magic_cookies_test_service export VSOMEIP_CONFIGURATION=magic_cookies_test_service.json -./magic_cookies_test_service --tcp --static-routing +./magic_cookies_test_service --tcp --static-routing & + +# Wait until client and service are finished +for job in $(jobs -p) +do + # Fail gets incremented if either client or service exit + # with a non-zero exit code + wait $job || ((FAIL+=1)) +done -exit $? +# Check if client and server both exited successfully +if [ $FAIL -eq 0 ] +then + exit 0 +else + exit 1 +fi diff --git a/test/offer_tests/conf/offer_test_external_master_starter.sh.in b/test/offer_tests/conf/offer_test_external_master_starter.sh.in index 9ff40e8..6c9f72b 100755 --- a/test/offer_tests/conf/offer_test_external_master_starter.sh.in +++ b/test/offer_tests/conf/offer_test_external_master_starter.sh.in @@ -28,12 +28,21 @@ PID_VSOMEIPD=$! # Start the services ./offer_test_service 2 & PID_SERVICE_TWO=$! +echo "SERVICE_TWO pid $PID_SERVICE_TWO" ./offer_test_client SUBSCRIBE & CLIENT_PIDS+=($!) +echo "client pid ${CLIENT_PIDS[0]}" sleep 1 +if [ ! -z "$USE_LXC_TEST" ]; then + echo "Waiting for 5s" + sleep 5 + echo "starting offer test on slave LXC offer_test_external_slave_starter.sh" + ssh -tt -i $SANDBOX_ROOT_DIR/commonapi_main/lxc-config/.ssh/mgc_lxc/rsa_key_file.pub -o StrictHostKeyChecking=no root@$LXC_TEST_SLAVE_IP "bash -ci \"set -m; cd \\\$SANDBOX_ROOT_DIR/ctarget/vsomeip/test; ./offer_test_external_slave_starter.sh\"" & + echo "remote ssh pid: $!" +else cat <<End-of-message ******************************************************************************* ******************************************************************************* @@ -47,12 +56,13 @@ cat <<End-of-message ******************************************************************************* ******************************************************************************* End-of-message - +fi # Wait until all clients and services are finished for job in ${CLIENT_PIDS[*]} $PID_SERVICE_TWO do # Fail gets incremented if a client exits with a non-zero exit code + echo "waiting for $job" wait $job || FAIL=$(($FAIL+1)) done @@ -60,6 +70,14 @@ done kill $PID_VSOMEIPD sleep 1 +# wait for slave to finish +for job in $(jobs -p) +do + # Fail gets incremented if either client or service exit + # with a non-zero exit code + echo "[Master] waiting for job $job" + wait $job || ((FAIL+=1)) +done # Rejecting remote offer for which there is already a local offer # * start application which offers service @@ -78,9 +96,17 @@ PID_SERVICE_TWO=$! ./offer_test_client SUBSCRIBE & CLIENT_PIDS+=($!) +echo "client pid ${CLIENT_PIDS[0]}" sleep 1 +if [ ! -z "$USE_LXC_TEST" ]; then + echo "Waiting for 5s" + sleep 5 + echo "starting offer test on slave LXC offer_test_external_sd_msg_sender" + ssh -tt -i $SANDBOX_ROOT_DIR/commonapi_main/lxc-config/.ssh/mgc_lxc/rsa_key_file.pub -o StrictHostKeyChecking=no root@$LXC_TEST_SLAVE_IP "bash -ci \"set -m; cd \\\$SANDBOX_ROOT_DIR/ctarget/vsomeip/test; ./offer_test_external_sd_msg_sender $LXC_TEST_MASTER_IP\"" & + echo "remote ssh job id: $!" +else cat <<End-of-message ******************************************************************************* ******************************************************************************* @@ -92,11 +118,13 @@ cat <<End-of-message ******************************************************************************* ******************************************************************************* End-of-message +fi # Wait until all clients and services are finished for job in ${CLIENT_PIDS[*]} $PID_SERVICE_TWO do # Fail gets incremented if a client exits with a non-zero exit code + echo "waiting for $job" wait $job || FAIL=$(($FAIL+1)) done @@ -104,6 +132,14 @@ done kill $PID_VSOMEIPD sleep 1 +# wait for slave to finish +for job in $(jobs -p) +do + # Fail gets incremented if either client or service exit + # with a non-zero exit code + echo "[Master] waiting for job $job" + wait $job || ((FAIL+=1)) +done # Check if everything went well if [ $FAIL -eq 0 ] diff --git a/test/offer_tests/offer_test_client.cpp b/test/offer_tests/offer_test_client.cpp index d338f13..493c3fa 100644 --- a/test/offer_tests/offer_test_client.cpp +++ b/test/offer_tests/offer_test_client.cpp @@ -41,8 +41,8 @@ public: last_received_response_(std::chrono::steady_clock::now()), number_received_responses_(0) { if (!app_->init()) { - VSOMEIP_ERROR << "Couldn't initialize application"; - EXPECT_TRUE(false); + ADD_FAILURE() << "Couldn't initialize application"; + return; } app_->register_state_handler( std::bind(&offer_test_client::on_state, this, diff --git a/test/offer_tests/offer_test_service.cpp b/test/offer_tests/offer_test_service.cpp index 2396d1a..f06de9e 100644 --- a/test/offer_tests/offer_test_service.cpp +++ b/test/offer_tests/offer_test_service.cpp @@ -36,8 +36,8 @@ public: offer_thread_(std::bind(&offer_test_service::run, this)), shutdown_method_called_(false) { if (!app_->init()) { - VSOMEIP_ERROR << "Couldn't initialize application"; - EXPECT_TRUE(false); + ADD_FAILURE() << "Couldn't initialize application"; + return; } app_->register_state_handler( std::bind(&offer_test_service::on_state, this, diff --git a/test/offer_tests/offer_test_service_external.cpp b/test/offer_tests/offer_test_service_external.cpp index c031587..2f74271 100644 --- a/test/offer_tests/offer_test_service_external.cpp +++ b/test/offer_tests/offer_test_service_external.cpp @@ -35,8 +35,8 @@ public: wait_until_service_available_(true), offer_thread_(std::bind(&offer_test_service::run, this)) { if (!app_->init()) { - VSOMEIP_ERROR << "Couldn't initialize application"; - EXPECT_TRUE(false); + ADD_FAILURE() << "Couldn't initialize application"; + return; } app_->register_state_handler( std::bind(&offer_test_service::on_state, this, diff --git a/test/payload_tests/external_local_payload_test_client_external_starter.sh b/test/payload_tests/external_local_payload_test_client_external_starter.sh index 87a70a6..b675b0a 100755 --- a/test/payload_tests/external_local_payload_test_client_external_starter.sh +++ b/test/payload_tests/external_local_payload_test_client_external_starter.sh @@ -56,6 +56,11 @@ SERIVCE_PID=$! # Display a message to show the user that he must now call the external client # to finish the test successfully +if [ ! -z "$USE_LXC_TEST" ]; then + echo "starting external local payload on slave LXC" + ssh -tt -i $SANDBOX_ROOT_DIR/commonapi_main/lxc-config/.ssh/mgc_lxc/rsa_key_file.pub -o StrictHostKeyChecking=no root@$LXC_TEST_SLAVE_IP "bash -ci \"set -m; cd \\\$SANDBOX_ROOT_DIR/ctarget/vsomeip/test; ./external_local_payload_test_client_external_start.sh\"" & + echo "remote ssh job id: $!" +else cat <<End-of-message ******************************************************************************* ******************************************************************************* @@ -69,6 +74,7 @@ cat <<End-of-message ******************************************************************************* ******************************************************************************* End-of-message +fi # The service should listen on a TCP and UDP socket now sleep 1 @@ -78,12 +84,11 @@ check_tcp_udp_sockets_are_open $SERIVCE_PID 2 # The client remotely shuts down the service if he has successfully transmitted # all the packets with different payloads. Therefore we can assume that everything # went well, even if we can only check the exit code of the service here. -for job in $(jobs -p) -do - # Fail gets incremented if either client or service exit - # with a non-zero exit code - wait $job || ((FAIL+=1)) -done + +# Fail gets incremented if either client or service exit +# with a non-zero exit code +wait $SERIVCE_PID || ((FAIL+=1)) + # Start the service for payload test with tcp export VSOMEIP_APPLICATION_NAME=external_local_payload_test_service @@ -100,12 +105,11 @@ check_tcp_udp_sockets_are_open $SERIVCE_PID 2 # The client remotely shuts down the service if he has successfully transmitted # all the packets with different payloads. Therefore we can assume that everything # went well, even if we can only check the exit code of the service here. -for job in $(jobs -p) -do - # Fail gets incremented if either client or service exit - # with a non-zero exit code - wait $job || ((FAIL+=1)) -done + +# Fail gets incremented if either client or service exit +# with a non-zero exit code +wait $SERIVCE_PID || ((FAIL+=1)) + # Check if server exited sucessfully if [ $FAIL -eq 0 ] diff --git a/test/payload_tests/external_local_payload_test_client_local_and_external_starter.sh b/test/payload_tests/external_local_payload_test_client_local_and_external_starter.sh index 1464bf9..bc4ce89 100755 --- a/test/payload_tests/external_local_payload_test_client_local_and_external_starter.sh +++ b/test/payload_tests/external_local_payload_test_client_local_and_external_starter.sh @@ -73,6 +73,11 @@ wait $CLIENT_PID || ((FAIL+=1)) # Display a message to show the user that he must now call the external client # to finish the test successfully +if [ ! -z "$USE_LXC_TEST" ]; then + echo "starting external local payload on slave LXC" + ssh -tt -i $SANDBOX_ROOT_DIR/commonapi_main/lxc-config/.ssh/mgc_lxc/rsa_key_file.pub -o StrictHostKeyChecking=no root@$LXC_TEST_SLAVE_IP "bash -ci \"set -m; cd \\\$SANDBOX_ROOT_DIR/ctarget/vsomeip/test; ./external_local_payload_test_client_external_start.sh\"" & + echo "remote ssh job id: $!" +else cat <<End-of-message ******************************************************************************* ******************************************************************************* @@ -86,6 +91,7 @@ cat <<End-of-message ******************************************************************************* ******************************************************************************* End-of-message +fi # The service should still listen on a TCP and UDP socket sleep 1 @@ -95,12 +101,11 @@ check_tcp_udp_sockets_are_open $SERIVCE_PID 2 # The client remotely shuts down the service if he has successfully transmitted # all the packets with different payloads. Therefore we can assume that everything # went well, even if we can only check the exit code of the service here. -for job in $(jobs -p) -do - # Fail gets incremented if either client or service exit - # with a non-zero exit code - wait $job || ((FAIL+=1)) -done + +# Fail gets incremented if either client or service exit +# with a non-zero exit code +wait $SERIVCE_PID || ((FAIL+=1)) + # Start the service for payload test with tcp export VSOMEIP_APPLICATION_NAME=external_local_payload_test_service @@ -117,12 +122,10 @@ check_tcp_udp_sockets_are_open $SERIVCE_PID 2 # The client remotely shuts down the service if he has successfully transmitted # all the packets with different payloads. Therefore we can assume that everything # went well, even if we can only check the exit code of the service here. -for job in $(jobs -p) -do - # Fail gets incremented if either client or service exit - # with a non-zero exit code - wait $job || ((FAIL+=1)) -done + +# Fail gets incremented if either client or service exit +# with a non-zero exit code +wait $SERIVCE_PID || ((FAIL+=1)) # Check if client and server both exited sucessfully and the service didnt't # have any open TCP/UDP sockets diff --git a/test/payload_tests/local_payload_test_huge_payload_starter.sh b/test/payload_tests/local_payload_test_huge_payload_starter.sh new file mode 100755 index 0000000..07cc372 --- /dev/null +++ b/test/payload_tests/local_payload_test_huge_payload_starter.sh @@ -0,0 +1,43 @@ +#!/bin/bash +# Copyright (C) 2015-2016 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +# Purpose: This script is needed to start the client and service with +# one command. This is necessary as ctest - which is used to run the +# tests - isn't able to start two binaries for one testcase. Therefore +# the testcase simply executes this script. This script then runs client +# and service and checks that both exit sucessfully. + +FAIL=0 + +# Start the service +export VSOMEIP_APPLICATION_NAME=local_payload_test_service +export VSOMEIP_CONFIGURATION=local_payload_test_service.json +./payload_test_service & +SERIVCE_PID=$! +sleep 1; + +# Start the client +export VSOMEIP_APPLICATION_NAME=local_payload_test_client +export VSOMEIP_CONFIGURATION=local_payload_test_client.json +./payload_test_client --number-of-messages 100 --max-payload-size 10485760 & +CLIENT_PID=$! + +# Wait until client and service are finished +for job in $(jobs -p) +do + # Fail gets incremented if either client or service exit + # with a non-zero exit code + wait $job || ((FAIL+=1)) +done + +# Check if client and server both exited 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/payload_tests/payload_test_client.cpp b/test/payload_tests/payload_test_client.cpp index 27759b7..11d4511 100644 --- a/test/payload_tests/payload_test_client.cpp +++ b/test/payload_tests/payload_test_client.cpp @@ -40,11 +40,11 @@ payload_test_client::payload_test_client( { } -void payload_test_client::init() +bool payload_test_client::init() { if (!app_->init()) { - VSOMEIP_ERROR << "Couldn't initialize application"; - EXPECT_TRUE(false); + ADD_FAILURE() << "Couldn't initialize application"; + return false; } app_->register_state_handler( @@ -61,6 +61,7 @@ void payload_test_client::init() std::bind(&payload_test_client::on_availability, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); + return true; } void payload_test_client::start() @@ -185,8 +186,8 @@ void payload_test_client::run() std::shared_ptr<vsomeip::payload> payload = vsomeip::runtime::get()->create_payload(); std::vector<vsomeip::byte_t> payload_data; - bool lastrun = false; - while (current_payload_size_ <= max_allowed_payload) + bool reached_peak = false; + for(;;) { payload_data.assign(current_payload_size_ , vsomeip_test::PAYLOAD_TEST_DATA); payload->set_data(payload_data); @@ -201,16 +202,19 @@ void payload_test_client::run() print_throughput(); // Increase array size for next iteration - current_payload_size_ *= 2; + if(!reached_peak) { + current_payload_size_ *= 2; + } else { + current_payload_size_ /= 2; + } - //special case to test the biggest payload possible as last test - // 16 Bytes are reserved for the SOME/IP header - if(current_payload_size_ > max_allowed_payload - 16 && !lastrun) + if(!reached_peak && current_payload_size_ > max_allowed_payload) { - current_payload_size_ = max_allowed_payload - 16; - lastrun = true; + current_payload_size_ = max_allowed_payload; + reached_peak = true; + } else if(reached_peak && current_payload_size_ <= 1) { + break; } - std::this_thread::sleep_for(std::chrono::milliseconds(500)); } blocked_ = false; @@ -229,13 +233,15 @@ std::uint32_t payload_test_client::get_max_allowed_payload() switch (max_payload_size) { case payloadsize::UDS: - payload = VSOMEIP_MAX_LOCAL_MESSAGE_SIZE; + // TODO + payload = 1024 * 32 - 16; break; case payloadsize::TCP: - payload = VSOMEIP_MAX_TCP_MESSAGE_SIZE; + // TODO + payload = 4095 - 16; break; case payloadsize::UDP: - payload = VSOMEIP_MAX_UDP_MESSAGE_SIZE; + payload = VSOMEIP_MAX_UDP_MESSAGE_SIZE - 16; break; case payloadsize::USER_SPECIFIED: payload = user_defined_max_payload; @@ -291,24 +297,25 @@ void payload_test_client::print_throughput() stop_watch::usec_t time_per_message = time_needed / number_of_sent_messages_; std::double_t calls_per_sec = number_of_sent_messages_ * (usec_per_sec / static_cast<double>(time_needed)); - std::double_t kbyte_per_sec = ((number_of_sent_messages_ + std::double_t mbyte_per_sec = ((number_of_sent_messages_ * current_payload_size_) - / (static_cast<double>(time_needed) / usec_per_sec)) / 1024; + / (static_cast<double>(time_needed) / usec_per_sec)) / (1024*1024); VSOMEIP_INFO<< "[ Payload Test ] : :" - << "Payload size [byte]: " << std::setw(8) << std::setfill('0') << current_payload_size_ - << " Messages sent: " << std::setw(8) << std::setfill('0') << number_of_sent_messages_ - << " Meantime/message [usec]: " << std::setw(8) << std::setfill('0') << time_per_message - << " Calls/sec: " << std::setw(8) << std::setfill('0') << calls_per_sec - << " KiB/sec: " << std::setw(8) << std::setfill('0') << kbyte_per_sec; + << "Payload size [byte]: " << std::dec << std::setw(8) << std::setfill('0') << current_payload_size_ + << " Messages sent: " << std::dec << std::setw(8) << std::setfill('0') << number_of_sent_messages_ + << " Meantime/message [usec]: " << std::dec << std::setw(8) << std::setfill('0') << time_per_message + << " Calls/sec: " << std::dec << std::setw(8) << std::setfill('0') << calls_per_sec + << " MiB/sec: " << std::dec << std::setw(8) << std::setfill('0') << mbyte_per_sec; } TEST(someip_payload_test, send_different_payloads) { payload_test_client test_client_(use_tcp, call_service_sync, sliding_window_size); - test_client_.init(); - test_client_.start(); - test_client_.join_sender_thread(); + if (test_client_.init()) { + test_client_.start(); + test_client_.join_sender_thread(); + } } diff --git a/test/payload_tests/payload_test_client.hpp b/test/payload_tests/payload_test_client.hpp index 8af352e..b9da542 100644 --- a/test/payload_tests/payload_test_client.hpp +++ b/test/payload_tests/payload_test_client.hpp @@ -24,7 +24,7 @@ class payload_test_client { public: payload_test_client(bool _use_tcp, bool _call_service_sync, std::uint32_t _sliding_window_size); - void init(); + bool init(); void start(); void stop(); void join_sender_thread(); diff --git a/test/payload_tests/payload_test_service.cpp b/test/payload_tests/payload_test_service.cpp index 74191da..05a9cb4 100644 --- a/test/payload_tests/payload_test_service.cpp +++ b/test/payload_tests/payload_test_service.cpp @@ -19,13 +19,13 @@ payload_test_service::payload_test_service(bool _use_tcp) : { } -void payload_test_service::init() +bool payload_test_service::init() { std::lock_guard<std::mutex> its_lock(mutex_); if (!app_->init()) { - VSOMEIP_ERROR << "Couldn't initialize application"; - EXPECT_TRUE(false); + 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, @@ -41,6 +41,7 @@ void payload_test_service::init() app_->register_state_handler( std::bind(&payload_test_service::on_state, this, std::placeholders::_1)); + return true; } void payload_test_service::start() @@ -101,25 +102,26 @@ void payload_test_service::on_message(const std::shared_ptr<vsomeip::message>& _ 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() << "]"; + << _request->get_session() << "] payload size [byte]:" + << std::dec << _request->get_payload()->get_length(); } - ASSERT_EQ(_request->get_service(), vsomeip_test::TEST_SERVICE_SERVICE_ID); - ASSERT_EQ(_request->get_method(), vsomeip_test::TEST_SERVICE_METHOD_ID); + ASSERT_EQ(vsomeip_test::TEST_SERVICE_SERVICE_ID, _request->get_service()); + ASSERT_EQ(vsomeip_test::TEST_SERVICE_METHOD_ID, _request->get_method()); // Check the protocol version this shall be set to 0x01 according to the spec. // TR_SOMEIP_00052 - ASSERT_EQ(_request->get_protocol_version(), 0x01); + ASSERT_EQ(0x01, _request->get_protocol_version()); // Check the message type this shall be 0xx (REQUEST) according to the spec. // TR_SOMEIP_00055 - ASSERT_EQ(_request->get_message_type(), vsomeip::message_type_e::MT_REQUEST); + ASSERT_EQ(vsomeip::message_type_e::MT_REQUEST, _request->get_message_type()); if (check_payload) { std::shared_ptr<vsomeip::payload> pl = _request->get_payload(); vsomeip::byte_t* pl_ptr = pl->get_data(); for (vsomeip::length_t i = 0; i < pl->get_length(); i++) { - ASSERT_EQ(*(pl_ptr+i), vsomeip_test::PAYLOAD_TEST_DATA); + ASSERT_EQ(vsomeip_test::PAYLOAD_TEST_DATA, *(pl_ptr+i)); } } @@ -150,9 +152,10 @@ void payload_test_service::run() TEST(someip_payload_test, send_response_for_every_request) { payload_test_service test_service(use_tcp); - test_service.init(); - test_service.start(); - test_service.join_offer_thread(); + if (test_service.init()) { + test_service.start(); + test_service.join_offer_thread(); + } } #ifndef WIN32 diff --git a/test/payload_tests/payload_test_service.hpp b/test/payload_tests/payload_test_service.hpp index 098543a..d109146 100644 --- a/test/payload_tests/payload_test_service.hpp +++ b/test/payload_tests/payload_test_service.hpp @@ -20,7 +20,7 @@ class payload_test_service { public: payload_test_service(bool _use_tcp); - void init(); + bool init(); void start(); void stop(); void offer(); diff --git a/test/readme.txt b/test/readme.txt index 9e127b4..6b191d5 100644 --- a/test/readme.txt +++ b/test/readme.txt @@ -278,13 +278,16 @@ All tests should be marked as "passed". Big payload tests ----------------- -This test tests the possibility to increase the maximum allowed payload size for -local and TCP messages via configuration file. +This test tests the possibility to sent messages with bigger payloads +for local and TCP communication. The test will send a messages with 600k payload from a client to a service. The service will reply with a response containing 600k payload as well. This is repeated 10 times. There is a version for local and for TCP communication available. +Additionally there are test versions available which sent up to 10MiB big +messages and a version which tests the limitiation of message sizes configurable +via json file. Automatic start from the build directory: diff --git a/test/routing_tests/external_local_routing_test_service.cpp b/test/routing_tests/external_local_routing_test_service.cpp index d92f958..cd92508 100644 --- a/test/routing_tests/external_local_routing_test_service.cpp +++ b/test/routing_tests/external_local_routing_test_service.cpp @@ -16,13 +16,13 @@ external_local_routing_test_service::external_local_routing_test_service(bool _u { } -void external_local_routing_test_service::init() +bool external_local_routing_test_service::init() { std::lock_guard<std::mutex> its_lock(mutex_); if (!app_->init()) { - VSOMEIP_ERROR << "Couldn't initialize application"; - EXPECT_TRUE(false); + 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, @@ -39,6 +39,7 @@ void external_local_routing_test_service::init() std::placeholders::_1)); VSOMEIP_INFO << "Static routing " << (use_static_routing_ ? "ON" : "OFF"); + return true; } void external_local_routing_test_service::start() @@ -169,9 +170,10 @@ TEST(someip_external_local_routing_test, receive_ten_messages_over_local_and_ext { bool use_static_routing = true; external_local_routing_test_service test_service(use_static_routing); - test_service.init(); - test_service.start(); - test_service.join_offer_thread(); + if (test_service.init()) { + test_service.start(); + test_service.join_offer_thread(); + } } #ifndef WIN32 diff --git a/test/routing_tests/external_local_routing_test_service.hpp b/test/routing_tests/external_local_routing_test_service.hpp index f1e73b9..e30a71c 100644 --- a/test/routing_tests/external_local_routing_test_service.hpp +++ b/test/routing_tests/external_local_routing_test_service.hpp @@ -20,7 +20,7 @@ class external_local_routing_test_service { public: external_local_routing_test_service(bool _use_static_routing); - void init(); + bool init(); void start(); void stop(); void offer(); diff --git a/test/routing_tests/external_local_routing_test_starter.sh b/test/routing_tests/external_local_routing_test_starter.sh index 36a85e6..f4ba129 100755 --- a/test/routing_tests/external_local_routing_test_starter.sh +++ b/test/routing_tests/external_local_routing_test_starter.sh @@ -76,7 +76,12 @@ kill -0 $CLIENT_PID &> /dev/null CLIENT_STILL_THERE=$? if [ $CLIENT_STILL_THERE -ne 0 ] then -cat <<End-of-message + if [ ! -z "$USE_LXC_TEST" ]; then + echo "starting external_local_routing_test_starter.sh on slave LXC" + ssh -tt -i $SANDBOX_ROOT_DIR/commonapi_main/lxc-config/.ssh/mgc_lxc/rsa_key_file.pub -o StrictHostKeyChecking=no root@$LXC_TEST_SLAVE_IP "bash -ci \"set -m; cd \\\$SANDBOX_ROOT_DIR/ctarget/vsomeip/test; ./external_local_routing_test_client_external_start.sh\"" & + echo "remote ssh job id: $!" + else + cat <<End-of-message ******************************************************************************* ******************************************************************************* ** Please now run: @@ -89,6 +94,7 @@ cat <<End-of-message ******************************************************************************* ******************************************************************************* End-of-message + fi fi # Wait until client and service are finished diff --git a/test/routing_tests/local_routing_test_client.cpp b/test/routing_tests/local_routing_test_client.cpp index f280eb2..a9acb44 100644 --- a/test/routing_tests/local_routing_test_client.cpp +++ b/test/routing_tests/local_routing_test_client.cpp @@ -18,11 +18,11 @@ local_routing_test_client::local_routing_test_client(bool _use_tcp) : { } -void local_routing_test_client::init() +bool local_routing_test_client::init() { if (!app_->init()) { - VSOMEIP_ERROR << "Couldn't initialize application"; - EXPECT_TRUE(false); + ADD_FAILURE() << "Couldn't initialize application"; + return false; } app_->register_state_handler( @@ -39,6 +39,7 @@ void local_routing_test_client::init() std::bind(&local_routing_test_client::on_availability, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); + return true; } void local_routing_test_client::start() @@ -152,9 +153,10 @@ TEST(someip_local_routing_test, send_ten_messages_to_service_and_receive_reply) { bool use_tcp = false; local_routing_test_client test_client_(use_tcp); - test_client_.init(); - test_client_.start(); - test_client_.join_sender_thread(); + if (test_client_.init()) { + test_client_.start(); + test_client_.join_sender_thread(); + } } #ifndef WIN32 diff --git a/test/routing_tests/local_routing_test_client.hpp b/test/routing_tests/local_routing_test_client.hpp index cb30667..2229ae6 100644 --- a/test/routing_tests/local_routing_test_client.hpp +++ b/test/routing_tests/local_routing_test_client.hpp @@ -21,7 +21,7 @@ class local_routing_test_client { public: local_routing_test_client(bool _use_tcp); - void init(); + bool init(); void start(); void stop(); void join_sender_thread(); diff --git a/test/routing_tests/local_routing_test_service.cpp b/test/routing_tests/local_routing_test_service.cpp index 3a61ddf..137e8ea 100644 --- a/test/routing_tests/local_routing_test_service.cpp +++ b/test/routing_tests/local_routing_test_service.cpp @@ -15,13 +15,13 @@ local_routing_test_service::local_routing_test_service(bool _use_static_routing) { } -void local_routing_test_service::init() +bool local_routing_test_service::init() { std::lock_guard<std::mutex> its_lock(mutex_); if (!app_->init()) { - VSOMEIP_ERROR << "Couldn't initialize application"; - EXPECT_TRUE(false); + 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, @@ -33,6 +33,7 @@ void local_routing_test_service::init() std::placeholders::_1)); VSOMEIP_INFO << "Static routing " << (use_static_routing_ ? "ON" : "OFF"); + return true; } void local_routing_test_service::start() @@ -148,9 +149,10 @@ TEST(someip_local_routing_test, receive_ten_messages_over_local_uds_socket) { bool use_static_routing = true; local_routing_test_service test_service(use_static_routing); - test_service.init(); - test_service.start(); - test_service.join_offer_thread(); + if (test_service.init()) { + test_service.start(); + test_service.join_offer_thread(); + } } #ifndef WIN32 diff --git a/test/routing_tests/local_routing_test_service.hpp b/test/routing_tests/local_routing_test_service.hpp index f78d5b0..3d575d7 100644 --- a/test/routing_tests/local_routing_test_service.hpp +++ b/test/routing_tests/local_routing_test_service.hpp @@ -20,7 +20,7 @@ class local_routing_test_service { public: local_routing_test_service(bool _use_static_routing); - void init(); + bool init(); void start(); void stop(); void offer(); diff --git a/test/subscribe_notify_one_tests/subscribe_notify_one_test_master_starter.sh b/test/subscribe_notify_one_tests/subscribe_notify_one_test_master_starter.sh index f85aa6c..995e66e 100755 --- a/test/subscribe_notify_one_tests/subscribe_notify_one_test_master_starter.sh +++ b/test/subscribe_notify_one_tests/subscribe_notify_one_test_master_starter.sh @@ -62,7 +62,12 @@ export VSOMEIP_CONFIGURATION=$2 sleep 1 -cat <<End-of-message +if [ ! -z "$USE_LXC_TEST" ]; then + echo "starting subscribe_notify_one_test_slave_starter.sh on slave LXC with parameters $1 $CLIENT_JSON_FILE" + ssh -tt -i $SANDBOX_ROOT_DIR/commonapi_main/lxc-config/.ssh/mgc_lxc/rsa_key_file.pub -o StrictHostKeyChecking=no root@$LXC_TEST_SLAVE_IP "bash -ci \"set -m; cd \\\$SANDBOX_ROOT_DIR/ctarget/vsomeip/test; ./subscribe_notify_one_test_slave_starter.sh $1 $CLIENT_JSON_FILE\"" & + echo "remote ssh job id: $!" +else + cat <<End-of-message ******************************************************************************* ******************************************************************************* ** Please now run: @@ -75,6 +80,7 @@ cat <<End-of-message ******************************************************************************* ******************************************************************************* End-of-message +fi # Wait until client and service are finished for job in $(jobs -p) diff --git a/test/subscribe_notify_one_tests/subscribe_notify_one_test_service.cpp b/test/subscribe_notify_one_tests/subscribe_notify_one_test_service.cpp index fd3c047..0727b8e 100644 --- a/test/subscribe_notify_one_tests/subscribe_notify_one_test_service.cpp +++ b/test/subscribe_notify_one_tests/subscribe_notify_one_test_service.cpp @@ -37,8 +37,8 @@ public: wait_for_notify_(true), notify_thread_(std::bind(&subscribe_notify_one_test_service::notify_one, this)) { if (!app_->init()) { - VSOMEIP_ERROR << "Couldn't initialize application"; - EXPECT_TRUE(false); + ADD_FAILURE() << "Couldn't initialize application"; + return; } app_->register_state_handler( std::bind(&subscribe_notify_one_test_service::on_state, this, @@ -78,6 +78,8 @@ public: std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); + app_->request_service(i.service_id, i.instance_id, vsomeip::DEFAULT_MAJOR, vsomeip::DEFAULT_MINOR, true); + std::set<vsomeip::eventgroup_t> its_eventgroups; its_eventgroups.insert(i.eventgroup_id); app_->request_event(i.service_id, i.instance_id, i.event_id, its_eventgroups, false); @@ -319,7 +321,7 @@ public: // successfully subscribed as we only receive once subscription per // remote node no matter how many clients subscribed to this eventgroup // on the remote node - std::this_thread::sleep_for(std::chrono::milliseconds(2000)); + std::this_thread::sleep_for(std::chrono::milliseconds(500)); VSOMEIP_INFO << "[" << std::setw(4) << std::setfill('0') << std::hex << service_info_.service_id << "] Starting to notify"; @@ -341,7 +343,7 @@ public: app_->notify_one(service_info_.service_id, service_info_.instance_id, service_info_.event_id, its_payload, client); } - std::this_thread::sleep_for(std::chrono::milliseconds(500)); + std::this_thread::sleep_for(std::chrono::milliseconds(50)); } } @@ -363,8 +365,17 @@ public: wait_until_notified_from_other_services_ = false; condition_.notify_one(); } - - std::this_thread::sleep_for(std::chrono::seconds(6)); + for(const auto& i : subscribe_notify_one_test::service_infos) { + if ((i.service_id == service_info_.service_id + && i.instance_id == service_info_.instance_id) + || (i.service_id == 0xFFFF && i.instance_id == 0xFFFF)) { + continue; + } + app_->unsubscribe(i.service_id, i.instance_id, i.eventgroup_id); + app_->release_event(i.service_id, i.instance_id, i.event_id); + app_->release_service(i.service_id, i.instance_id); + } + std::this_thread::sleep_for(std::chrono::seconds(1)); app_->clear_all_handler(); app_->stop(); } diff --git a/test/subscribe_notify_tests/subscribe_notify_test_master_starter.sh b/test/subscribe_notify_tests/subscribe_notify_test_master_starter.sh index bbb48ea..006d2bc 100755 --- a/test/subscribe_notify_tests/subscribe_notify_test_master_starter.sh +++ b/test/subscribe_notify_tests/subscribe_notify_test_master_starter.sh @@ -63,7 +63,12 @@ export VSOMEIP_CONFIGURATION=$2 sleep 1 -cat <<End-of-message +if [ ! -z "$USE_LXC_TEST" ]; then + echo "starting subscribe_notify_test_slave_starter.sh on slave LXC with parameters $1 $CLIENT_JSON_FILE $3" + ssh -tt -i $SANDBOX_ROOT_DIR/commonapi_main/lxc-config/.ssh/mgc_lxc/rsa_key_file.pub -o StrictHostKeyChecking=no root@$LXC_TEST_SLAVE_IP "bash -ci \"set -m; cd \\\$SANDBOX_ROOT_DIR/ctarget/vsomeip/test; ./subscribe_notify_test_slave_starter.sh $1 $CLIENT_JSON_FILE $3\"" & + echo "remote ssh job id: $!" +else + cat <<End-of-message ******************************************************************************* ******************************************************************************* ** Please now run: @@ -76,6 +81,7 @@ cat <<End-of-message ******************************************************************************* ******************************************************************************* End-of-message +fi # Wait until client and service are finished for job in $(jobs -p) diff --git a/test/subscribe_notify_tests/subscribe_notify_test_service.cpp b/test/subscribe_notify_tests/subscribe_notify_test_service.cpp index 9dd3bbb..bec20c6 100644 --- a/test/subscribe_notify_tests/subscribe_notify_test_service.cpp +++ b/test/subscribe_notify_tests/subscribe_notify_test_service.cpp @@ -38,8 +38,8 @@ public: wait_for_notify_(true), notify_thread_(std::bind(&subscribe_notify_test_service::notify, this)) { if (!app_->init()) { - VSOMEIP_ERROR << "Couldn't initialize application"; - EXPECT_TRUE(false); + ADD_FAILURE() << "Couldn't initialize application"; + return; } app_->register_state_handler( std::bind(&subscribe_notify_test_service::on_state, this, @@ -359,6 +359,16 @@ public: } std::this_thread::sleep_for(std::chrono::seconds(1)); + for(const auto& i : service_infos_) { + if ((i.service_id == service_info_.service_id + && i.instance_id == service_info_.instance_id) + || (i.service_id == 0xFFFF && i.instance_id == 0xFFFF)) { + continue; + } + app_->unsubscribe(i.service_id, i.instance_id, i.eventgroup_id); + app_->release_event(i.service_id, i.instance_id, i.event_id); + app_->release_service(i.service_id, i.instance_id); + } app_->clear_all_handler(); app_->stop(); } diff --git a/tools/vsomeip_ctrl.cpp b/tools/vsomeip_ctrl.cpp index 947caf8..362f1b4 100644 --- a/tools/vsomeip_ctrl.cpp +++ b/tools/vsomeip_ctrl.cpp @@ -61,7 +61,10 @@ public: validate_message(); - app_->init(); + if (!app_->init()) { + VSOMEIP_ERROR << "Couldn't initialize application"; + exit(EXIT_FAILURE); + } app_->register_state_handler( std::bind(&vsomeip_sender::on_state, this, std::placeholders::_1)); @@ -77,6 +80,8 @@ public: }; void stop(int _exit_code) { + app_->clear_all_handler(); + app_->release_service(service_id_, instance_); app_->stop(); exit(_exit_code); } |