diff options
author | Juergen Gehring <juergen.gehring@bmw.de> | 2017-06-19 08:03:41 -0700 |
---|---|---|
committer | Juergen Gehring <juergen.gehring@bmw.de> | 2017-06-19 08:03:41 -0700 |
commit | cf67875117ef7b1b9a25fe1f23e8b7ba1197c934 (patch) | |
tree | e6cb18195024eccf224ffd270a924aabf2768285 | |
parent | 5315798ff81796217b55eb8c622f154bb0a1c487 (diff) | |
download | vSomeIP-cf67875117ef7b1b9a25fe1f23e8b7ba1197c934.tar.gz |
vSomeIP 2.6.32.6.3
52 files changed, 1950 insertions, 155 deletions
@@ -14,6 +14,8 @@ /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/big_payload_tests/big_payload_test_tcp_client_limited_general.json +/test/big_payload_tests/big_payload_test_tcp_service_limited_general.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 @@ -296,3 +296,9 @@ v2.6.2 - Activate TCP-Keep-Alive for TCP endpoints - Debouncing of request-service messages (routing info performance) - Fixed false session-id handling of identification request + +v2.6.3 +- Improve reboot detection of other nodes +- Introduce 'max-payload-size-reliable' json file parameter which can be used to + globally limit the maximum allowed payload size for TCP communication +- Added CRC checksum calculation for bit optimized messages diff --git a/CMakeLists.txt b/CMakeLists.txt index a7e67bb..a4b84e7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,7 +8,7 @@ project (vsomeip) set (VSOMEIP_MAJOR_VERSION 2) set (VSOMEIP_MINOR_VERSION 6) -set (VSOMEIP_PATCH_VERSION 2) +set (VSOMEIP_PATCH_VERSION 3) 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) @@ -123,7 +123,13 @@ file(GLOB vsomeip_SRC "implementation/runtime/src/*.cpp" "implementation/utility/src/*.cpp" ) + +file(GLOB_RECURSE vsomeip_e2e_SRC + "implementation/e2e_protection/src/*.cpp" +) + list(SORT vsomeip_SRC) +list(SORT vsomeip_e2e_SRC) add_definitions(-DVSOMEIP_VERSION="${VSOMEIP_VERSION}") @@ -142,7 +148,7 @@ else() set(USE_RT "rt") endif() -add_library(vsomeip SHARED ${vsomeip_SRC}) +add_library(vsomeip SHARED ${vsomeip_SRC} ${vsomeip_e2e_SRC}) set_target_properties (vsomeip PROPERTIES VERSION ${VSOMEIP_VERSION} SOVERSION ${VSOMEIP_MAJOR_VERSION}) # PRIVATE means the listed libraries won't be included in the "link interface", # meaning the exported vsomeipTargets.cmake targets won't try to link against diff --git a/documentation/vsomeipUserGuide b/documentation/vsomeipUserGuide index b2c7d1d..19aa864 100644 --- a/documentation/vsomeipUserGuide +++ b/documentation/vsomeipUserGuide @@ -582,6 +582,12 @@ 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. +* `max-payload-size-reliable` ++ +The maximum allowed payload size for TCP communication in +bytes. By default the payload size for TCP 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 diff --git a/implementation/configuration/include/configuration.hpp b/implementation/configuration/include/configuration.hpp index 26ebf36..c8b7717 100644 --- a/implementation/configuration/include/configuration.hpp +++ b/implementation/configuration/include/configuration.hpp @@ -21,6 +21,9 @@ #include "internal.hpp" #include "trace.hpp" +#include "../../e2e_protection/include/e2exf/config.hpp" +#include "e2e.hpp" + namespace vsomeip { class event; @@ -77,7 +80,7 @@ public: virtual std::size_t get_request_debouncing(const std::string &_name) const = 0; virtual std::uint32_t get_max_message_size_local() const = 0; - virtual std::uint32_t get_message_size_reliable(const std::string& _address, + virtual std::uint32_t get_max_message_size_reliable(const std::string& _address, std::uint16_t _port) const = 0; virtual std::uint32_t get_buffer_shrink_threshold() const = 0; @@ -125,6 +128,10 @@ public: virtual bool is_offer_allowed(client_t _client, service_t _service, instance_t _instance) const = 0; virtual bool check_credentials(client_t _client, uint32_t _uid, uint32_t _gid) const = 0; + + //E2E + virtual std::map<e2exf::data_identifier, std::shared_ptr<cfg::e2e>> get_e2e_configuration() const = 0; + virtual bool is_e2e_enabled() const = 0; }; } // namespace vsomeip diff --git a/implementation/configuration/include/configuration_impl.hpp b/implementation/configuration/include/configuration_impl.hpp index 9f7c3c3..b345d9d 100644 --- a/implementation/configuration/include/configuration_impl.hpp +++ b/implementation/configuration/include/configuration_impl.hpp @@ -19,6 +19,8 @@ #include "watchdog.hpp" #include "service_instance_range.hpp" #include "policy.hpp" +#include "../../e2e_protection/include/e2exf/config.hpp" +#include "e2e.hpp" namespace vsomeip { namespace cfg { @@ -91,7 +93,7 @@ public: eventgroup_t _eventgroup) const; VSOMEIP_EXPORT std::uint32_t get_max_message_size_local() const; - VSOMEIP_EXPORT std::uint32_t get_message_size_reliable(const std::string& _address, + VSOMEIP_EXPORT std::uint32_t get_max_message_size_reliable(const std::string& _address, std::uint16_t _port) const; VSOMEIP_EXPORT std::uint32_t get_buffer_shrink_threshold() const; @@ -137,6 +139,10 @@ public: VSOMEIP_EXPORT bool is_offer_allowed(client_t _client, service_t _service, instance_t _instance) const; VSOMEIP_EXPORT bool check_credentials(client_t _client, uint32_t _uid, uint32_t _gid) const; + + //E2E + VSOMEIP_EXPORT std::map<e2exf::data_identifier, std::shared_ptr<cfg::e2e>> get_e2e_configuration() const; + VSOMEIP_EXPORT bool is_e2e_enabled() const; private: void read_data(const std::set<std::string> &_input, @@ -209,6 +215,9 @@ private: void set_mandatory(const std::string &_input); void trim(std::string &_s); + void load_e2e(const element &_element); + void load_e2e_protected(const boost::property_tree::ptree &_tree); + private: std::mutex mutex_; @@ -260,6 +269,7 @@ 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 max_reliable_message_size_; std::uint32_t buffer_shrink_threshold_; std::shared_ptr<trace> trace_; @@ -308,6 +318,9 @@ protected: std::map<client_t, std::shared_ptr<policy>> policies_; bool policy_enabled_; bool check_credentials_; + + bool e2e_enabled_; + std::map<e2exf::data_identifier, std::shared_ptr<cfg::e2e>> e2e_configuration_; }; } // namespace cfg diff --git a/implementation/configuration/include/e2e.hpp b/implementation/configuration/include/e2e.hpp new file mode 100644 index 0000000..305ef7a --- /dev/null +++ b/implementation/configuration/include/e2e.hpp @@ -0,0 +1,65 @@ +// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef CONFIGURATION_INCLUDE_E2E_HPP_ +#define CONFIGURATION_INCLUDE_E2E_HPP_ + +#include <string> +#include <vector> + +#include <vsomeip/primitive_types.hpp> + +namespace vsomeip { +namespace cfg { + + +struct e2e { + + e2e() : + data_id(0), + variant(""), + profile(""), + service_id(0), + event_id(0), + crc_offset(0), + data_id_mode(0), + data_length(0) { + } + + + e2e(uint16_t _data_id, std::string _variant, std::string _profile, uint16_t _service_id, + uint16_t _event_id,uint16_t _crc_offset, + uint8_t _data_id_mode, uint16_t _data_length) : + + data_id(_data_id), + variant(_variant), + profile(_profile), + service_id(_service_id), + event_id(_event_id), + crc_offset(_crc_offset), + data_id_mode(_data_id_mode), + data_length(_data_length) { + + } + + // common config + uint16_t data_id; + std::string variant; + std::string profile; + uint16_t service_id; + uint16_t event_id; + + //profile 1 specific config + // [SWS_E2E_00018] + uint16_t crc_offset; + uint8_t data_id_mode; + uint16_t data_length; +}; + + + +} +} +#endif /* CONFIGURATION_INCLUDE_E2E_HPP_ */ diff --git a/implementation/configuration/src/configuration_impl.cpp b/implementation/configuration/src/configuration_impl.cpp index 7375bdb..dc13103 100644 --- a/implementation/configuration/src/configuration_impl.cpp +++ b/implementation/configuration/src/configuration_impl.cpp @@ -60,6 +60,7 @@ configuration_impl::configuration_impl() sd_offer_debounce_time_(VSOMEIP_SD_DEFAULT_OFFER_DEBOUNCE_TIME), max_configured_message_size_(0), max_local_message_size_(0), + max_reliable_message_size_(0), buffer_shrink_threshold_(0), trace_(std::make_shared<trace>()), watchdog_(std::make_shared<watchdog>()), @@ -68,7 +69,8 @@ configuration_impl::configuration_impl() permissions_shm_(VSOMEIP_DEFAULT_SHM_PERMISSION), umask_(VSOMEIP_DEFAULT_UMASK_LOCAL_ENDPOINTS), policy_enabled_(false), - check_credentials_(false) { + check_credentials_(false), + e2e_enabled_(false) { unicast_ = unicast_.from_string(VSOMEIP_UNICAST_ADDRESS); for (auto i = 0; i < ET_MAX; i++) is_configured_[i] = false; @@ -81,6 +83,7 @@ configuration_impl::configuration_impl(const configuration_impl &_other) mandatory_(_other.mandatory_), max_configured_message_size_(_other.max_configured_message_size_), max_local_message_size_(_other.max_local_message_size_), + max_reliable_message_size_(_other.max_reliable_message_size_), buffer_shrink_threshold_(_other.buffer_shrink_threshold_), permissions_shm_(VSOMEIP_DEFAULT_SHM_PERMISSION), umask_(VSOMEIP_DEFAULT_UMASK_LOCAL_ENDPOINTS) { @@ -126,6 +129,7 @@ configuration_impl::configuration_impl(const configuration_impl &_other) policy_enabled_ = _other.policy_enabled_; check_credentials_ = _other.check_credentials_; + e2e_enabled_ = _other.e2e_enabled_; } configuration_impl::~configuration_impl() { @@ -315,6 +319,7 @@ bool configuration_impl::load_data(const std::vector<element> &_elements, load_clients(e); load_watchdog(e); load_selective_broadcasts_support(e); + load_e2e(e); } } @@ -1290,6 +1295,7 @@ 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"); + const std::string max_reliable_payload_size("max-payload-size-reliable"); try { if (_element.tree_.get_child_optional(max_local_payload_size)) { auto mpsl = _element.tree_.get_child(max_local_payload_size); @@ -1303,6 +1309,18 @@ void configuration_impl::load_payload_sizes(const element &_element) { << " " << e.what(); } } + if (_element.tree_.get_child_optional(max_reliable_payload_size)) { + auto mpsl = _element.tree_.get_child(max_reliable_payload_size); + std::string s(mpsl.data()); + try { + // add 16 Byte for the SOME/IP header + max_reliable_message_size_ = static_cast<std::uint32_t>(std::stoul( + s.c_str(), NULL, 10) + 16); + } catch (const std::exception &e) { + VSOMEIP_ERROR<< __func__ << ": " << max_reliable_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()); @@ -1369,6 +1387,19 @@ void configuration_impl::load_payload_sizes(const element &_element) { << max_local_payload_size << " will be increased to " << max_configured_message_size_ - 16 << " to ensure " << "local message distribution."; + max_local_message_size_ = max_configured_message_size_; + } + if (max_local_message_size_ != 0 + && max_reliable_message_size_ != 0 + && max_reliable_message_size_ > max_local_message_size_) { + VSOMEIP_WARNING << max_local_payload_size << " (" + << max_local_message_size_ - 16 << ") is configured" + << " smaller than " << max_reliable_payload_size << " (" + << max_reliable_message_size_ - 16 << "). " + << max_local_payload_size << " will be increased to " + << max_reliable_message_size_ - 16 << " to ensure " + << "local message distribution."; + max_local_message_size_ = max_reliable_message_size_; } } } catch (...) { @@ -2018,18 +2049,18 @@ std::uint32_t configuration_impl::get_max_message_size_local() const { + sizeof(bool) + sizeof(bool) + sizeof(client_t)); } -std::uint32_t configuration_impl::get_message_size_reliable( +std::uint32_t configuration_impl::get_max_message_size_reliable( const std::string& _address, std::uint16_t _port) const { - auto its_address = message_sizes_.find(_address); + const auto its_address = message_sizes_.find(_address); if(its_address != message_sizes_.end()) { - auto its_port = its_address->second.find(_port); + const auto its_port = its_address->second.find(_port); if(its_port != its_address->second.end()) { return its_port->second; } } - return (VSOMEIP_MAX_TCP_MESSAGE_SIZE == 0) ? - MESSAGE_SIZE_UNLIMITED : - VSOMEIP_MAX_TCP_MESSAGE_SIZE; + return (max_reliable_message_size_ == 0) ? + ((VSOMEIP_MAX_TCP_MESSAGE_SIZE == 0) ? MESSAGE_SIZE_UNLIMITED : + VSOMEIP_MAX_TCP_MESSAGE_SIZE) : max_reliable_message_size_; } std::uint32_t configuration_impl::get_buffer_shrink_threshold() const { @@ -2212,5 +2243,116 @@ bool configuration_impl::is_offer_allowed(client_t _client, service_t _service, return !check_credentials_; } +bool configuration_impl::is_e2e_enabled() const { + return e2e_enabled_; +} + +void configuration_impl::load_e2e(const element &_element) { +#ifdef _WIN32 + return; +#endif + try { + auto optional = _element.tree_.get_child_optional("e2e"); + if (!optional) { + return; + } + auto found_e2e = _element.tree_.get_child("e2e"); + for (auto its_e2e = found_e2e.begin(); + its_e2e != found_e2e.end(); ++its_e2e) { + if (its_e2e->first == "e2e_enabled") { + if (its_e2e->second.data() == "true") { + e2e_enabled_ = true; + } + } + if (its_e2e->first == "protected") { + for (auto its_protected = its_e2e->second.begin(); + its_protected != its_e2e->second.end(); ++its_protected) { + load_e2e_protected(its_protected->second); + } + } + } + } catch (...) { + } +} + +void configuration_impl::load_e2e_protected(const boost::property_tree::ptree &_tree) { + + uint16_t data_id(0); + std::string variant(""); + std::string profile(""); + uint16_t service_id(0); + uint16_t event_id(0); + + uint16_t crc_offset(0); + uint8_t data_id_mode(0); + uint16_t data_length(0); + + for (auto l = _tree.begin(); l != _tree.end(); ++l) { + std::stringstream its_converter; + uint16_t tmp; + if (l->first == "data_id" && data_id == 0) { + std::string value = l->second.data(); + if (value.size() > 1 && value[0] == '0' && value[1] == 'x') { + its_converter << std::hex << value; + } else { + its_converter << std::dec << value; + } + its_converter >> data_id; + } else if (l->first == "service_id") { + std::string value = l->second.data(); + if (value.size() > 1 && value[0] == '0' && value[1] == 'x') { + its_converter << std::hex << value; + } else { + its_converter << std::dec << value; + } + its_converter >> service_id; + } else if (l->first == "event_id") { + std::string value = l->second.data(); + if (value.size() > 1 && value[0] == '0' && value[1] == 'x') { + its_converter << std::hex << value; + } else { + its_converter << std::dec << value; + } + its_converter >> event_id; + } else if (l->first == "variant") { + std::string value = l->second.data(); + its_converter << value; + its_converter >> variant; + } else if (l->first == "profile") { + std::string value = l->second.data(); + its_converter << value; + its_converter >> profile; + } else if (l->first == "crc_offset") { + std::string value = l->second.data(); + its_converter << value; + its_converter >> crc_offset; + } else if (l->first == "data_id_mode") { + std::string value = l->second.data(); + its_converter << value; + its_converter >> tmp; + data_id_mode = static_cast<uint8_t>(tmp); + } else if (l->first == "data_length") { + std::string value = l->second.data(); + its_converter << value; + its_converter >> data_length; + } + } + e2exf::data_identifier its_data_identifier = {service_id, event_id}; + e2e_configuration_[its_data_identifier] = std::make_shared<cfg::e2e>( + data_id, + variant, + profile, + service_id, + event_id, + crc_offset, + data_id_mode, + data_length + ); +} + +std::map<e2exf::data_identifier, std::shared_ptr<cfg::e2e>> configuration_impl::get_e2e_configuration() const { + return e2e_configuration_; +} + } // namespace config } // namespace vsomeip diff --git a/implementation/e2e_protection/include/buffer/buffer.hpp b/implementation/e2e_protection/include/buffer/buffer.hpp new file mode 100644 index 0000000..b92d409 --- /dev/null +++ b/implementation/e2e_protection/include/buffer/buffer.hpp @@ -0,0 +1,47 @@ +// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef BUFFER_BUFFER_HPP +#define BUFFER_BUFFER_HPP + +#include <stdexcept> +#include <cstdint> +#include <ostream> +#include <vector> + +namespace buffer { + +using e2e_buffer = std::vector<uint8_t>; + +class buffer_view { + public: + buffer_view(const uint8_t *_data_ptr, size_t _data_length) : data_ptr(_data_ptr), data_length(_data_length) { + + } + + buffer_view(const buffer::e2e_buffer &_buffer) : data_ptr(_buffer.data()), data_length(_buffer.size()) {} + + buffer_view(const buffer::e2e_buffer &_buffer, size_t _length) : data_ptr(_buffer.data()), data_length(_length) { + + } + + buffer_view(const buffer::e2e_buffer &_buffer, size_t _begin, size_t _end) + : data_ptr(_buffer.data() + _begin), data_length(_end - _begin) { + + } + + const uint8_t *begin(void) const { return data_ptr; } + + const uint8_t *end(void) const { return data_ptr + data_length; } + +private: + const uint8_t *data_ptr; + size_t data_length; +}; +} + +std::ostream &operator<<(std::ostream &_os, const buffer::e2e_buffer &_buffer); + +#endif diff --git a/implementation/e2e_protection/include/crc/crc.hpp b/implementation/e2e_protection/include/crc/crc.hpp new file mode 100644 index 0000000..8e393ea --- /dev/null +++ b/implementation/e2e_protection/include/crc/crc.hpp @@ -0,0 +1,30 @@ +// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef CRC_CRC_HPP +#define CRC_CRC_HPP + +#include <cstdint> +#include "../buffer/buffer.hpp" + +namespace crc { +class e2e_crc { + public: + static uint8_t calculate_profile_01(buffer::buffer_view _buffer_view, + const uint8_t _start_value = 0x00U); + static uint32_t calculate_profile_04(buffer::buffer_view _buffer_view, + const uint32_t _start_value = 0x00000000U); + + static uint32_t calculate_profile_custom(buffer::buffer_view _buffer_view); + + private: + static const uint8_t lookup_table_profile_01[256]; + static const uint32_t lookup_table_profile_04[256]; + static const uint32_t lookup_table_profile_custom[256]; + +}; +} + +#endif diff --git a/implementation/e2e_protection/include/e2e/profile/profile01/checker.hpp b/implementation/e2e_protection/include/e2e/profile/profile01/checker.hpp new file mode 100644 index 0000000..bc97f0d --- /dev/null +++ b/implementation/e2e_protection/include/e2e/profile/profile01/checker.hpp @@ -0,0 +1,37 @@ +// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef E2E_PROFILE_PROFILE01_CHECKER_HPP +#define E2E_PROFILE_PROFILE01_CHECKER_HPP + +#include "../profile01/profile_01.hpp" +#include "../profile_interface/checker.hpp" + +namespace e2e { +namespace profile { +namespace profile01 { + +class profile_01_checker final : public e2e::profile::profile_interface::checker { + + public: + profile_01_checker(void) = delete; + + // [SWS_E2E_00389] initialize state + explicit profile_01_checker(const Config &_config) : + config(_config) {} + + virtual void check(const buffer::e2e_buffer &_buffer, + e2e::profile::profile_interface::generic_check_status &_generic_check_status) override final; + +private: + Config config; + std::mutex check_mutex; + +}; +} +} +} + +#endif diff --git a/implementation/e2e_protection/include/e2e/profile/profile01/profile_01.hpp b/implementation/e2e_protection/include/e2e/profile/profile01/profile_01.hpp new file mode 100644 index 0000000..4574ca3 --- /dev/null +++ b/implementation/e2e_protection/include/e2e/profile/profile01/profile_01.hpp @@ -0,0 +1,52 @@ +// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef E2E_PROFILE_PROFILE01_PROFILE01_HPP +#define E2E_PROFILE_PROFILE01_PROFILE01_HPP + +#include <cstdint> +#include "../../../buffer/buffer.hpp" + +namespace e2e { +namespace profile { +namespace profile01 { + +struct Config; + +class profile_01 { + public: + static uint8_t compute_crc(const Config &_config, const buffer::e2e_buffer &_buffer); + + static bool is_buffer_length_valid(const Config &_config, const buffer::e2e_buffer &_buffer); +}; + +// [SWS_E2E_00200] +enum class p01_data_id_mode : uint8_t { E2E_P01_DATAID_BOTH, E2E_P01_DATAID_ALT, E2E_P01_DATAID_LOW, E2E_P01_DATAID_NIBBLE}; + +struct Config { + // [SWS_E2E_00018] + uint16_t crc_offset; + uint16_t data_id; + p01_data_id_mode data_id_mode; + uint16_t data_length; + +#ifndef E2E_DEVELOPMENT + Config() = delete; +#else + Config() = default; +#endif + Config(uint16_t _crc_offset, uint16_t _data_id, p01_data_id_mode _data_id_mode, uint16_t _data_length) + + : crc_offset(_crc_offset), data_id(_data_id), + data_id_mode(_data_id_mode), data_length(_data_length) { + } + Config(const Config &_config) = default; + Config &operator=(const Config &_config) = default; +}; +} +} +} + +#endif diff --git a/implementation/e2e_protection/include/e2e/profile/profile01/protector.hpp b/implementation/e2e_protection/include/e2e/profile/profile01/protector.hpp new file mode 100644 index 0000000..7c10f25 --- /dev/null +++ b/implementation/e2e_protection/include/e2e/profile/profile01/protector.hpp @@ -0,0 +1,36 @@ +// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef E2E_PROFILE_PROFILE01_PROTECTOR_HPP +#define E2E_PROFILE_PROFILE01_PROTECTOR_HPP + +#include <mutex> +#include "../profile01/profile_01.hpp" +#include "../profile_interface/protector.hpp" + +namespace e2e { +namespace profile { +namespace profile01 { + +class protector final : public e2e::profile::profile_interface::protector { + public: + protector(void) = delete; + + explicit protector(const Config &_config) : config(_config){}; + + void protect(buffer::e2e_buffer &_buffer) override final; + + private: + + void write_crc(buffer::e2e_buffer &_buffer, uint8_t _computed_crc); + + private: + Config config; + std::mutex protect_mutex; +}; +} +} +} +#endif diff --git a/implementation/e2e_protection/include/e2e/profile/profile_custom/checker.hpp b/implementation/e2e_protection/include/e2e/profile/profile_custom/checker.hpp new file mode 100644 index 0000000..00ea47c --- /dev/null +++ b/implementation/e2e_protection/include/e2e/profile/profile_custom/checker.hpp @@ -0,0 +1,40 @@ +// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef E2E_PROFILE_PROFILE_CUSTOM_CHECKER_HPP +#define E2E_PROFILE_PROFILE_CUSTOM_CHECKER_HPP + +#include "../profile_custom/profile_custom.hpp" +#include "../profile_interface/checker.hpp" +#include <mutex> + +namespace e2e { +namespace profile { +namespace profile_custom { + +class profile_custom_checker final : public e2e::profile::profile_interface::checker { + + public: + profile_custom_checker(void) = delete; + + explicit profile_custom_checker(const Config &_config) : + config(_config) {} + + virtual void check(const buffer::e2e_buffer &_buffer, + e2e::profile::profile_interface::generic_check_status &_generic_check_status); + + private: + uint32_t read_crc(const buffer::e2e_buffer &_buffer) const; + +private: + Config config; + std::mutex check_mutex; + +}; +} +} +} + +#endif diff --git a/implementation/e2e_protection/include/e2e/profile/profile_custom/profile_custom.hpp b/implementation/e2e_protection/include/e2e/profile/profile_custom/profile_custom.hpp new file mode 100644 index 0000000..da0e57f --- /dev/null +++ b/implementation/e2e_protection/include/e2e/profile/profile_custom/profile_custom.hpp @@ -0,0 +1,44 @@ +// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef E2E_PROFILE_PROFILE_CUSTOM_PROFILE_CUSTOM_HPP +#define E2E_PROFILE_PROFILE_CUSTOM_PROFILE_CUSTOM_HPP + +#include <cstdint> +#include "../../../buffer/buffer.hpp" + +namespace e2e { +namespace profile { +namespace profile_custom { + +struct Config; + +class profile_custom { + public: + static uint32_t compute_crc(const Config &_config, const buffer::e2e_buffer &_buffer); + + static bool is_buffer_length_valid(const Config &_config, const buffer::e2e_buffer &_buffer); +}; + +struct Config { + uint16_t crc_offset; + +#ifndef E2E_DEVELOPMENT + Config() = delete; +#else + Config() = default; +#endif + Config(uint16_t _crc_offset) + + : crc_offset(_crc_offset) { + } + Config(const Config &_config) = default; + Config &operator=(const Config &_config) = default; +}; +} +} +} + +#endif diff --git a/implementation/e2e_protection/include/e2e/profile/profile_custom/protector.hpp b/implementation/e2e_protection/include/e2e/profile/profile_custom/protector.hpp new file mode 100644 index 0000000..40307c4 --- /dev/null +++ b/implementation/e2e_protection/include/e2e/profile/profile_custom/protector.hpp @@ -0,0 +1,36 @@ +// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef E2E_PROFILE_PROFILE_CUSTOM_PROTECTOR_HPP +#define E2E_PROFILE_PROFILE_CUSTOM_PROTECTOR_HPP + +#include <mutex> +#include "../profile_custom/profile_custom.hpp" +#include "../profile_interface/protector.hpp" + +namespace e2e { +namespace profile { +namespace profile_custom { + +class protector final : public e2e::profile::profile_interface::protector { + public: + protector(void) = delete; + + explicit protector(const Config &_config) : config(_config){}; + + void protect(buffer::e2e_buffer &_buffer) override final; + + private: + + void write_crc(buffer::e2e_buffer &_buffer, uint32_t _computed_crc); + + private: + Config config; + std::mutex protect_mutex; +}; +} +} +} +#endif diff --git a/implementation/e2e_protection/include/e2e/profile/profile_interface/checker.hpp b/implementation/e2e_protection/include/e2e/profile/profile_interface/checker.hpp new file mode 100644 index 0000000..ed102a5 --- /dev/null +++ b/implementation/e2e_protection/include/e2e/profile/profile_interface/checker.hpp @@ -0,0 +1,28 @@ +// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + + +#ifndef E2E_PROFILE_INTERFACE_CHECKER_HPP +#define E2E_PROFILE_INTERFACE_CHECKER_HPP + +#include "../profile_interface/profile_interface.hpp" +#include "../../../buffer/buffer.hpp" +#include <mutex> + + +namespace e2e { +namespace profile { +namespace profile_interface { + +class checker : public profile_interface { + public: + virtual void check(const buffer::e2e_buffer &_buffer, + e2e::profile::profile_interface::generic_check_status &_generic_check_status) = 0; +}; +} +} +} + +#endif diff --git a/implementation/e2e_protection/include/e2e/profile/profile_interface/profile_interface.hpp b/implementation/e2e_protection/include/e2e/profile/profile_interface/profile_interface.hpp new file mode 100644 index 0000000..996a86d --- /dev/null +++ b/implementation/e2e_protection/include/e2e/profile/profile_interface/profile_interface.hpp @@ -0,0 +1,24 @@ +// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + + +#ifndef E2E_PROFILE_INTERFACE_INTERFACE_HPP +#define E2E_PROFILE_INTERFACE_INTERFACE_HPP + +#include <cstdint> + +namespace e2e { +namespace profile { +namespace profile_interface { + +enum class generic_check_status : uint8_t { E2E_OK, E2E_WRONG_CRC, E2E_ERROR}; + +class profile_interface { + +}; +} +} +} +#endif diff --git a/implementation/e2e_protection/include/e2e/profile/profile_interface/protector.hpp b/implementation/e2e_protection/include/e2e/profile/profile_interface/protector.hpp new file mode 100644 index 0000000..a904585 --- /dev/null +++ b/implementation/e2e_protection/include/e2e/profile/profile_interface/protector.hpp @@ -0,0 +1,24 @@ +// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef E2E_PROFILE_INTERFACE_PROTECTOR_HPP +#define E2E_PROFILE_INTERFACE_PROTECTOR_HPP + +#include "../../../buffer/buffer.hpp" +#include "../profile_interface/profile_interface.hpp" + +namespace e2e { +namespace profile { +namespace profile_interface { + +class protector : public profile_interface { + public: + virtual void protect(buffer::e2e_buffer &_buffer) = 0; +}; +} +} +} + +#endif diff --git a/implementation/e2e_protection/include/e2exf/config.hpp b/implementation/e2e_protection/include/e2exf/config.hpp new file mode 100644 index 0000000..4945a7b --- /dev/null +++ b/implementation/e2e_protection/include/e2exf/config.hpp @@ -0,0 +1,26 @@ +// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef E2EXF_CONFIG_HPP +#define E2EXF_CONFIG_HPP + +#include "../e2e/profile/profile_interface/checker.hpp" +#include "../e2e/profile/profile_interface/protector.hpp" + +#include <memory> +#include <map> + +namespace e2exf { + +using session_id = uint16_t; +using instance_id = uint16_t; + +using data_identifier = std::pair<session_id, instance_id>; + +} + +std::ostream &operator<<(std::ostream &_os, const e2exf::data_identifier &_data_identifier); + +#endif diff --git a/implementation/e2e_protection/src/buffer/buffer.cpp b/implementation/e2e_protection/src/buffer/buffer.cpp new file mode 100644 index 0000000..ad7cf69 --- /dev/null +++ b/implementation/e2e_protection/src/buffer/buffer.cpp @@ -0,0 +1,18 @@ +// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#include "../../../e2e_protection/include/buffer/buffer.hpp" +#include <iomanip> + +std::ostream &operator<<(std::ostream &_os, const buffer::e2e_buffer &_buffer) { + for (auto b : _buffer) { + if (isupper(b)) { + _os << b; + } else { + _os << "[" << std::setfill('0') << std::setw(2) << std::hex << (uint32_t)b << std::dec << "]"; + } + } + return _os; +} diff --git a/implementation/e2e_protection/src/crc/crc.cpp b/implementation/e2e_protection/src/crc/crc.cpp new file mode 100644 index 0000000..a3e6758 --- /dev/null +++ b/implementation/e2e_protection/src/crc/crc.cpp @@ -0,0 +1,186 @@ +// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#include "../../include/crc/crc.hpp" +#include <iostream> +#include <string> +#include <iomanip> + +namespace crc { + +/** + * Calculates the crc over the provided range. + * + * @param begin Constant iterator pointing to begin of the range. + * @param end Constant iterator pointing to end of the range. + * @param startValue The crc value from previous call. + * @return The calculated crc value. + * + * Parameters of the CRC: + * - Width = 8 + * - Poly = 0x1D + * - XorIn = 0xFF + * - ReflectIn = false + * - XorOut = 0xFF + * - ReflectOut = false + * - Algorithm = table-driven + */ +uint8_t e2e_crc::calculate_profile_01(buffer::buffer_view _buffer_view, const uint8_t _start_value) { + uint8_t crc = _start_value ^ 0xFFU; + for (uint8_t byte : _buffer_view) { + crc = static_cast<uint8_t>(lookup_table_profile_01[static_cast<uint8_t>((byte) ^ crc)] ^ (crc >> 8U)); + } + crc = crc ^ 0xFFU; + return crc; +} + +const uint8_t e2e_crc::lookup_table_profile_01[256] = { + 0x00U, 0x1DU, 0x3AU, 0x27U, 0x74U, 0x69U, 0x4EU, 0x53U, 0xE8U, 0xF5U, 0xD2U, 0xCFU, 0x9CU, 0x81U, 0xA6U, 0xBBU, + 0xCDU, 0xD0U, 0xF7U, 0xEAU, 0xB9U, 0xA4U, 0x83U, 0x9EU, 0x25U, 0x38U, 0x1FU, 0x02U, 0x51U, 0x4CU, 0x6BU, 0x76U, + 0x87U, 0x9AU, 0xBDU, 0xA0U, 0xF3U, 0xEEU, 0xC9U, 0xD4U, 0x6FU, 0x72U, 0x55U, 0x48U, 0x1BU, 0x06U, 0x21U, 0x3CU, + 0x4AU, 0x57U, 0x70U, 0x6DU, 0x3EU, 0x23U, 0x04U, 0x19U, 0xA2U, 0xBFU, 0x98U, 0x85U, 0xD6U, 0xCBU, 0xECU, 0xF1U, + 0x13U, 0x0EU, 0x29U, 0x34U, 0x67U, 0x7AU, 0x5DU, 0x40U, 0xFBU, 0xE6U, 0xC1U, 0xDCU, 0x8FU, 0x92U, 0xB5U, 0xA8U, + 0xDEU, 0xC3U, 0xE4U, 0xF9U, 0xAAU, 0xB7U, 0x90U, 0x8DU, 0x36U, 0x2BU, 0x0CU, 0x11U, 0x42U, 0x5FU, 0x78U, 0x65U, + 0x94U, 0x89U, 0xAEU, 0xB3U, 0xE0U, 0xFDU, 0xDAU, 0xC7U, 0x7CU, 0x61U, 0x46U, 0x5BU, 0x08U, 0x15U, 0x32U, 0x2FU, + 0x59U, 0x44U, 0x63U, 0x7EU, 0x2DU, 0x30U, 0x17U, 0x0AU, 0xB1U, 0xACU, 0x8BU, 0x96U, 0xC5U, 0xD8U, 0xFFU, 0xE2U, + 0x26U, 0x3BU, 0x1CU, 0x01U, 0x52U, 0x4FU, 0x68U, 0x75U, 0xCEU, 0xD3U, 0xF4U, 0xE9U, 0xBAU, 0xA7U, 0x80U, 0x9DU, + 0xEBU, 0xF6U, 0xD1U, 0xCCU, 0x9FU, 0x82U, 0xA5U, 0xB8U, 0x03U, 0x1EU, 0x39U, 0x24U, 0x77U, 0x6AU, 0x4DU, 0x50U, + 0xA1U, 0xBCU, 0x9BU, 0x86U, 0xD5U, 0xC8U, 0xEFU, 0xF2U, 0x49U, 0x54U, 0x73U, 0x6EU, 0x3DU, 0x20U, 0x07U, 0x1AU, + 0x6CU, 0x71U, 0x56U, 0x4BU, 0x18U, 0x05U, 0x22U, 0x3FU, 0x84U, 0x99U, 0xBEU, 0xA3U, 0xF0U, 0xEDU, 0xCAU, 0xD7U, + 0x35U, 0x28U, 0x0FU, 0x12U, 0x41U, 0x5CU, 0x7BU, 0x66U, 0xDDU, 0xC0U, 0xE7U, 0xFAU, 0xA9U, 0xB4U, 0x93U, 0x8EU, + 0xF8U, 0xE5U, 0xC2U, 0xDFU, 0x8CU, 0x91U, 0xB6U, 0xABU, 0x10U, 0x0DU, 0x2AU, 0x37U, 0x64U, 0x79U, 0x5EU, 0x43U, + 0xB2U, 0xAFU, 0x88U, 0x95U, 0xC6U, 0xDBU, 0xFCU, 0xE1U, 0x5AU, 0x47U, 0x60U, 0x7DU, 0x2EU, 0x33U, 0x14U, 0x09U, + 0x7FU, 0x62U, 0x45U, 0x58U, 0x0BU, 0x16U, 0x31U, 0x2CU, 0x97U, 0x8AU, 0xADU, 0xB0U, 0xE3U, 0xFEU, 0xD9U, 0xC4U +}; + +/** +* Calculates the CRC over the provided range. +* +* @param begin Constant iterator pointing to begin of the range. +* @param end Constant iterator pointing to end of the range. +* @param startValue The CRC value from previous call. +* @return The calculated CRC value. +* +* Parameters of the CRC: +* - Width = 32 +* - Poly = 0xF4ACFB13 +* - XorIn = 0xFFFFFFFF +* - ReflectIn = true +* - XorOut = 0xFFFFFFFF +* - ReflectOut = true +*/ +uint32_t e2e_crc::calculate_profile_04(buffer::buffer_view _buffer_view, const uint32_t _start_value) { + uint32_t crc = _start_value ^ 0xFFFFFFFFU; + for (uint8_t byte : _buffer_view) { + crc = lookup_table_profile_04[static_cast<uint8_t>(byte ^ crc)] ^ (crc >> 8U); + } + + crc = crc ^ 0xFFFFFFFFU; + + return crc; +} + +const uint32_t e2e_crc::lookup_table_profile_04[256] = { + 0x00000000U, 0x30850FF5U, 0x610A1FEAU, 0x518F101FU, 0xC2143FD4U, 0xF2913021U, 0xA31E203EU, 0x939B2FCBU, 0x159615F7U, + 0x25131A02U, 0x749C0A1DU, 0x441905E8U, 0xD7822A23U, 0xE70725D6U, 0xB68835C9U, 0x860D3A3CU, 0x2B2C2BEEU, 0x1BA9241BU, + 0x4A263404U, 0x7AA33BF1U, 0xE938143AU, 0xD9BD1BCFU, 0x88320BD0U, 0xB8B70425U, 0x3EBA3E19U, 0x0E3F31ECU, 0x5FB021F3U, + 0x6F352E06U, 0xFCAE01CDU, 0xCC2B0E38U, 0x9DA41E27U, 0xAD2111D2U, 0x565857DCU, 0x66DD5829U, 0x37524836U, 0x07D747C3U, + 0x944C6808U, 0xA4C967FDU, 0xF54677E2U, 0xC5C37817U, 0x43CE422BU, 0x734B4DDEU, 0x22C45DC1U, 0x12415234U, 0x81DA7DFFU, + 0xB15F720AU, 0xE0D06215U, 0xD0556DE0U, 0x7D747C32U, 0x4DF173C7U, 0x1C7E63D8U, 0x2CFB6C2DU, 0xBF6043E6U, 0x8FE54C13U, + 0xDE6A5C0CU, 0xEEEF53F9U, 0x68E269C5U, 0x58676630U, 0x09E8762FU, 0x396D79DAU, 0xAAF65611U, 0x9A7359E4U, 0xCBFC49FBU, + 0xFB79460EU, 0xACB0AFB8U, 0x9C35A04DU, 0xCDBAB052U, 0xFD3FBFA7U, 0x6EA4906CU, 0x5E219F99U, 0x0FAE8F86U, 0x3F2B8073U, + 0xB926BA4FU, 0x89A3B5BAU, 0xD82CA5A5U, 0xE8A9AA50U, 0x7B32859BU, 0x4BB78A6EU, 0x1A389A71U, 0x2ABD9584U, 0x879C8456U, + 0xB7198BA3U, 0xE6969BBCU, 0xD6139449U, 0x4588BB82U, 0x750DB477U, 0x2482A468U, 0x1407AB9DU, 0x920A91A1U, 0xA28F9E54U, + 0xF3008E4BU, 0xC38581BEU, 0x501EAE75U, 0x609BA180U, 0x3114B19FU, 0x0191BE6AU, 0xFAE8F864U, 0xCA6DF791U, 0x9BE2E78EU, + 0xAB67E87BU, 0x38FCC7B0U, 0x0879C845U, 0x59F6D85AU, 0x6973D7AFU, 0xEF7EED93U, 0xDFFBE266U, 0x8E74F279U, 0xBEF1FD8CU, + 0x2D6AD247U, 0x1DEFDDB2U, 0x4C60CDADU, 0x7CE5C258U, 0xD1C4D38AU, 0xE141DC7FU, 0xB0CECC60U, 0x804BC395U, 0x13D0EC5EU, + 0x2355E3ABU, 0x72DAF3B4U, 0x425FFC41U, 0xC452C67DU, 0xF4D7C988U, 0xA558D997U, 0x95DDD662U, 0x0646F9A9U, 0x36C3F65CU, + 0x674CE643U, 0x57C9E9B6U, 0xC8DF352FU, 0xF85A3ADAU, 0xA9D52AC5U, 0x99502530U, 0x0ACB0AFBU, 0x3A4E050EU, 0x6BC11511U, + 0x5B441AE4U, 0xDD4920D8U, 0xEDCC2F2DU, 0xBC433F32U, 0x8CC630C7U, 0x1F5D1F0CU, 0x2FD810F9U, 0x7E5700E6U, 0x4ED20F13U, + 0xE3F31EC1U, 0xD3761134U, 0x82F9012BU, 0xB27C0EDEU, 0x21E72115U, 0x11622EE0U, 0x40ED3EFFU, 0x7068310AU, 0xF6650B36U, + 0xC6E004C3U, 0x976F14DCU, 0xA7EA1B29U, 0x347134E2U, 0x04F43B17U, 0x557B2B08U, 0x65FE24FDU, 0x9E8762F3U, 0xAE026D06U, + 0xFF8D7D19U, 0xCF0872ECU, 0x5C935D27U, 0x6C1652D2U, 0x3D9942CDU, 0x0D1C4D38U, 0x8B117704U, 0xBB9478F1U, 0xEA1B68EEU, + 0xDA9E671BU, 0x490548D0U, 0x79804725U, 0x280F573AU, 0x188A58CFU, 0xB5AB491DU, 0x852E46E8U, 0xD4A156F7U, 0xE4245902U, + 0x77BF76C9U, 0x473A793CU, 0x16B56923U, 0x263066D6U, 0xA03D5CEAU, 0x90B8531FU, 0xC1374300U, 0xF1B24CF5U, 0x6229633EU, + 0x52AC6CCBU, 0x03237CD4U, 0x33A67321U, 0x646F9A97U, 0x54EA9562U, 0x0565857DU, 0x35E08A88U, 0xA67BA543U, 0x96FEAAB6U, + 0xC771BAA9U, 0xF7F4B55CU, 0x71F98F60U, 0x417C8095U, 0x10F3908AU, 0x20769F7FU, 0xB3EDB0B4U, 0x8368BF41U, 0xD2E7AF5EU, + 0xE262A0ABU, 0x4F43B179U, 0x7FC6BE8CU, 0x2E49AE93U, 0x1ECCA166U, 0x8D578EADU, 0xBDD28158U, 0xEC5D9147U, 0xDCD89EB2U, + 0x5AD5A48EU, 0x6A50AB7BU, 0x3BDFBB64U, 0x0B5AB491U, 0x98C19B5AU, 0xA84494AFU, 0xF9CB84B0U, 0xC94E8B45U, 0x3237CD4BU, + 0x02B2C2BEU, 0x533DD2A1U, 0x63B8DD54U, 0xF023F29FU, 0xC0A6FD6AU, 0x9129ED75U, 0xA1ACE280U, 0x27A1D8BCU, 0x1724D749U, + 0x46ABC756U, 0x762EC8A3U, 0xE5B5E768U, 0xD530E89DU, 0x84BFF882U, 0xB43AF777U, 0x191BE6A5U, 0x299EE950U, 0x7811F94FU, + 0x4894F6BAU, 0xDB0FD971U, 0xEB8AD684U, 0xBA05C69BU, 0x8A80C96EU, 0x0C8DF352U, 0x3C08FCA7U, 0x6D87ECB8U, 0x5D02E34DU, + 0xCE99CC86U, 0xFE1CC373U, 0xAF93D36CU, 0x9F16DC99U +}; + + + + +/** +* Calculates the CRC over the provided range. +* +* @param begin Constant iterator pointing to begin of the range. +* @param end Constant iterator pointing to end of the range. +* @param startValue The CRC value from previous call. +* @return The calculated CRC value. +* +* Parameters of the CRC: +* - Width = 32 +* - Poly = 0x4C11DB7 +* - InitValue = 0xFFFFFFFF +* - ReflectIn = true +* - XorOut = 0xFFFFFFFF +* - ReflectOut = true +*/ +uint32_t e2e_crc::calculate_profile_custom(buffer::buffer_view _buffer_view) { + // InitValue + uint32_t crc = 0xFFFFFFFFU; + + for (uint8_t byte : _buffer_view) { + crc = lookup_table_profile_custom[static_cast<uint8_t>(byte ^ crc)] ^ (crc >> 8U); + } + + // XorOut + crc = crc ^ 0xFFFFFFFFU; + return crc; +} + + +const uint32_t e2e_crc::lookup_table_profile_custom[256] = { + 0x00000000U, 0x77073096U, 0xEE0E612CU, 0x990951BAU, 0x076DC419U, 0x706AF48FU, 0xE963A535U, 0x9E6495A3U, + 0x0EDB8832U, 0x79DCB8A4U, 0xE0D5E91EU, 0x97D2D988U, 0x09B64C2BU, 0x7EB17CBDU, 0xE7B82D07U, 0x90BF1D91U, + 0x1DB71064U, 0x6AB020F2U, 0xF3B97148U, 0x84BE41DEU, 0x1ADAD47DU, 0x6DDDE4EBU, 0xF4D4B551U, 0x83D385C7U, + 0x136C9856U, 0x646BA8C0U, 0xFD62F97AU, 0x8A65C9ECU, 0x14015C4FU, 0x63066CD9U, 0xFA0F3D63U, 0x8D080DF5U, + 0x3B6E20C8U, 0x4C69105EU, 0xD56041E4U, 0xA2677172U, 0x3C03E4D1U, 0x4B04D447U, 0xD20D85FDU, 0xA50AB56BU, + 0x35B5A8FAU, 0x42B2986CU, 0xDBBBC9D6U, 0xACBCF940U, 0x32D86CE3U, 0x45DF5C75U, 0xDCD60DCFU, 0xABD13D59U, + 0x26D930ACU, 0x51DE003AU, 0xC8D75180U, 0xBFD06116U, 0x21B4F4B5U, 0x56B3C423U, 0xCFBA9599U, 0xB8BDA50FU, + 0x2802B89EU, 0x5F058808U, 0xC60CD9B2U, 0xB10BE924U, 0x2F6F7C87U, 0x58684C11U, 0xC1611DABU, 0xB6662D3DU, + 0x76DC4190U, 0x01DB7106U, 0x98D220BCU, 0xEFD5102AU, 0x71B18589U, 0x06B6B51FU, 0x9FBFE4A5U, 0xE8B8D433U, + 0x7807C9A2U, 0x0F00F934U, 0x9609A88EU, 0xE10E9818U, 0x7F6A0DBBU, 0x086D3D2DU, 0x91646C97U, 0xE6635C01U, + 0x6B6B51F4U, 0x1C6C6162U, 0x856530D8U, 0xF262004EU, 0x6C0695EDU, 0x1B01A57BU, 0x8208F4C1U, 0xF50FC457U, + 0x65B0D9C6U, 0x12B7E950U, 0x8BBEB8EAU, 0xFCB9887CU, 0x62DD1DDFU, 0x15DA2D49U, 0x8CD37CF3U, 0xFBD44C65U, + 0x4DB26158U, 0x3AB551CEU, 0xA3BC0074U, 0xD4BB30E2U, 0x4ADFA541U, 0x3DD895D7U, 0xA4D1C46DU, 0xD3D6F4FBU, + 0x4369E96AU, 0x346ED9FCU, 0xAD678846U, 0xDA60B8D0U, 0x44042D73U, 0x33031DE5U, 0xAA0A4C5FU, 0xDD0D7CC9U, + 0x5005713CU, 0x270241AAU, 0xBE0B1010U, 0xC90C2086U, 0x5768B525U, 0x206F85B3U, 0xB966D409U, 0xCE61E49FU, + 0x5EDEF90EU, 0x29D9C998U, 0xB0D09822U, 0xC7D7A8B4U, 0x59B33D17U, 0x2EB40D81U, 0xB7BD5C3BU, 0xC0BA6CADU, + 0xEDB88320U, 0x9ABFB3B6U, 0x03B6E20CU, 0x74B1D29AU, 0xEAD54739U, 0x9DD277AFU, 0x04DB2615U, 0x73DC1683U, + 0xE3630B12U, 0x94643B84U, 0x0D6D6A3EU, 0x7A6A5AA8U, 0xE40ECF0BU, 0x9309FF9DU, 0x0A00AE27U, 0x7D079EB1U, + 0xF00F9344U, 0x8708A3D2U, 0x1E01F268U, 0x6906C2FEU, 0xF762575DU, 0x806567CBU, 0x196C3671U, 0x6E6B06E7U, + 0xFED41B76U, 0x89D32BE0U, 0x10DA7A5AU, 0x67DD4ACCU, 0xF9B9DF6FU, 0x8EBEEFF9U, 0x17B7BE43U, 0x60B08ED5U, + 0xD6D6A3E8U, 0xA1D1937EU, 0x38D8C2C4U, 0x4FDFF252U, 0xD1BB67F1U, 0xA6BC5767U, 0x3FB506DDU, 0x48B2364BU, + 0xD80D2BDAU, 0xAF0A1B4CU, 0x36034AF6U, 0x41047A60U, 0xDF60EFC3U, 0xA867DF55U, 0x316E8EEFU, 0x4669BE79U, + 0xCB61B38CU, 0xBC66831AU, 0x256FD2A0U, 0x5268E236U, 0xCC0C7795U, 0xBB0B4703U, 0x220216B9U, 0x5505262FU, + 0xC5BA3BBEU, 0xB2BD0B28U, 0x2BB45A92U, 0x5CB36A04U, 0xC2D7FFA7U, 0xB5D0CF31U, 0x2CD99E8BU, 0x5BDEAE1DU, + 0x9B64C2B0U, 0xEC63F226U, 0x756AA39CU, 0x026D930AU, 0x9C0906A9U, 0xEB0E363FU, 0x72076785U, 0x05005713U, + 0x95BF4A82U, 0xE2B87A14U, 0x7BB12BAEU, 0x0CB61B38U, 0x92D28E9BU, 0xE5D5BE0DU, 0x7CDCEFB7U, 0x0BDBDF21U, + 0x86D3D2D4U, 0xF1D4E242U, 0x68DDB3F8U, 0x1FDA836EU, 0x81BE16CDU, 0xF6B9265BU, 0x6FB077E1U, 0x18B74777U, + 0x88085AE6U, 0xFF0F6A70U, 0x66063BCAU, 0x11010B5CU, 0x8F659EFFU, 0xF862AE69U, 0x616BFFD3U, 0x166CCF45U, + 0xA00AE278U, 0xD70DD2EEU, 0x4E048354U, 0x3903B3C2U, 0xA7672661U, 0xD06016F7U, 0x4969474DU, 0x3E6E77DBU, + 0xAED16A4AU, 0xD9D65ADCU, 0x40DF0B66U, 0x37D83BF0U, 0xA9BCAE53U, 0xDEBB9EC5U, 0x47B2CF7FU, 0x30B5FFE9U, + 0xBDBDF21CU, 0xCABAC28AU, 0x53B39330U, 0x24B4A3A6U, 0xBAD03605U, 0xCDD70693U, 0x54DE5729U, 0x23D967BFU, + 0xB3667A2EU, 0xC4614AB8U, 0x5D681B02U, 0x2A6F2B94U, 0xB40BBE37U, 0xC30C8EA1U, 0x5A05DF1BU, 0x2D02EF8DU +}; + +} + diff --git a/implementation/e2e_protection/src/e2e/profile/profile01/checker.cpp b/implementation/e2e_protection/src/e2e/profile/profile01/checker.cpp new file mode 100644 index 0000000..7379445 --- /dev/null +++ b/implementation/e2e_protection/src/e2e/profile/profile01/checker.cpp @@ -0,0 +1,42 @@ +// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#include "../../../../../e2e_protection/include/e2e/profile/profile01/checker.hpp" +#include "../../../../../logging/include/logger.hpp" +#include <iostream> +#include <sstream> +#include <string> +#include <iomanip> +#include <algorithm> + +namespace e2e { +namespace profile { +namespace profile01 { + +// [SWS_E2E_00196] +void profile_01_checker::check(const buffer::e2e_buffer &_buffer, + e2e::profile::profile_interface::generic_check_status &_generic_check_status) { + std::lock_guard<std::mutex> lock(check_mutex); + _generic_check_status = e2e::profile::profile_interface::generic_check_status::E2E_ERROR; + + + if(profile_01::is_buffer_length_valid(config, _buffer)) { + uint8_t received_crc(0); + uint8_t calculated_crc(0); + received_crc = _buffer[config.crc_offset]; + calculated_crc = profile_01::compute_crc(config, _buffer); + if(received_crc == calculated_crc) { + _generic_check_status = e2e::profile::profile_interface::generic_check_status::E2E_OK; + } else { + _generic_check_status = e2e::profile::profile_interface::generic_check_status::E2E_WRONG_CRC; + VSOMEIP_INFO << std::hex << "E2E protection: CRC8 does not match: calculated CRC: " << (uint32_t) calculated_crc << " received CRC: " << (uint32_t) received_crc; + } + } + return; +} + +} +} +} diff --git a/implementation/e2e_protection/src/e2e/profile/profile01/profile_01.cpp b/implementation/e2e_protection/src/e2e/profile/profile01/profile_01.cpp new file mode 100644 index 0000000..f00ab86 --- /dev/null +++ b/implementation/e2e_protection/src/e2e/profile/profile01/profile_01.cpp @@ -0,0 +1,106 @@ +// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#include "../../../../../e2e_protection/include/e2e/profile/profile01/profile_01.hpp" +#include "../../../../../e2e_protection/include/crc/crc.hpp" +#include <iostream> +#include <sstream> +#include <string> +#include <iomanip> + +namespace e2e { +namespace profile { +namespace profile01 { + +uint8_t profile_01::compute_crc(const Config &_config, const buffer::e2e_buffer &_buffer) { + uint8_t computed_crc = 0xFF; + buffer::e2e_buffer data_id_buffer; //(_data, _data+_size); + data_id_buffer.push_back((uint8_t) (_config.data_id >> 8)); // insert MSB + data_id_buffer.push_back((uint8_t) _config.data_id); // insert LSB + + switch (_config.data_id_mode) { + case p01_data_id_mode::E2E_P01_DATAID_BOTH: // CRC over 2 bytes + /* + * Two bytes are included in the CRC (double ID configuration) This is used in E2E variant 1A. + */ + // CRC = Crc_CalculateCRC8(Config->DataID, 1, 0xFF, FALSE) + computed_crc = crc::e2e_crc::calculate_profile_01(buffer::buffer_view(data_id_buffer, 1, 2), 0xFF); //CRC over low byte of Data ID (LSB) + + // CRC = Crc_CalculateCRC8(Config->DataID >> 8, 1, CRC, FALSE) + computed_crc = crc::e2e_crc::calculate_profile_01(buffer::buffer_view(data_id_buffer, 0, 1), computed_crc); //CRC over high byte of Data ID (MSB) + + break; + case p01_data_id_mode::E2E_P01_DATAID_LOW: // CRC over low byte only + /* + * Only the low byte is included, the high byte is never used. + * This is applicable if the IDs in a particular system are 8 bits + */ + // CRC = Crc_CalculateCRC8(Config->DataID, 1, 0xFF, FALSE) + computed_crc = crc::e2e_crc::calculate_profile_01(buffer::buffer_view(data_id_buffer, 1, 2), 0xFF); //CRC over low byte of Data ID (LSB) + break; + + case p01_data_id_mode::E2E_P01_DATAID_ALT: + /* One of the two bytes byte is included, alternating high and low byte, + * depending on parity of the counter (alternating ID configuration). + * For an even counter, the low byte is included. + * For an odd counter, the high byte is included. + * This is used in E2E variant 1B. + * + if( counter % 2 == 0) { + // CRC = Crc_CalculateCRC8(Config->DataID, 1, 0xFF, FALSE) + computed_crc = crc::e2e_crc::calculate_profile_01(buffer::buffer_view(data_id_buffer, 1, 2), 0xFF); //CRC over low byte of Data ID (LSB) + } else { + // CRC = Crc_CalculateCRC8(Config->DataID >> 8, 1, 0xFF, FALSE) + computed_crc = crc::e2e_crc::calculate_profile_01(buffer::buffer_view(data_id_buffer, 0, 1), 0xFF); //CRC over high byte of Data ID (MSB) + } + */ + break; + + case p01_data_id_mode::E2E_P01_DATAID_NIBBLE: + /* + * The low byte is included in the implicit CRC calculation, + * the low nibble of the high byte is transmitted along with + * the data (i.e. it is explicitly included), the high nibble of + * the high byte is not used. This is applicable for the IDs + * up to 12 bits. This is used in E2E variant 1C. + */ + // CRC = Crc_CalculateCRC8(Config->DataID, 1, 0xFF, FALSE) + computed_crc = crc::e2e_crc::calculate_profile_01(buffer::buffer_view(data_id_buffer, 1, 2), 0xFF); //CRC over low byte of Data ID (LSB) + + // CRC = Crc_CalculateCRC8 (0, 1, CRC, FALSE) + data_id_buffer.clear(); + data_id_buffer.push_back(0x00); + computed_crc = crc::e2e_crc::calculate_profile_01(buffer::buffer_view(data_id_buffer, 0, 1), computed_crc); // CRC with 0x00 + break; + + default: + break; + } + + // Compute CRC over the area before the CRC (if CRC is not the first byte) + if(_config.crc_offset >= 1) { + // CRC = Crc_CalculateCRC8 (Data, (Config->CRCOffset / 8), CRC, FALSE) + computed_crc = crc::e2e_crc::calculate_profile_01(buffer::buffer_view(_buffer, 0, _config.crc_offset), computed_crc); + } + + // Compute the area after CRC, if CRC is not the last byte. Start with the byte after CRC, finish with the last byte of Data. + if((_config.crc_offset) < (_config.data_length / 8) - 1) { + // CRC = Crc_CalculateCRC8 (& Data[Config->CRCOffset/8 + 1], (Config->DataLength / 8 - Config->CRCOffset / 8 - 1), CRC, FALSE) + computed_crc = crc::e2e_crc::calculate_profile_01(buffer::buffer_view(_buffer, _config.crc_offset + 1, _buffer.size()), computed_crc); + } + + // CRC = CRC ^ 0xFF + // To negate the last XOR 0xFF operation done on computed CRC by the last CalculateCRC8(), there is a XORing doneexternally by E2E Library + computed_crc = computed_crc ^ 0xFFU; + return computed_crc; +} + +/** @req [SWS_E2E_00356] */ +bool profile_01::is_buffer_length_valid(const Config &_config, const buffer::e2e_buffer &_buffer) { + return (((_config.data_length / 8) + 1U <= _buffer.size()) && _config.crc_offset <= _buffer.size()); +} +} +} +} diff --git a/implementation/e2e_protection/src/e2e/profile/profile01/protector.cpp b/implementation/e2e_protection/src/e2e/profile/profile01/protector.cpp new file mode 100644 index 0000000..f3e7134 --- /dev/null +++ b/implementation/e2e_protection/src/e2e/profile/profile01/protector.cpp @@ -0,0 +1,39 @@ +// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#include "../../../../../e2e_protection/include/e2e/profile/profile01/protector.hpp" +#include "../../../../../logging/include/logger.hpp" + +#include <iostream> +#include <sstream> +#include <string> +#include <iomanip> + + +namespace e2e { +namespace profile { +namespace profile01 { + +/** @req [SWS_E2E_00195] */ +void protector::protect(buffer::e2e_buffer &_buffer) { + std::lock_guard<std::mutex> lock(protect_mutex); + + if(profile_01::is_buffer_length_valid(config, _buffer)) { + // compute the CRC over DataID and Data + uint8_t computed_crc = profile_01::compute_crc(config, _buffer); + // write CRC in Data + write_crc(_buffer, computed_crc); + } +} + + +/** @req [SRS_E2E_08528] */ +void protector::write_crc(buffer::e2e_buffer &_buffer, uint8_t _computed_crc) { + _buffer[config.crc_offset] = _computed_crc; +} + +} +} +} diff --git a/implementation/e2e_protection/src/e2e/profile/profile_custom/checker.cpp b/implementation/e2e_protection/src/e2e/profile/profile_custom/checker.cpp new file mode 100644 index 0000000..d2608d3 --- /dev/null +++ b/implementation/e2e_protection/src/e2e/profile/profile_custom/checker.cpp @@ -0,0 +1,49 @@ +// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#include "../../../../../e2e_protection/include/e2e/profile/profile_custom/checker.hpp" +#include "../../../../../logging/include/logger.hpp" +#include <iostream> +#include <sstream> +#include <string> +#include <iomanip> +#include <algorithm> + +namespace e2e { +namespace profile { +namespace profile_custom { + +void profile_custom_checker::check(const buffer::e2e_buffer &_buffer, + e2e::profile::profile_interface::generic_check_status &_generic_check_status) { + std::lock_guard<std::mutex> lock(check_mutex); + _generic_check_status = e2e::profile::profile_interface::generic_check_status::E2E_ERROR; + + if(profile_custom::is_buffer_length_valid(config, _buffer)) { + uint32_t received_crc(0); + uint32_t calculated_crc(0); + + received_crc = read_crc(_buffer); + calculated_crc = profile_custom::compute_crc(config, _buffer); + if(received_crc == calculated_crc) { + _generic_check_status = e2e::profile::profile_interface::generic_check_status::E2E_OK; + } else { + _generic_check_status = e2e::profile::profile_interface::generic_check_status::E2E_WRONG_CRC; + VSOMEIP_INFO << std::hex << "E2E protection: CRC32 does not match: calculated CRC: " << (uint32_t) calculated_crc << " received CRC: " << (uint32_t) received_crc; + } + } + return; +} + +uint32_t profile_custom_checker::read_crc(const buffer::e2e_buffer &_buffer) const { + return (static_cast<uint32_t>(_buffer[config.crc_offset ]) << 24U) | + (static_cast<uint32_t>(_buffer[config.crc_offset + 1U]) << 16U) | + (static_cast<uint32_t>(_buffer[config.crc_offset + 2U]) << 8U) | + static_cast<uint32_t>(_buffer[config.crc_offset + 3U]); +} + + +} +} +} diff --git a/implementation/e2e_protection/src/e2e/profile/profile_custom/profile_custom.cpp b/implementation/e2e_protection/src/e2e/profile/profile_custom/profile_custom.cpp new file mode 100644 index 0000000..bc39842 --- /dev/null +++ b/implementation/e2e_protection/src/e2e/profile/profile_custom/profile_custom.cpp @@ -0,0 +1,29 @@ +// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#include "../../../../../e2e_protection/include/e2e/profile/profile_custom/profile_custom.hpp" +#include "../../../../../e2e_protection/include/crc/crc.hpp" +#include <iostream> +#include <sstream> +#include <string> +#include <iomanip> + +namespace e2e { +namespace profile { +namespace profile_custom { + +uint32_t profile_custom::compute_crc(const Config &_config, const buffer::e2e_buffer &_buffer) { + uint32_t computed_crc = crc::e2e_crc::calculate_profile_custom(buffer::buffer_view(_buffer, _config.crc_offset + 4, _buffer.size())); + return computed_crc; +} + +bool profile_custom::is_buffer_length_valid(const Config &_config, const buffer::e2e_buffer &_buffer) { + + return ( (_config.crc_offset + 4U) <=_buffer.size()); +} + +} +} +} diff --git a/implementation/e2e_protection/src/e2e/profile/profile_custom/protector.cpp b/implementation/e2e_protection/src/e2e/profile/profile_custom/protector.cpp new file mode 100644 index 0000000..3c77116 --- /dev/null +++ b/implementation/e2e_protection/src/e2e/profile/profile_custom/protector.cpp @@ -0,0 +1,41 @@ +// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#include "../../../../../e2e_protection/include/e2e/profile/profile_custom/protector.hpp" +#include "../../../../../logging/include/logger.hpp" + +#include <iostream> +#include <sstream> +#include <string> +#include <iomanip> +#include <iostream> +#include <sstream> + + +namespace e2e { +namespace profile { +namespace profile_custom { + +void protector::protect(buffer::e2e_buffer &_buffer) { + std::lock_guard<std::mutex> lock(protect_mutex); + + if(profile_custom::is_buffer_length_valid(config, _buffer)) { + // compute the CRC over DataID and Data + uint32_t computed_crc = profile_custom::compute_crc(config, _buffer); + // write CRC in Data + write_crc(_buffer, computed_crc); + } +} + +void protector::write_crc(buffer::e2e_buffer &_buffer, uint32_t _computed_crc) { + _buffer[config.crc_offset] = static_cast<uint8_t>(_computed_crc >> 24U); + _buffer[config.crc_offset + 1U] = static_cast<uint8_t>(_computed_crc >> 16U); + _buffer[config.crc_offset + 2U] = static_cast<uint8_t>(_computed_crc >> 8U); + _buffer[config.crc_offset + 3U] = static_cast<uint8_t>(_computed_crc); +} + +} +} +} diff --git a/implementation/e2e_protection/src/e2exf/config.cpp b/implementation/e2e_protection/src/e2exf/config.cpp new file mode 100644 index 0000000..6aa9223 --- /dev/null +++ b/implementation/e2e_protection/src/e2exf/config.cpp @@ -0,0 +1,17 @@ +// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef PROJECT_CONFIG_CPP_HPP +#define PROJECT_CONFIG_CPP_HPP + +#include <ostream> +#include "../../../e2e_protection/include/e2exf/config.hpp" + +std::ostream &operator<<(std::ostream &_os, const e2exf::data_identifier &_data_identifier) { + _os << _data_identifier.first << _data_identifier.second; + return _os; +} + +#endif // PROJECT_CONFIG_CPP_HPP diff --git a/implementation/endpoints/include/local_server_endpoint_impl.hpp b/implementation/endpoints/include/local_server_endpoint_impl.hpp index b0e8d86..b6c26a7 100644 --- a/implementation/endpoints/include/local_server_endpoint_impl.hpp +++ b/implementation/endpoints/include/local_server_endpoint_impl.hpp @@ -76,6 +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(); std::unique_lock<std::mutex> get_socket_lock(); @@ -90,18 +91,23 @@ private: private: connection(std::weak_ptr<local_server_endpoint_impl> _server, std::uint32_t _recv_buffer_size_initial, + std::uint32_t _max_message_size, std::uint32_t _buffer_shrink_threshold); void send_magic_cookie(); void receive_cbk(boost::system::error_code const &_error, std::size_t _bytes); void calculate_shrink_count(); + const std::string get_path_local() const; + const std::string get_path_remote() const; + void handle_recv_buffer_exception(const std::exception &_e); std::mutex socket_mutex_; local_server_endpoint_impl::socket_type socket_; std::weak_ptr<local_server_endpoint_impl> server_; - const uint32_t recv_buffer_size_initial_; + const std::uint32_t recv_buffer_size_initial_; + const std::uint32_t max_message_size_; message_buffer_t recv_buffer_; size_t recv_buffer_size_; diff --git a/implementation/endpoints/include/tcp_client_endpoint_impl.hpp b/implementation/endpoints/include/tcp_client_endpoint_impl.hpp index 2a7263d..20eae38 100644 --- a/implementation/endpoints/include/tcp_client_endpoint_impl.hpp +++ b/implementation/endpoints/include/tcp_client_endpoint_impl.hpp @@ -46,6 +46,10 @@ private: void connect();
void receive();
void calculate_shrink_count();
+ const std::string get_address_port_remote() const;
+ const std::string get_address_port_local() const;
+ void handle_recv_buffer_exception(const std::exception &_e);
+
const std::uint32_t recv_buffer_size_initial_;
message_buffer_t recv_buffer_;
diff --git a/implementation/endpoints/include/tcp_server_endpoint_impl.hpp b/implementation/endpoints/include/tcp_server_endpoint_impl.hpp index 5875e71..410bca7 100644 --- a/implementation/endpoints/include/tcp_server_endpoint_impl.hpp +++ b/implementation/endpoints/include/tcp_server_endpoint_impl.hpp @@ -87,6 +87,10 @@ private: void receive_cbk(boost::system::error_code const &_error,
std::size_t _bytes);
void calculate_shrink_count();
+ const std::string get_address_port_remote() const;
+ const std::string get_address_port_local() const;
+ void handle_recv_buffer_exception(const std::exception &_e);
+
std::mutex socket_mutex_;
tcp_server_endpoint_impl::socket_type socket_;
diff --git a/implementation/endpoints/src/local_server_endpoint_impl.cpp b/implementation/endpoints/src/local_server_endpoint_impl.cpp index e2b6440..0e9bd4f 100644 --- a/implementation/endpoints/src/local_server_endpoint_impl.cpp +++ b/implementation/endpoints/src/local_server_endpoint_impl.cpp @@ -88,7 +88,8 @@ void local_server_endpoint_impl::start() { if (acceptor_.is_open()) { current_ = connection::create( std::dynamic_pointer_cast<local_server_endpoint_impl>( - shared_from_this()), buffer_shrink_threshold_); + shared_from_this()), max_message_size_, + buffer_shrink_threshold_); { std::unique_lock<std::mutex> its_lock(current_->get_socket_lock()); @@ -229,11 +230,13 @@ 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), recv_buffer_size_initial_(_initial_recv_buffer_size + 8), + max_message_size_(_max_message_size), recv_buffer_(recv_buffer_size_initial_, 0), recv_buffer_size_(0), missing_capacity_(0), @@ -245,12 +248,13 @@ local_server_endpoint_impl::connection::connection( 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, std::uint32_t _buffer_shrink_threshold) { const std::uint32_t its_initial_buffer_size = VSOMEIP_COMMAND_HEADER_SIZE + VSOMEIP_MAX_LOCAL_MESSAGE_SIZE + static_cast<std::uint32_t>(sizeof(instance_t) + sizeof(bool) + sizeof(bool)); - return ptr(new connection(_server, its_initial_buffer_size, + return ptr(new connection(_server, _max_message_size, its_initial_buffer_size, _buffer_shrink_threshold)); } @@ -269,25 +273,31 @@ void local_server_endpoint_impl::connection::start() { 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_) { - if (missing_capacity_ > MESSAGE_SIZE_UNLIMITED) { - VSOMEIP_ERROR << "Missing receive buffer capacity exceeds allowed maximum!"; - return; - } - 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); + try { + if (missing_capacity_) { + if (missing_capacity_ > MESSAGE_SIZE_UNLIMITED) { + VSOMEIP_ERROR << "Missing receive buffer capacity exceeds allowed maximum!"; + return; + } + 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; } - 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; + } catch (const std::exception &e) { + handle_recv_buffer_exception(e); + // don't start receiving again + return; } socket_.async_receive( boost::asio::buffer(&recv_buffer_[recv_buffer_size_], buffer_size), @@ -425,6 +435,17 @@ void local_server_endpoint_impl::connection::receive_cbk( } else { its_end = its_start; } + if (its_command_size && max_message_size_ != MESSAGE_SIZE_UNLIMITED + && its_command_size > max_message_size_) { + std::lock_guard<std::mutex> its_lock(socket_mutex_); + VSOMEIP_ERROR << "Received a local message which exceeds " + << "maximum message size (" << std::dec << its_command_size + << ") aborting! local: " << get_path_local() << " remote: " + << get_path_remote(); + recv_buffer_.resize(recv_buffer_size_initial_, 0x0); + recv_buffer_.shrink_to_fit(); + return; + } if (its_end + 3 < its_end) { VSOMEIP_ERROR << "buffer overflow in local server endpoint ~> abort!"; return; @@ -529,4 +550,71 @@ void local_server_endpoint_impl::connection::calculate_shrink_count() { } } +const std::string local_server_endpoint_impl::connection::get_path_local() const { + boost::system::error_code ec; + std::string its_local_path; + if (socket_.is_open()) { + endpoint_type its_local_endpoint = socket_.local_endpoint(ec); + if (!ec) { +#ifdef _WIN32 + its_local_path += its_local_endpoint.address().to_string(ec); + its_local_path += ":"; + its_local_path += std::to_string(its_local_endpoint.port()); +#else + its_local_path += its_local_endpoint.path(); +#endif + + } + } + return its_local_path; +} + +const std::string local_server_endpoint_impl::connection::get_path_remote() const { + boost::system::error_code ec; + std::string its_remote_path; + if (socket_.is_open()) { + endpoint_type its_remote_endpoint = socket_.remote_endpoint(ec); + if (!ec) { +#ifdef _WIN32 + its_remote_path += its_remote_endpoint.address().to_string(ec); + its_remote_path += ":"; + its_remote_path += std::to_string(its_remote_endpoint.port()); +#else + its_remote_path += its_remote_endpoint.path(); +#endif + } + } + return its_remote_path; +} + +void local_server_endpoint_impl::connection::handle_recv_buffer_exception( + const std::exception &_e) { + std::stringstream its_message; + its_message <<"local_server_endpoint_impl::connection catched exception" + << _e.what() << " local: " << get_path_local() << " remote: " + << get_path_remote() << " shutting down connection. Start of buffer: "; + + for (std::size_t i = 0; i < recv_buffer_size_ && i < 16; i++) { + its_message << std::setw(2) << std::setfill('0') << std::hex + << (int) (recv_buffer_[i]) << " "; + } + + its_message << " Last 16 Bytes captured: "; + for (int i = 15; recv_buffer_size_ > 15 && i >= 0; i--) { + its_message << std::setw(2) << std::setfill('0') << std::hex + << (int) (recv_buffer_[i]) << " "; + } + VSOMEIP_ERROR << its_message.str(); + recv_buffer_.clear(); + if (socket_.is_open()) { + boost::system::error_code its_error; + socket_.shutdown(socket_.shutdown_both, its_error); + socket_.close(its_error); + } + std::shared_ptr<local_server_endpoint_impl> its_server = server_.lock(); + if (its_server) { + its_server->remove_connection(this); + } +} + } // namespace vsomeip diff --git a/implementation/endpoints/src/tcp_client_endpoint_impl.cpp b/implementation/endpoints/src/tcp_client_endpoint_impl.cpp index 4afe3ef..e89bc5c 100644 --- a/implementation/endpoints/src/tcp_client_endpoint_impl.cpp +++ b/implementation/endpoints/src/tcp_client_endpoint_impl.cpp @@ -111,25 +111,31 @@ void tcp_client_endpoint_impl::receive() { 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_) {
- if (missing_capacity_ > MESSAGE_SIZE_UNLIMITED) {
- VSOMEIP_ERROR << "Missing receive buffer capacity exceeds allowed maximum!";
- return;
- }
- 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);
+ try {
+ if (missing_capacity_) {
+ if (missing_capacity_ > MESSAGE_SIZE_UNLIMITED) {
+ VSOMEIP_ERROR << "Missing receive buffer capacity exceeds allowed maximum!";
+ return;
+ }
+ 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;
}
- 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;
+ } catch (const std::exception &e) {
+ handle_recv_buffer_exception(e);
+ // don't start receiving again
+ return;
}
socket_.async_receive(
boost::asio::buffer(&recv_buffer_[recv_buffer_size_], buffer_size),
@@ -303,44 +309,53 @@ void tcp_client_endpoint_impl::receive_cbk( recv_buffer_size_ -= current_message_size;
its_iteration_gap += current_message_size;
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 (max_message_size_ != MESSAGE_SIZE_UNLIMITED &&
current_message_size > max_message_size_) {
+ std::lock_guard<std::mutex> its_lock(socket_mutex_);
+ recv_buffer_size_ = 0;
+ recv_buffer_.resize(recv_buffer_size_initial_, 0x0);
+ recv_buffer_.shrink_to_fit();
if (has_enabled_magic_cookies_) {
VSOMEIP_ERROR << "Received a TCP message which exceeds "
<< "maximum message size ("
<< std::dec << current_message_size
<< "). Magic Cookies are enabled: "
- << "Resetting receiver.";
- recv_buffer_size_ = 0;
+ << "Resetting receiver. local: "
+ << get_address_port_local() << " remote: "
+ << get_address_port_remote();
} else {
VSOMEIP_ERROR << "Received a TCP message which exceeds "
<< "maximum message size ("
<< std::dec << current_message_size
<< ") Magic cookies are disabled: "
- << "Client will be disabled!";
- recv_buffer_size_ = 0;
+ << "Client will be disabled! local: "
+ << get_address_port_local() << " remote: "
+ << get_address_port_remote();
return;
}
+ } 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 {
- 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;
+ std::lock_guard<std::mutex> its_lock(socket_mutex_);
+ 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
+ << "local: " << get_address_port_local()
+ << " remote: " << get_address_port_remote();
}
} while (has_full_message && recv_buffer_size_);
if (its_iteration_gap) {
@@ -380,4 +395,71 @@ void tcp_client_endpoint_impl::calculate_shrink_count() { }
}
+
+const std::string tcp_client_endpoint_impl::get_address_port_remote() const {
+ boost::system::error_code ec;
+ std::string its_address_port;
+ its_address_port.reserve(21);
+ boost::asio::ip::address its_address;
+ if (get_remote_address(its_address)) {
+ its_address_port += its_address.to_string();
+ }
+ its_address_port += ":";
+ its_address_port += std::to_string(remote_port_);
+ return its_address_port;
+}
+
+const std::string tcp_client_endpoint_impl::get_address_port_local() const {
+ std::string its_address_port;
+ its_address_port.reserve(21);
+ boost::system::error_code ec;
+ if (socket_.is_open()) {
+ endpoint_type its_local_endpoint = socket_.local_endpoint(ec);
+ if (!ec) {
+ its_address_port += its_local_endpoint.address().to_string(ec);
+ its_address_port += ":";
+ its_address_port.append(std::to_string(its_local_endpoint.port()));
+ }
+ }
+ return its_address_port;
+}
+
+void tcp_client_endpoint_impl::handle_recv_buffer_exception(
+ const std::exception &_e) {
+ boost::system::error_code ec;
+
+ std::stringstream its_message;
+ its_message <<"tcp_client_endpoint_impl::connection catched exception"
+ << _e.what() << " local: " << get_address_port_local()
+ << " remote: " << get_address_port_remote()
+ << " shutting down connection. Start of buffer: ";
+
+ for (std::size_t i = 0; i < recv_buffer_size_ && i < 16; i++) {
+ its_message << std::setw(2) << std::setfill('0') << std::hex
+ << (int) (recv_buffer_[i]) << " ";
+ }
+
+ its_message << " Last 16 Bytes captured: ";
+ for (int i = 15; recv_buffer_size_ > 15 && i >= 0; i--) {
+ its_message << std::setw(2) << std::setfill('0') << std::hex
+ << (int) (recv_buffer_[i]) << " ";
+ }
+ VSOMEIP_ERROR << its_message.str();
+ recv_buffer_.clear();
+ {
+ std::lock_guard<std::mutex> its_lock(mutex_);
+ sending_blocked_ = true;
+ }
+ {
+ std::lock_guard<std::mutex> its_lock(connect_timer_mutex_);
+ boost::system::error_code ec;
+ connect_timer_.cancel(ec);
+ }
+ if (socket_.is_open()) {
+ boost::system::error_code its_error;
+ socket_.shutdown(socket_type::shutdown_both, its_error);
+ socket_.close(its_error);
+ }
+}
+
} // namespace vsomeip
diff --git a/implementation/endpoints/src/tcp_server_endpoint_impl.cpp b/implementation/endpoints/src/tcp_server_endpoint_impl.cpp index 85766ef..251137b 100644 --- a/implementation/endpoints/src/tcp_server_endpoint_impl.cpp +++ b/implementation/endpoints/src/tcp_server_endpoint_impl.cpp @@ -259,25 +259,31 @@ void tcp_server_endpoint_impl::connection::receive() { 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_) { - if (missing_capacity_ > MESSAGE_SIZE_UNLIMITED) { - VSOMEIP_ERROR << "Missing receive buffer capacity exceeds allowed maximum!"; - return; - } - 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); + try { + if (missing_capacity_) { + if (missing_capacity_ > MESSAGE_SIZE_UNLIMITED) { + VSOMEIP_ERROR << "Missing receive buffer capacity exceeds allowed maximum!"; + return; + } + 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; } - 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; + } catch (const std::exception &e) { + handle_recv_buffer_exception(e); + // don't start receiving again + return; } socket_.async_receive(boost::asio::buffer(&recv_buffer_[recv_buffer_size_], buffer_size), std::bind(&tcp_server_endpoint_impl::connection::receive_cbk, @@ -453,42 +459,51 @@ void tcp_server_endpoint_impl::connection::receive_cbk( remote_address_, remote_port_); } } - } 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; - } else { - 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_) { + if (max_message_size_ != MESSAGE_SIZE_UNLIMITED + && current_message_size > max_message_size_) { + std::lock_guard<std::mutex> its_lock(socket_mutex_); + recv_buffer_size_ = 0; + recv_buffer_.resize(recv_buffer_size_initial_, 0x0); + recv_buffer_.shrink_to_fit(); + 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. local: " + << get_address_port_local() << " remote: " + << get_address_port_remote(); + } else { + 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! local: " + << get_address_port_local() << " remote: " + << get_address_port_remote(); + return; + } + } 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 { + std::lock_guard<std::mutex> its_lock(socket_mutex_); 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; + << " its_iteration_gap: " << its_iteration_gap + << "local: " << get_address_port_local() + << " remote: " << get_address_port_remote(); } } } while (has_full_message && recv_buffer_size_); @@ -570,6 +585,62 @@ void tcp_server_endpoint_impl::connection::set_remote_info( remote_port_ = _remote.port(); } +const std::string tcp_server_endpoint_impl::connection::get_address_port_remote() const { + std::string its_address_port; + its_address_port.reserve(21); + boost::system::error_code ec; + its_address_port += remote_address_.to_string(ec); + its_address_port += ":"; + its_address_port += std::to_string(remote_port_); + return its_address_port; +} + +const std::string tcp_server_endpoint_impl::connection::get_address_port_local() const { + std::string its_address_port; + its_address_port.reserve(21); + boost::system::error_code ec; + if (socket_.is_open()) { + endpoint_type its_local_endpoint = socket_.local_endpoint(ec); + if (!ec) { + its_address_port += its_local_endpoint.address().to_string(ec); + its_address_port += ":"; + its_address_port += std::to_string(its_local_endpoint.port()); + } + } + return its_address_port; +} + +void tcp_server_endpoint_impl::connection::handle_recv_buffer_exception( + const std::exception &_e) { + std::stringstream its_message; + its_message <<"tcp_server_endpoint_impl::connection catched exception" + << _e.what() << " local: " << get_address_port_local() + << " remote: " << get_address_port_remote() + << " shutting down connection. Start of buffer: "; + + for (std::size_t i = 0; i < recv_buffer_size_ && i < 16; i++) { + its_message << std::setw(2) << std::setfill('0') << std::hex + << (int) (recv_buffer_[i]) << " "; + } + + its_message << " Last 16 Bytes captured: "; + for (int i = 15; recv_buffer_size_ > 15 && i >= 0; i--) { + its_message << std::setw(2) << std::setfill('0') << std::hex + << (int) (recv_buffer_[i]) << " "; + } + VSOMEIP_ERROR << its_message.str(); + recv_buffer_.clear(); + if (socket_.is_open()) { + boost::system::error_code its_error; + socket_.shutdown(socket_.shutdown_both, its_error); + socket_.close(its_error); + } + std::shared_ptr<tcp_server_endpoint_impl> its_server = server_.lock(); + if (its_server) { + its_server->remove_connection(this); + } +} + // Dummies void tcp_server_endpoint_impl::receive() { // intentionally left empty diff --git a/implementation/routing/include/routing_manager_impl.hpp b/implementation/routing/include/routing_manager_impl.hpp index a6d7f0d..69a8412 100644 --- a/implementation/routing/include/routing_manager_impl.hpp +++ b/implementation/routing/include/routing_manager_impl.hpp @@ -400,6 +400,9 @@ private: client_t, client_t>>> pending_offers_; std::mutex pending_subscription_mutex_; + + std::map<e2exf::data_identifier, std::shared_ptr<e2e::profile::profile_interface::protector>> custom_protectors; + std::map<e2exf::data_identifier, std::shared_ptr<e2e::profile::profile_interface::checker>> custom_checkers; }; } // namespace vsomeip diff --git a/implementation/routing/src/routing_manager_impl.cpp b/implementation/routing/src/routing_manager_impl.cpp index bfc232e..96e3b08 100644 --- a/implementation/routing/src/routing_manager_impl.cpp +++ b/implementation/routing/src/routing_manager_impl.cpp @@ -43,6 +43,17 @@ #include "../../utility/include/byteorder.hpp" #include "../../utility/include/utility.hpp" +#include "../../e2e_protection/include/buffer/buffer.hpp" +#include "../../e2e_protection/include/e2exf/config.hpp" + +#include "../../e2e_protection/include/e2e/profile/profile01/profile_01.hpp" +#include "../../e2e_protection/include/e2e/profile/profile01/protector.hpp" +#include "../../e2e_protection/include/e2e/profile/profile01/checker.hpp" + +#include "../../e2e_protection/include/e2e/profile/profile_custom/profile_custom.hpp" +#include "../../e2e_protection/include/e2e/profile/profile_custom/protector.hpp" +#include "../../e2e_protection/include/e2e/profile/profile_custom/checker.hpp" + namespace vsomeip { routing_manager_impl::routing_manager_impl(routing_manager_host *_host) : @@ -89,6 +100,35 @@ void routing_manager_impl::init() { discovery_->init(); } } + + if( configuration_->is_e2e_enabled()) { + VSOMEIP_INFO << "E2E protection enabled."; + std::map<e2exf::data_identifier, std::shared_ptr<cfg::e2e>> its_e2e_configuration = configuration_->get_e2e_configuration(); + for (auto &identifier : its_e2e_configuration) { + auto its_cfg = identifier.second; + if(its_cfg->profile == "CRC8") { + e2exf::data_identifier its_data_identifier = {its_cfg->service_id, its_cfg->event_id}; + e2e::profile::profile01::Config its_profile_config = e2e::profile::profile01::Config(its_cfg->crc_offset, its_cfg->data_id, + (e2e::profile::profile01::p01_data_id_mode) its_cfg->data_id_mode, its_cfg->data_length); + if ((its_cfg->variant == "protector") || (its_cfg->variant == "both")) { + custom_protectors[its_data_identifier] = std::make_shared<e2e::profile::profile01::protector>(its_profile_config); + } + if ((its_cfg->variant == "checker") || (its_cfg->variant == "both")) { + custom_checkers[its_data_identifier] = std::make_shared<e2e::profile::profile01::profile_01_checker>(its_profile_config); + } + } else if(its_cfg->profile == "CRC32") { + e2exf::data_identifier its_data_identifier = {its_cfg->service_id, its_cfg->event_id}; + e2e::profile::profile_custom::Config its_profile_config = e2e::profile::profile_custom::Config(its_cfg->crc_offset); + + if ((its_cfg->variant == "protector") || (its_cfg->variant == "both")) { + custom_protectors[its_data_identifier] = std::make_shared<e2e::profile::profile_custom::protector>(its_profile_config); + } + if ((its_cfg->variant == "checker") || (its_cfg->variant == "both")) { + custom_checkers[its_data_identifier] = std::make_shared<e2e::profile::profile_custom::profile_custom_checker>(its_profile_config); + } + } + } + } } void routing_manager_impl::start() { @@ -567,6 +607,23 @@ bool routing_manager_impl::send(client_t _client, const byte_t *_data, // TODO: find out how to handle session id here is_sent = deliver_message(_data, _size, _instance, _reliable); } else { + buffer::e2e_buffer outputBuffer; + if( configuration_->is_e2e_enabled()) { + if ( !is_service_discovery) { + service_t its_service = VSOMEIP_BYTES_TO_WORD( + _data[VSOMEIP_SERVICE_POS_MIN], _data[VSOMEIP_SERVICE_POS_MAX]); + method_t its_method = VSOMEIP_BYTES_TO_WORD( + _data[VSOMEIP_METHOD_POS_MIN], _data[VSOMEIP_METHOD_POS_MAX]); + if( custom_protectors.count({its_service, its_method})) { + outputBuffer.assign(_data, _data + VSOMEIP_PAYLOAD_POS); + buffer::e2e_buffer inputBuffer(_data + VSOMEIP_PAYLOAD_POS, _data +_size); + custom_protectors[{its_service, its_method}]->protect( inputBuffer); + outputBuffer.resize(inputBuffer.size() + VSOMEIP_PAYLOAD_POS); + std::copy(inputBuffer.begin(), inputBuffer.end(), outputBuffer.begin() + VSOMEIP_PAYLOAD_POS); + _data = outputBuffer.data(); + } + } + } if (is_request) { client_t client = VSOMEIP_ROUTING_CLIENT; { @@ -694,8 +751,24 @@ bool routing_manager_impl::send_to( bool is_sent(false); std::lock_guard<std::mutex> its_lock(serialize_mutex_); if (serializer_->serialize(_message.get())) { - is_sent = send_to(_target, - serializer_->get_data(), serializer_->get_size(), _flush); + const byte_t *_data = serializer_->get_data(); + length_t _size = serializer_->get_size(); + buffer::e2e_buffer outputBuffer; + if( configuration_->is_e2e_enabled()) { + service_t its_service = VSOMEIP_BYTES_TO_WORD( + _data[VSOMEIP_SERVICE_POS_MIN], _data[VSOMEIP_SERVICE_POS_MAX]); + method_t its_method = VSOMEIP_BYTES_TO_WORD( + _data[VSOMEIP_METHOD_POS_MIN], _data[VSOMEIP_METHOD_POS_MAX]); + if( custom_protectors.count({its_service, its_method})) { + outputBuffer.assign(_data, _data + VSOMEIP_PAYLOAD_POS); + buffer::e2e_buffer inputBuffer(_data + VSOMEIP_PAYLOAD_POS, _data +_size); + custom_protectors[{its_service, its_method}]->protect( inputBuffer); + outputBuffer.resize(inputBuffer.size() + VSOMEIP_PAYLOAD_POS); + std::copy(inputBuffer.begin(), inputBuffer.end(), outputBuffer.begin() + VSOMEIP_PAYLOAD_POS); + _data = outputBuffer.data(); + } + } + is_sent = send_to(_target, _data, _size, _flush); serializer_->reset(); } else { VSOMEIP_ERROR<< "routing_manager_impl::send_to: serialization failed."; @@ -942,7 +1015,20 @@ void routing_manager_impl::on_message(const byte_t *_data, length_t _size, } } } + if( configuration_->is_e2e_enabled()) { + its_method = VSOMEIP_BYTES_TO_WORD( + _data[VSOMEIP_METHOD_POS_MIN], + _data[VSOMEIP_METHOD_POS_MAX]); + if( custom_checkers.count({its_service, its_method})) { + buffer::e2e_buffer inputBuffer(_data + VSOMEIP_PAYLOAD_POS, _data + _size); + e2e::profile::profile_interface::generic_check_status check_status; + custom_checkers[{its_service, its_method}]->check( inputBuffer, check_status); + if ( check_status != e2e::profile::profile_interface::generic_check_status::E2E_OK ) { + VSOMEIP_INFO << std::hex << "E2E protection: CRC check failed for service: " << its_service << " method: " << its_method; + } + } + } if (!deliver_specific_endpoint_message( its_service, its_instance, _data, _size, _receiver)) { // set client ID to zero for all messages @@ -1499,7 +1585,7 @@ std::shared_ptr<endpoint> routing_manager_impl::create_client_endpoint( _local_port), boost::asio::ip::tcp::endpoint(_address, _remote_port), io_, - configuration_->get_message_size_reliable( + configuration_->get_max_message_size_reliable( _address.to_string(), _remote_port), configuration_->get_buffer_shrink_threshold()); @@ -1538,7 +1624,7 @@ std::shared_ptr<endpoint> routing_manager_impl::create_server_endpoint( its_endpoint = std::make_shared<tcp_server_endpoint_impl>( shared_from_this(), boost::asio::ip::tcp::endpoint(its_unicast, _port), io_, - configuration_->get_message_size_reliable( + configuration_->get_max_message_size_reliable( its_unicast.to_string(), _port), configuration_->get_buffer_shrink_threshold()); if (configuration_->has_enabled_magic_cookies( diff --git a/implementation/service_discovery/include/service_discovery_impl.hpp b/implementation/service_discovery/include/service_discovery_impl.hpp index 09d4bd7..910fc61 100644 --- a/implementation/service_discovery/include/service_discovery_impl.hpp +++ b/implementation/service_discovery/include/service_discovery_impl.hpp @@ -303,7 +303,7 @@ private: // Sessions std::map<boost::asio::ip::address, std::pair<session_t, bool> > sessions_sent_; std::map<boost::asio::ip::address, - std::tuple<session_t, session_t, bool> > sessions_received_; + std::tuple<session_t, session_t, bool, bool> > sessions_received_; // Runtime std::weak_ptr<runtime> runtime_; diff --git a/implementation/service_discovery/src/service_discovery_impl.cpp b/implementation/service_discovery/src/service_discovery_impl.cpp index 7318eda..e8d29ef 100644 --- a/implementation/service_discovery/src/service_discovery_impl.cpp +++ b/implementation/service_discovery/src/service_discovery_impl.cpp @@ -586,39 +586,56 @@ bool service_discovery_impl::is_reboot( bool _reboot_flag, session_t _session) { bool result(false); - auto its_last_session = sessions_received_.find(_sender); + auto its_received = sessions_received_.find(_sender); bool is_multicast = _destination.is_multicast(); - session_t its_unicast_id = (is_multicast ? 0 : _session); - session_t its_multicast_id = (is_multicast ? _session : 0); + session_t its_multicast_session(0), its_unicast_session(0); + bool its_multicast_reboot_flag(true), its_unicast_reboot_flag(true); - if (its_last_session == sessions_received_.end()) { + if (is_multicast) { + its_multicast_session = _session; + its_multicast_reboot_flag = _reboot_flag; + } else { + its_unicast_session = _session; + its_unicast_reboot_flag = _reboot_flag; + } + + if (its_received == sessions_received_.end()) { sessions_received_[_sender] - = std::make_tuple(its_multicast_id, its_unicast_id, _reboot_flag); + = std::make_tuple(its_multicast_session, its_unicast_session, + its_multicast_reboot_flag, its_unicast_reboot_flag); } else { // Reboot detection: Either the flag has changed from false to true, // or the session identifier overrun while the flag is true - if (its_last_session != sessions_received_.end()) { - if (!std::get<2>(its_last_session->second) && _reboot_flag) { - result = true; - } else { - session_t its_last_id = (is_multicast ? - std::get<0>(its_last_session->second) : - std::get<1>(its_last_session->second)); - - if (std::get<2>(its_last_session->second) && _reboot_flag && - its_last_id >= _session) { - result = true; - } - } - } + if ((is_multicast && !std::get<2>(its_received->second) && _reboot_flag) + || (!is_multicast && !std::get<3>(its_received->second) && _reboot_flag)) { + result = true; + } else { + session_t its_old_session; + bool its_old_reboot_flag; + + if (is_multicast) { + its_old_session = std::get<0>(its_received->second); + its_old_reboot_flag = std::get<2>(its_received->second); + } else { + its_old_session = std::get<1>(its_received->second); + its_old_reboot_flag = std::get<3>(its_received->second); + } + + if (its_old_reboot_flag && _reboot_flag + && its_old_session >= _session) { + result = true; + } + } if (result == false) { - // no reboot -> update session + // no reboot -> update session/flag if (is_multicast) { - std::get<0>(its_last_session->second) = its_multicast_id; + std::get<0>(its_received->second) = its_multicast_session; + std::get<2>(its_received->second) = its_multicast_reboot_flag; } else { - std::get<1>(its_last_session->second) = its_unicast_id; + std::get<1>(its_received->second) = its_unicast_session; + std::get<3>(its_received->second) = its_multicast_reboot_flag; } } else { // reboot -> reset the session @@ -1037,6 +1054,7 @@ void service_discovery_impl::on_message(const byte_t *_data, length_t _length, // Expire all subscriptions / services in case of reboot if (is_reboot(_sender, _destination, its_message->get_reboot_flag(), its_message->get_session())) { + VSOMEIP_INFO << "Reboot detected: IP=" << _sender.to_string(); host_->expire_subscriptions(_sender); host_->expire_services(_sender); host_->on_reboot(_sender); diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 41f253a..fde4c84 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -840,6 +840,30 @@ if(NOT ${TESTS_BAT}) ) # Copy config file for client and service into $BUILDDIR/test + set(TEST_EXTERNAL_BIG_PAYLOAD_CLIENT_CONFIG_FILE_LIMITED ${TEST_BIG_PAYLOAD_NAME}_tcp_client_limited_general.json) + configure_file( + ${PROJECT_SOURCE_DIR}/test/big_payload_tests/conf/${TEST_EXTERNAL_BIG_PAYLOAD_CLIENT_CONFIG_FILE_LIMITED}.in + ${PROJECT_SOURCE_DIR}/test/big_payload_tests/${TEST_EXTERNAL_BIG_PAYLOAD_CLIENT_CONFIG_FILE_LIMITED} + @ONLY) + copy_to_builddir( + ${PROJECT_SOURCE_DIR}/test/big_payload_tests/${TEST_EXTERNAL_BIG_PAYLOAD_CLIENT_CONFIG_FILE_LIMITED} + ${PROJECT_BINARY_DIR}/test/${TEST_EXTERNAL_BIG_PAYLOAD_CLIENT_CONFIG_FILE_LIMITED} + ${TEST_BIG_PAYLOAD_CLIENT} + ) + + # Copy config file for client and service into $BUILDDIR/test + set(TEST_EXTERNAL_BIG_PAYLOAD_SERVICE_CONFIG_FILE_LIMITED ${TEST_BIG_PAYLOAD_NAME}_tcp_service_limited_general.json) + configure_file( + ${PROJECT_SOURCE_DIR}/test/big_payload_tests/conf/${TEST_EXTERNAL_BIG_PAYLOAD_SERVICE_CONFIG_FILE_LIMITED}.in + ${PROJECT_SOURCE_DIR}/test/big_payload_tests/${TEST_EXTERNAL_BIG_PAYLOAD_SERVICE_CONFIG_FILE_LIMITED} + @ONLY) + copy_to_builddir( + ${PROJECT_SOURCE_DIR}/test/big_payload_tests/${TEST_EXTERNAL_BIG_PAYLOAD_SERVICE_CONFIG_FILE_LIMITED} + ${PROJECT_BINARY_DIR}/test/${TEST_EXTERNAL_BIG_PAYLOAD_SERVICE_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_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 @@ -891,6 +915,7 @@ if(NOT ${TESTS_BAT}) 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_NAME_LIMITED_GENERAL big_payload_test_external_limited_general) 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} @@ -1895,6 +1920,11 @@ if(NOT ${TESTS_BAT}) ) set_tests_properties(${TEST_EXTERNAL_BIG_PAYLOAD_NAME_LIMITED} PROPERTIES TIMEOUT 120) + add_test(NAME ${TEST_EXTERNAL_BIG_PAYLOAD_NAME_LIMITED_GENERAL} + COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_EXTERNAL_BIG_PAYLOAD_STARTER} LIMITEDGENERAL + ) + set_tests_properties(${TEST_EXTERNAL_BIG_PAYLOAD_NAME_LIMITED_GENERAL} PROPERTIES TIMEOUT 120) + # 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}) diff --git a/test/big_payload_tests/big_payload_test_client.cpp b/test/big_payload_tests/big_payload_test_client.cpp index f4b9128..6264836 100644 --- a/test/big_payload_tests/big_payload_test_client.cpp +++ b/test/big_payload_tests/big_payload_test_client.cpp @@ -28,6 +28,9 @@ big_payload_test_client::big_payload_test_client( case big_payload_test::test_mode::LIMITED: service_id_ = big_payload_test::TEST_SERVICE_SERVICE_ID_LIMITED; break; + case big_payload_test::test_mode::LIMITED_GENERAL: + service_id_ = big_payload_test::TEST_SERVICE_SERVICE_ID_LIMITED_GENERAL; + break; default: service_id_ = big_payload_test::TEST_SERVICE_SERVICE_ID; break; @@ -67,7 +70,8 @@ void big_payload_test_client::start() void big_payload_test_client::stop() { VSOMEIP_INFO << "Stopping..."; - if (test_mode_ == big_payload_test::test_mode::LIMITED) { + if (test_mode_ == big_payload_test::test_mode::LIMITED + || test_mode_ == big_payload_test::test_mode::LIMITED_GENERAL) { std::this_thread::sleep_for(std::chrono::milliseconds(3000)); ASSERT_EQ(number_of_acknowledged_messages_, number_of_messages_to_send_ / 4); } @@ -77,7 +81,8 @@ void big_payload_test_client::stop() void big_payload_test_client::join_sender_thread(){ sender_.join(); - if (test_mode_ == big_payload_test::test_mode::LIMITED) { + if (test_mode_ == big_payload_test::test_mode::LIMITED + || test_mode_ == big_payload_test::test_mode::LIMITED_GENERAL) { ASSERT_EQ(number_of_acknowledged_messages_, number_of_messages_to_send_ / 4); } else { ASSERT_EQ(number_of_sent_messages_, number_of_acknowledged_messages_); @@ -144,7 +149,8 @@ void big_payload_test_client::on_message(const std::shared_ptr<vsomeip::message> GTEST_FATAL_FAILURE_("wrong data transmitted"); } number_of_acknowledged_messages_++; - if (test_mode_ == big_payload_test::test_mode::LIMITED) { + if (test_mode_ == big_payload_test::test_mode::LIMITED + || test_mode_ == big_payload_test::test_mode::LIMITED_GENERAL) { if (number_of_acknowledged_messages_ == number_of_messages_to_send_ / 4) { send(); } @@ -184,7 +190,8 @@ void big_payload_test_client::run() 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) { + } else if (test_mode_ == big_payload_test::test_mode::LIMITED + || test_mode_ == big_payload_test::test_mode::LIMITED_GENERAL) { 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, @@ -215,7 +222,8 @@ void big_payload_test_client::run() == 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) { + if (test_mode_ == big_payload_test::LIMITED + || test_mode_ == big_payload_test::test_mode::LIMITED_GENERAL) { ASSERT_EQ(number_of_messages_to_send_ / 4, number_of_acknowledged_messages_); } else { @@ -248,6 +256,8 @@ int main(int argc, char** argv) 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; + } else if (std::string("LIMITEDGENERAL") == std::string(argv[1])) { + test_mode = big_payload_test::test_mode::LIMITED_GENERAL; } } return RUN_ALL_TESTS(); 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 ff5a33f..f76da1c 100755 --- a/test/big_payload_tests/big_payload_test_external_starter.sh +++ b/test/big_payload_tests/big_payload_test_external_starter.sh @@ -10,9 +10,9 @@ # 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" ]] +if [[ $# -gt 0 && $1 != "RANDOM" && $1 != "LIMITED" && $1 != "LIMITEDGENERAL" ]] then - echo "The only allowed parameter to this script is RANDOM or LIMITED." + echo "The only allowed parameter to this script is RANDOM or LIMITED or LIMITEDGENERAL." echo "Like $0 RANDOM" exit 1 fi @@ -20,9 +20,10 @@ fi FAIL=0 # Start the client -if [[ $# -gt 0 && $1 == "RANDOM" ]] -then +if [[ $# -gt 0 && $1 == "RANDOM" ]]; then export VSOMEIP_CONFIGURATION=big_payload_test_tcp_client_random.json +elif [[ $# -gt 0 && $1 == "LIMITEDGENERAL" ]]; then + export VSOMEIP_CONFIGURATION=big_payload_test_tcp_client_limited_general.json else export VSOMEIP_CONFIGURATION=big_payload_test_tcp_client.json fi diff --git a/test/big_payload_tests/big_payload_test_globals.hpp b/test/big_payload_tests/big_payload_test_globals.hpp index 7d11035..152217d 100644 --- a/test/big_payload_tests/big_payload_test_globals.hpp +++ b/test/big_payload_tests/big_payload_test_globals.hpp @@ -20,6 +20,7 @@ namespace big_payload_test { 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_SERVICE_ID_LIMITED_GENERAL = 0x1237; constexpr vsomeip::service_t TEST_SERVICE_INSTANCE_ID = 0x1; constexpr vsomeip::method_t TEST_SERVICE_METHOD_ID = 0x8421; @@ -27,6 +28,7 @@ namespace big_payload_test { enum test_mode { RANDOM, LIMITED, + LIMITED_GENERAL, UNKNOWN }; } diff --git a/test/big_payload_tests/big_payload_test_service.cpp b/test/big_payload_tests/big_payload_test_service.cpp index 00f7daf..34b2d85 100644 --- a/test/big_payload_tests/big_payload_test_service.cpp +++ b/test/big_payload_tests/big_payload_test_service.cpp @@ -24,6 +24,10 @@ big_payload_test_service::big_payload_test_service(big_payload_test::test_mode _ expected_messages_ = big_payload_test::BIG_PAYLOAD_TEST_NUMBER_MESSAGES / 2; service_id_ = big_payload_test::TEST_SERVICE_SERVICE_ID_LIMITED; break; + case big_payload_test::test_mode::LIMITED_GENERAL: + expected_messages_ = big_payload_test::BIG_PAYLOAD_TEST_NUMBER_MESSAGES / 2; + service_id_ = big_payload_test::TEST_SERVICE_SERVICE_ID_LIMITED_GENERAL; + break; default: expected_messages_ = big_payload_test::BIG_PAYLOAD_TEST_NUMBER_MESSAGES; service_id_ = big_payload_test::TEST_SERVICE_SERVICE_ID; @@ -141,7 +145,8 @@ void big_payload_test_service::on_message(const std::shared_ptr<vsomeip::message 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) { + } else if (test_mode_ == big_payload_test::test_mode::LIMITED + || test_mode_ == big_payload_test::test_mode::LIMITED_GENERAL) { 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 @@ -188,7 +193,8 @@ void big_payload_test_service::run() } } std::this_thread::sleep_for(std::chrono::seconds(3)); - if (test_mode_ == big_payload_test::test_mode::LIMITED) { + if (test_mode_ == big_payload_test::test_mode::LIMITED + || test_mode_ == big_payload_test::test_mode::LIMITED_GENERAL) { ASSERT_EQ(number_of_received_messages_, expected_messages_); } stop(); @@ -215,6 +221,8 @@ int main(int argc, char** argv) 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; + } else if (std::string("LIMITEDGENERAL") == std::string(argv[1])) { + test_mode = big_payload_test::test_mode::LIMITED_GENERAL; } } return RUN_ALL_TESTS(); 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 2b4d2d7..22dd4df 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,17 +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" ]] +if [[ $# -gt 0 && $1 != "RANDOM" && $1 != "LIMITED" && $1 != "LIMITEDGENERAL" ]] then - echo "The only allowed parameter to this script is RANDOM or LIMITED." + echo "The only allowed parameter to this script is RANDOM or LIMITED or LIMITEDGENERAL." echo "Like $0 RANDOM" exit 1 fi # Start the service -if [[ $# -gt 0 && $1 == "RANDOM" ]] -then +if [[ $# -gt 0 && $1 == "RANDOM" ]]; then export VSOMEIP_CONFIGURATION=big_payload_test_tcp_service_random.json +elif [[ $# -gt 0 && $1 == "LIMITEDGENERAL" ]]; then + export VSOMEIP_CONFIGURATION=big_payload_test_tcp_service_limited_general.json else export VSOMEIP_CONFIGURATION=big_payload_test_tcp_service.json fi diff --git a/test/big_payload_tests/conf/big_payload_test_tcp_client_limited_general.json.in b/test/big_payload_tests/conf/big_payload_test_tcp_client_limited_general.json.in new file mode 100644 index 0000000..f28efc8 --- /dev/null +++ b/test/big_payload_tests/conf/big_payload_test_tcp_client_limited_general.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" + } + ], + "max-payload-size-reliable":"614400", + "routing":"big_payload_test_client", + "service-discovery": + { + "enable":"true", + "multicast":"224.244.224.245", + "port":"30490", + "protocol":"udp" + } +} diff --git a/test/big_payload_tests/conf/big_payload_test_tcp_service.json.in b/test/big_payload_tests/conf/big_payload_test_tcp_service.json.in index c17c688..08149bb 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 @@ -46,6 +46,15 @@ "port":"30509", "enable-magic-cookies":"false" } + }, + { + "service":"0x1237", + "instance":"0x01", + "reliable": + { + "port":"30509", + "enable-magic-cookies":"false" + } } ], "payload-sizes": diff --git a/test/big_payload_tests/conf/big_payload_test_tcp_service_limited_general.json.in b/test/big_payload_tests/conf/big_payload_test_tcp_service_limited_general.json.in new file mode 100644 index 0000000..f8414f3 --- /dev/null +++ b/test/big_payload_tests/conf/big_payload_test_tcp_service_limited_general.json.in @@ -0,0 +1,69 @@ +{ + "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" + } + }, + { + "service":"0x1237", + "instance":"0x01", + "reliable": + { + "port":"30509", + "enable-magic-cookies":"false" + } + } + ], + "max-payload-size-reliable":"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/conf/big_payload_test_tcp_service_random.json.in b/test/big_payload_tests/conf/big_payload_test_tcp_service_random.json.in index 56613e3..d583fd1 100644 --- 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 @@ -47,6 +47,15 @@ "port":"30509", "enable-magic-cookies":"false" } + }, + { + "service":"0x1237", + "instance":"0x01", + "reliable": + { + "port":"30509", + "enable-magic-cookies":"false" + } } ], "buffer-shrink-threshold" : "2", diff --git a/test/configuration_tests/configuration-test-deprecated.json b/test/configuration_tests/configuration-test-deprecated.json index 09a2e7e..87f3279 100644 --- a/test/configuration_tests/configuration-test-deprecated.json +++ b/test/configuration_tests/configuration-test-deprecated.json @@ -122,6 +122,32 @@ ] } ], + "max-payload-size-local" : "15000", + "max-payload-size-reliable" : "17000", + "buffer-shrink-threshold" : "11", + "payload-sizes": + [ + { + "unicast":"10.10.10.10", + "ports": + [ + { + "port":"7777", + "max-payload-size":"14999" + } + ] + }, + { + "unicast":"10.10.10.11", + "ports": + [ + { + "port":"7778", + "max-payload-size":"15001" + } + ] + } + ], "routing" : "my_application", "service-discovery" : { diff --git a/test/configuration_tests/configuration-test.cpp b/test/configuration_tests/configuration-test.cpp index d306c52..5eb9015 100644 --- a/test/configuration_tests/configuration-test.cpp +++ b/test/configuration_tests/configuration-test.cpp @@ -236,6 +236,19 @@ void check_file(const std::string &_config_file, _expected_unreliable_port_4466_0321, "UNRELIABLE_PORT_4466_0321"); + // payload sizes + // use 17000 instead of 1500 as configured max-local-payload size will be + // increased to bigger max-reliable-payload-size + std::uint32_t max_local_message_size( + 17000u + 16u + + VSOMEIP_COMMAND_HEADER_SIZE + + sizeof(vsomeip::instance_t) + sizeof(bool) + sizeof(bool) + + sizeof(vsomeip::client_t)); + check<std::uint32_t>(max_local_message_size, its_configuration->get_max_message_size_local(), "max-local-message-size"); + check<std::uint32_t>(11u, its_configuration->get_buffer_shrink_threshold(), "buffer shrink threshold"); + check<std::uint32_t>(14999u + 16u, its_configuration->get_max_message_size_reliable("10.10.10.10", 7777), "max-message-size-reliable1"); + check<std::uint32_t>(17000u + 16, its_configuration->get_max_message_size_reliable("11.11.11.11", 4711), "max-message-size-reliable2"); + check<std::uint32_t>(15001u + 16, its_configuration->get_max_message_size_reliable("10.10.10.11", 7778), "max-message-size-reliable3"); + // 6. Service discovery bool enabled = its_configuration->is_sd_enabled(); std::string protocol = its_configuration->get_sd_protocol(); diff --git a/test/configuration_tests/configuration-test.json b/test/configuration_tests/configuration-test.json index 499dbc9..afa3c41 100644 --- a/test/configuration_tests/configuration-test.json +++ b/test/configuration_tests/configuration-test.json @@ -85,6 +85,32 @@ "unreliable" : "30444" } ], + "max-payload-size-local" : "15000", + "max-payload-size-reliable" : "17000", + "buffer-shrink-threshold" : "11", + "payload-sizes": + [ + { + "unicast":"10.10.10.10", + "ports": + [ + { + "port":"7777", + "max-payload-size":"14999" + } + ] + }, + { + "unicast":"10.10.10.11", + "ports": + [ + { + "port":"7778", + "max-payload-size":"15001" + } + ] + } + ], "routing" : "my_application", "service-discovery" : { |